From d84612c9264ddc8ab69033708ab4721051d30ff4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kim=20Harjam=C3=A4ki?= Date: Fri, 3 Jul 2026 14:02:23 +0300 Subject: [PATCH 1/3] fix(audit): resolve linting and formatting errors --- autogen_dashboard/session_runner.py | 3 --- maf_starter/provider_fallback.py | 2 +- maf_starter/routing_policy.py | 2 +- maf_starter/team_factory.py | 2 +- tests/test_loop_workers.py | 9 ++++++--- tests/test_phase1_api.py | 2 +- tests/test_phase3_specialists.py | 1 - tests/test_phase7_e2e.py | 3 +-- tests/test_workspace_contract.py | 1 - 9 files changed, 11 insertions(+), 14 deletions(-) diff --git a/autogen_dashboard/session_runner.py b/autogen_dashboard/session_runner.py index 17c7239..8dabbb5 100644 --- a/autogen_dashboard/session_runner.py +++ b/autogen_dashboard/session_runner.py @@ -43,7 +43,6 @@ from autogen_starter.config import Settings from autogen_starter.providers import ProviderConfigError, collect_provider_statuses, create_model_client from maf_starter.approval_policy import ( - ApprovalScope, classify_validation_commands, classify_write_operations, is_execution_approved, @@ -54,8 +53,6 @@ AutoAnswerRecord, RunOrchestrationState, RunStagePauseKind, - SpecialistHandoff, - SpecialistState, StageName, StageSummary, specialist_role_for_stage, diff --git a/maf_starter/provider_fallback.py b/maf_starter/provider_fallback.py index 11752bd..758b1ec 100644 --- a/maf_starter/provider_fallback.py +++ b/maf_starter/provider_fallback.py @@ -65,7 +65,7 @@ async def get_final_response(self): AnthropicClient = None from maf_starter.config import Settings, activate_run_scope, reset_run_scope -from maf_starter.execution_profile import CLOUD_SAFE_PROFILE, LOCAL_PROFILE, ExecutionProfile +from maf_starter.execution_profile import LOCAL_PROFILE, ExecutionProfile from maf_starter.routing_policy import RoutingPlan, build_routing_plan from maf_starter.routing_types import CapabilityChange, ChainStep, RouteAttempt diff --git a/maf_starter/routing_policy.py b/maf_starter/routing_policy.py index a504fa3..9a55749 100644 --- a/maf_starter/routing_policy.py +++ b/maf_starter/routing_policy.py @@ -6,7 +6,7 @@ from agent_framework import Message from maf_starter.config import Settings -from maf_starter.routing_types import CapabilityChange, ChainStep, RouteAttempt, RouteLane, parse_chain_steps +from maf_starter.routing_types import CapabilityChange, ChainStep, RouteAttempt, RouteLane SIMPLE_KEYWORDS = ( diff --git a/maf_starter/team_factory.py b/maf_starter/team_factory.py index d68a53c..8e5e903 100644 --- a/maf_starter/team_factory.py +++ b/maf_starter/team_factory.py @@ -4,7 +4,7 @@ from agent_framework import WorkflowBuilder -from maf_starter.agent_factory import build_agent, build_agent_for_model +from maf_starter.agent_factory import build_agent_for_model from maf_starter.config import Settings, load_settings from maf_starter.orchestration import ( CANONICAL_STAGE_NAMES, diff --git a/tests/test_loop_workers.py b/tests/test_loop_workers.py index 3e7b89b..aebec48 100644 --- a/tests/test_loop_workers.py +++ b/tests/test_loop_workers.py @@ -72,10 +72,13 @@ def __init__(self) -> None: self.fan_out = None self.fan_in = None def add_fan_out_edges(self, source, targets): - self.fan_out = (source, tuple(targets)); return self + self.fan_out = (source, tuple(targets)) + return self def add_fan_in_edges(self, sources, target): - self.fan_in = (tuple(sources), target); return self - def build(self): return self + self.fan_in = (tuple(sources), target) + return self + def build(self): + return self builder = BuilderSpy() result = build_maf_fanout_workflow("dispatcher", [1, 2, 3, 4], "aggregator", builder=builder) diff --git a/tests/test_phase1_api.py b/tests/test_phase1_api.py index 4063ad0..4173edf 100644 --- a/tests/test_phase1_api.py +++ b/tests/test_phase1_api.py @@ -7,7 +7,7 @@ from autogen_dashboard.app import create_app from autogen_dashboard.dependencies import get_session_service -from autogen_dashboard.schemas import RepoContext, SessionActionResponse, SessionCreateResponse, SessionDetail +from autogen_dashboard.schemas import RepoContext, SessionDetail def utc_now() -> datetime: diff --git a/tests/test_phase3_specialists.py b/tests/test_phase3_specialists.py index 8cd9137..9951fc7 100644 --- a/tests/test_phase3_specialists.py +++ b/tests/test_phase3_specialists.py @@ -1,6 +1,5 @@ from __future__ import annotations -import os import shutil import unittest import uuid diff --git a/tests/test_phase7_e2e.py b/tests/test_phase7_e2e.py index 6622902..213bc46 100644 --- a/tests/test_phase7_e2e.py +++ b/tests/test_phase7_e2e.py @@ -1,5 +1,3 @@ -from __future__ import annotations - """Phase 7 end-to-end integration tests. Validates three Phase 7 success criteria: @@ -7,6 +5,7 @@ 2. Local profile accepts all providers without raising. 3. Async dispatch via WorkerBoundary.submit_async returns run_id without blocking. """ +from __future__ import annotations import asyncio import unittest diff --git a/tests/test_workspace_contract.py b/tests/test_workspace_contract.py index 7130462..0443b3e 100644 --- a/tests/test_workspace_contract.py +++ b/tests/test_workspace_contract.py @@ -2,7 +2,6 @@ import shutil import subprocess -import tempfile import unittest import uuid from datetime import datetime, timezone From ae67cdc318b97c2eb0019767499985894d604d54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kim=20Harjam=C3=A4ki?= Date: Fri, 3 Jul 2026 17:56:53 +0300 Subject: [PATCH 2/3] test(contracts): add consumer-side contract-compatibility gate Pins cas-contracts v1.1.0 and validates the SDLC wire payload in CI. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/ci.yml | 6 + requirements.txt | 1 + .../cas-contracts/v1.1.0/common.schema.json | 103 +++++++++ .../cas-contracts/v1.1.0/manifest.json | 35 ++++ .../phase-execution-request.schema.json | 35 ++++ .../v1.1.0/phase-execution-result.schema.json | 27 +++ .../phase-verification-result.schema.json | 27 +++ .../v1.1.0/sdlc-lifecycle-event.schema.json | 23 ++ .../v1.1.0/sdlc-profile.schema.json | 67 ++++++ tests/test_contract_compatibility.py | 198 ++++++++++++++++++ 10 files changed, 522 insertions(+) create mode 100644 tests/contracts/cas-contracts/v1.1.0/common.schema.json create mode 100644 tests/contracts/cas-contracts/v1.1.0/manifest.json create mode 100644 tests/contracts/cas-contracts/v1.1.0/phase-execution-request.schema.json create mode 100644 tests/contracts/cas-contracts/v1.1.0/phase-execution-result.schema.json create mode 100644 tests/contracts/cas-contracts/v1.1.0/phase-verification-result.schema.json create mode 100644 tests/contracts/cas-contracts/v1.1.0/sdlc-lifecycle-event.schema.json create mode 100644 tests/contracts/cas-contracts/v1.1.0/sdlc-profile.schema.json create mode 100644 tests/test_contract_compatibility.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b13aa8d..2f13bd6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,6 +38,12 @@ jobs: - name: Verify dependency consistency run: python -m pip check + - name: Contract compatibility (pinned cas-contracts v1.1) + # Consumer-side gate: fails red if autogen's pinned CAS contract version + # or the vendored v1.1 schema release drifts. See + # tests/test_contract_compatibility.py for the validated contract surface. + run: python -m pytest tests/test_contract_compatibility.py -q --tb=short + - name: Run full test suite run: python -m pytest -q --tb=short diff --git a/requirements.txt b/requirements.txt index d1bfa6f..8856013 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,6 +5,7 @@ autogen-agentchat>=0.7.5,<0.8.0 autogen-core>=0.7.5,<0.8.0 autogen-ext[anthropic,ollama,openai]>=0.7.5,<0.8.0 fastapi>=0.115,<1.0 +jsonschema>=4.23,<5.0 openapi-spec-validator>=0.7,<1.0 pydantic>=2.0,<3.0 pytest>=8.0,<10.0 diff --git a/tests/contracts/cas-contracts/v1.1.0/common.schema.json b/tests/contracts/cas-contracts/v1.1.0/common.schema.json new file mode 100644 index 0000000..b23a790 --- /dev/null +++ b/tests/contracts/cas-contracts/v1.1.0/common.schema.json @@ -0,0 +1,103 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.coding-autopilot.dev/v1.1/common.schema.json", + "title": "CAS Common Definitions v1.1", + "$defs": { + "actor": { + "type": "object", + "additionalProperties": false, + "required": ["id", "type"], + "properties": { + "id": { "type": "string", "minLength": 1, "maxLength": 256 }, + "type": { + "type": "string", + "enum": ["human", "agent", "service", "workflow"] + }, + "displayName": { "type": "string", "minLength": 1, "maxLength": 256 } + } + }, + "traceContext": { + "type": "object", + "additionalProperties": false, + "required": ["traceparent"], + "properties": { + "traceparent": { + "type": "string", + "pattern": "^[\\da-f]{2}-[\\da-f]{32}-[\\da-f]{16}-[\\da-f]{2}$" + }, + "tracestate": { "type": "string", "maxLength": 512 } + } + }, + "lifecycleMetadata": { + "type": "object", + "required": [ + "correlationId", + "promptId", + "runId", + "repo", + "actor", + "timestamp", + "schemaVersion", + "traceContext" + ], + "properties": { + "correlationId": { "type": "string", "minLength": 1, "maxLength": 128 }, + "promptId": { "type": "string", "minLength": 1, "maxLength": 128 }, + "runId": { "type": "string", "minLength": 1, "maxLength": 128 }, + "repo": { + "type": "string", + "pattern": "^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$" + }, + "actor": { "$ref": "#/$defs/actor" }, + "timestamp": { "type": "string", "format": "date-time" }, + "schemaVersion": { "const": "1.1.0" }, + "traceContext": { "$ref": "#/$defs/traceContext" } + } + }, + "evidence": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "uri"], + "properties": { + "kind": { "type": "string", "minLength": 1, "maxLength": 64 }, + "uri": { "type": "string", "format": "uri" }, + "sha256": { "type": "string", "pattern": "^[\\da-f]{64}$" } + } + }, + "phaseId": { + "type": "string", + "enum": [ + "understand", + "research", + "analyze", + "plan", + "risk-assessment", + "implement", + "verify", + "review", + "improve", + "document", + "update-memory", + "finished" + ] + }, + "executionBatch": { + "type": "string", + "enum": ["discovery", "design", "change", "assurance", "closure"] + }, + "phaseStatus": { + "type": "string", + "enum": [ + "pending", + "ready", + "running", + "passed", + "failed", + "invalidated", + "rolled-back", + "waiting", + "terminal" + ] + } + } +} diff --git a/tests/contracts/cas-contracts/v1.1.0/manifest.json b/tests/contracts/cas-contracts/v1.1.0/manifest.json new file mode 100644 index 0000000..c0bd518 --- /dev/null +++ b/tests/contracts/cas-contracts/v1.1.0/manifest.json @@ -0,0 +1,35 @@ +{ + "version": "1.1.0", + "schemas": [ + { + "id": "https://schemas.coding-autopilot.dev/v1.1/common.schema.json", + "path": "common.schema.json", + "sha256": "078026d60c219658fe0fc5cf7c4f786acdcf0c492121f7d688d5078b33ca25af" + }, + { + "id": "https://schemas.coding-autopilot.dev/v1.1/phase-execution-request.schema.json", + "path": "phase-execution-request.schema.json", + "sha256": "927ffda5ba809e58627ba25b3275355644b510b0ae1c76f446aa7b7f291f08fd" + }, + { + "id": "https://schemas.coding-autopilot.dev/v1.1/phase-execution-result.schema.json", + "path": "phase-execution-result.schema.json", + "sha256": "1d353e20cf6338c2de4a9bec0bad83ca0dec6c9feb5434c5e6264fdc075e7c25" + }, + { + "id": "https://schemas.coding-autopilot.dev/v1.1/phase-verification-result.schema.json", + "path": "phase-verification-result.schema.json", + "sha256": "ec5b97a2bf75892530442f666d23a8b6dbb8f13bda0efe49553d3f64cd41b995" + }, + { + "id": "https://schemas.coding-autopilot.dev/v1.1/sdlc-lifecycle-event.schema.json", + "path": "sdlc-lifecycle-event.schema.json", + "sha256": "bd955637761679d3b6e8ee09fb7b693b1d0362615b0865204c5ae3bacb3809dc" + }, + { + "id": "https://schemas.coding-autopilot.dev/v1.1/sdlc-profile.schema.json", + "path": "sdlc-profile.schema.json", + "sha256": "f4974e911e7cb88191c1a331470c8cd7a79d1c7311c963dd70cd9c8f524ebe45" + } + ] +} diff --git a/tests/contracts/cas-contracts/v1.1.0/phase-execution-request.schema.json b/tests/contracts/cas-contracts/v1.1.0/phase-execution-request.schema.json new file mode 100644 index 0000000..e7ad5a8 --- /dev/null +++ b/tests/contracts/cas-contracts/v1.1.0/phase-execution-request.schema.json @@ -0,0 +1,35 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.coding-autopilot.dev/v1.1/phase-execution-request.schema.json", + "title": "PhaseExecutionRequest", + "type": "object", + "allOf": [ + { "$ref": "common.schema.json#/$defs/lifecycleMetadata" }, + { + "type": "object", + "required": ["kind", "profileVersion", "phase", "batch", "goal", "constraints"], + "properties": { + "kind": { "const": "PhaseExecutionRequest" }, + "profileVersion": { "type": "string", "const": "v1.1" }, + "phase": { "$ref": "common.schema.json#/$defs/phaseId" }, + "batch": { "$ref": "common.schema.json#/$defs/executionBatch" }, + "goal": { "type": "string", "minLength": 1, "maxLength": 5000 }, + "constraints": { + "type": "array", + "items": { "type": "string", "minLength": 1, "maxLength": 1000 } + }, + "validatedInputs": { "type": "array", "items": { "type": "string" } }, + "priorEvidence": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/evidence" } }, + "requiredOutputSchema": { "type": "string", "minLength": 1, "maxLength": 256 }, + "requiredArtifacts": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 256 } }, + "successCriteria": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 1000 } }, + "verifier": { "type": "string", "minLength": 1, "maxLength": 256 }, + "failureBehavior": { "type": "string", "minLength": 1, "maxLength": 5000 }, + "rollbackBehavior": { "type": "string", "minLength": 1, "maxLength": 5000 }, + "memoryCandidateFields": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 256 } }, + "humanEscalationConditions": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 1000 } } + } + } + ], + "unevaluatedProperties": false +} diff --git a/tests/contracts/cas-contracts/v1.1.0/phase-execution-result.schema.json b/tests/contracts/cas-contracts/v1.1.0/phase-execution-result.schema.json new file mode 100644 index 0000000..5aa2623 --- /dev/null +++ b/tests/contracts/cas-contracts/v1.1.0/phase-execution-result.schema.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.coding-autopilot.dev/v1.1/phase-execution-result.schema.json", + "title": "PhaseExecutionResult", + "type": "object", + "allOf": [ + { "$ref": "common.schema.json#/$defs/lifecycleMetadata" }, + { + "type": "object", + "required": ["kind", "phase", "status", "promptDigest"], + "properties": { + "kind": { "const": "PhaseExecutionResult" }, + "phase": { "$ref": "common.schema.json#/$defs/phaseId" }, + "batch": { "$ref": "common.schema.json#/$defs/executionBatch" }, + "status": { "$ref": "common.schema.json#/$defs/phaseStatus" }, + "promptDigest": { "type": "string", "pattern": "^[\\da-f]{64}$" }, + "artifacts": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/evidence" } }, + "output": { "type": "object" }, + "promptMetadata": { "type": "object" }, + "sanitizedPrompt": { "type": "string", "maxLength": 50000 }, + "verifier": { "type": "string", "minLength": 1, "maxLength": 256 }, + "checkpoint": { "type": "string", "minLength": 1, "maxLength": 256 } + } + } + ], + "unevaluatedProperties": false +} diff --git a/tests/contracts/cas-contracts/v1.1.0/phase-verification-result.schema.json b/tests/contracts/cas-contracts/v1.1.0/phase-verification-result.schema.json new file mode 100644 index 0000000..083d947 --- /dev/null +++ b/tests/contracts/cas-contracts/v1.1.0/phase-verification-result.schema.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.coding-autopilot.dev/v1.1/phase-verification-result.schema.json", + "title": "PhaseVerificationResult", + "type": "object", + "allOf": [ + { "$ref": "common.schema.json#/$defs/lifecycleMetadata" }, + { + "type": "object", + "required": ["kind", "phase", "verifier", "outcome"], + "properties": { + "kind": { "const": "PhaseVerificationResult" }, + "phase": { "$ref": "common.schema.json#/$defs/phaseId" }, + "verifier": { "type": "string", "minLength": 1, "maxLength": 256 }, + "outcome": { "enum": ["passed", "failed", "inconclusive"] }, + "invalidatedPhaseIds": { + "type": "array", + "items": { "$ref": "common.schema.json#/$defs/phaseId" }, + "uniqueItems": true + }, + "evidence": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/evidence" } }, + "reason": { "type": "string", "maxLength": 5000 } + } + } + ], + "unevaluatedProperties": false +} diff --git a/tests/contracts/cas-contracts/v1.1.0/sdlc-lifecycle-event.schema.json b/tests/contracts/cas-contracts/v1.1.0/sdlc-lifecycle-event.schema.json new file mode 100644 index 0000000..b062c81 --- /dev/null +++ b/tests/contracts/cas-contracts/v1.1.0/sdlc-lifecycle-event.schema.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.coding-autopilot.dev/v1.1/sdlc-lifecycle-event.schema.json", + "title": "SdlcLifecycleEvent", + "type": "object", + "allOf": [ + { "$ref": "common.schema.json#/$defs/lifecycleMetadata" }, + { + "type": "object", + "required": ["kind", "eventType", "phase"], + "properties": { + "kind": { "const": "SdlcLifecycleEvent" }, + "eventType": { "type": "string", "minLength": 1, "maxLength": 128 }, + "phase": { "$ref": "common.schema.json#/$defs/phaseId" }, + "batch": { "$ref": "common.schema.json#/$defs/executionBatch" }, + "status": { "$ref": "common.schema.json#/$defs/phaseStatus" }, + "message": { "type": "string", "maxLength": 5000 }, + "evidence": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/evidence" } } + } + } + ], + "unevaluatedProperties": false +} diff --git a/tests/contracts/cas-contracts/v1.1.0/sdlc-profile.schema.json b/tests/contracts/cas-contracts/v1.1.0/sdlc-profile.schema.json new file mode 100644 index 0000000..d9dbd62 --- /dev/null +++ b/tests/contracts/cas-contracts/v1.1.0/sdlc-profile.schema.json @@ -0,0 +1,67 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.coding-autopilot.dev/v1.1/sdlc-profile.schema.json", + "title": "SdlcProfile", + "type": "object", + "allOf": [ + { "$ref": "common.schema.json#/$defs/lifecycleMetadata" }, + { + "type": "object", + "required": ["kind", "profileId", "profileVersion", "phases", "goalBudget"], + "properties": { + "kind": { "const": "SdlcProfile" }, + "profileId": { "type": "string", "minLength": 1, "maxLength": 128 }, + "profileVersion": { "type": "string", "pattern": "^v1\\.1$" }, + "goalBudget": { "type": "integer", "minimum": 1 }, + "phases": { + "type": "array", + "minItems": 12, + "maxItems": 12, + "items": { + "type": "object", + "additionalProperties": false, + "required": ["id", "name", "batch", "dependencies", "verifier"], + "properties": { + "id": { "$ref": "common.schema.json#/$defs/phaseId" }, + "name": { "type": "string", "minLength": 1, "maxLength": 128 }, + "batch": { "$ref": "common.schema.json#/$defs/executionBatch" }, + "dependencies": { + "type": "array", + "items": { "$ref": "common.schema.json#/$defs/phaseId" }, + "uniqueItems": true + }, + "verifier": { "type": "string", "minLength": 1, "maxLength": 256 }, + "requiredArtifacts": { + "type": "array", + "items": { "type": "string", "minLength": 1, "maxLength": 256 } + }, + "successCriteria": { + "type": "array", + "minItems": 1, + "items": { "type": "string", "minLength": 1, "maxLength": 1000 } + }, + "rollbackTo": { "$ref": "common.schema.json#/$defs/phaseId" }, + "maxAttempts": { "type": "integer", "minimum": 1 } + } + } + }, + "goalAttempts": { "type": "integer", "minimum": 1 }, + "iterations": { "type": "integer", "minimum": 1 }, + "runtimeMinutes": { "type": "integer", "minimum": 1 }, + "modelCalls": { "type": "integer", "minimum": 1 }, + "noProgressLimit": { "type": "integer", "minimum": 1 }, + "repositoryOverrides": { + "type": "object", + "additionalProperties": false, + "properties": { + "promptFragments": { "type": "object" }, + "verifierCommands": { "type": "object" }, + "requiredArtifacts": { "type": "object" }, + "phaseLimits": { "type": "object" } + } + } + } + } + ], + "unevaluatedProperties": false +} diff --git a/tests/test_contract_compatibility.py b/tests/test_contract_compatibility.py new file mode 100644 index 0000000..a165d6e --- /dev/null +++ b/tests/test_contract_compatibility.py @@ -0,0 +1,198 @@ +"""Consumer-side contract-compatibility check against pinned cas-contracts schemas. + +autogen consumes the CAS v1.1 SDLC contract family. Its dashboard/session models +(``autogen_dashboard/schemas.py``) are an *internal* snake_case representation and +are intentionally NOT the wire shape. The authoritative wire shape is the camelCase +JSON Schema published by ``cas-contracts`` at ``v1.1`` (schemaVersion ``1.1.0``). + +This module pins the contract version autogen targets and fails CI (red check) when: + +* the pinned ``schemaVersion`` / ``profileVersion`` autogen emits no longer matches + the vendored cas-contracts release, +* the vendored schema release has been tampered with (manifest SHA-256 drift), or +* a representative wire payload for each contract autogen produces/consumes stops + validating against the pinned schema. + +Cross-repo reference note: cas-contracts is a *separate* repo. In this local polyrepo +CI checks out only this repo, so we vendor the pinned ``v1.1.0`` release under +``tests/contracts/cas-contracts/v1.1.0/`` (same convention as cas-reference-product). +When the sibling ``../../cas-contracts`` checkout is present (local dev), we additionally +assert the vendored copy has not drifted from the upstream source of truth. +""" + +from __future__ import annotations + +import hashlib +import json +from pathlib import Path +from typing import Any + +import pytest + +jsonschema = pytest.importorskip("jsonschema") +referencing = pytest.importorskip("referencing") +from jsonschema import Draft202012Validator # noqa: E402 +from referencing import Registry, Resource # noqa: E402 + +# The contract version autogen's models pin themselves to. These MUST stay in lockstep +# with autogen_dashboard/schemas.py (SdlcProfileModel.profile_version, the various +# kind/profile_version literals) and with the vendored release below. +PINNED_SCHEMA_VERSION = "1.1.0" +PINNED_PROFILE_VERSION = "v1.1" + +CONTRACT_ROOT = Path(__file__).parent / "contracts" / "cas-contracts" / f"v{PINNED_SCHEMA_VERSION}" +UPSTREAM_ROOT = ( + Path(__file__).resolve().parents[2] + / "cas-contracts" + / "registry" + / "releases" + / f"v{PINNED_SCHEMA_VERSION}" +) + + +def _load_json(path: Path) -> dict[str, Any]: + return json.loads(path.read_text(encoding="utf-8")) + + +def _registry() -> Registry[Any]: + resources = [] + for path in CONTRACT_ROOT.glob("*.schema.json"): + schema = _load_json(path) + resources.append((schema["$id"], Resource.from_contents(schema))) + return Registry().with_resources(resources) + + +def _validate(schema_name: str, instance: dict[str, Any]) -> None: + schema = _load_json(CONTRACT_ROOT / schema_name) + Draft202012Validator(schema, registry=_registry()).validate(instance) + + +# Shared lifecycle metadata every v1.1 contract requires (common.schema.json#lifecycleMetadata). +def _lifecycle() -> dict[str, Any]: + return { + "correlationId": "corr-001", + "promptId": "prompt-001", + "runId": "run-001", + "repo": "Coding-Autopilot-System/autogen", + "actor": {"id": "maf-manager", "type": "agent"}, + "timestamp": "2026-07-03T00:00:00Z", + "schemaVersion": PINNED_SCHEMA_VERSION, + "traceContext": { + "traceparent": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01" + }, + } + + +def test_vendored_release_matches_manifest_hashes() -> None: + """The vendored pinned release must be internally consistent (tamper check).""" + manifest = _load_json(CONTRACT_ROOT / "manifest.json") + assert manifest["version"] == PINNED_SCHEMA_VERSION + for entry in manifest["schemas"]: + content = (CONTRACT_ROOT / entry["path"]).read_bytes() + assert hashlib.sha256(content).hexdigest() == entry["sha256"], entry["path"] + + +def test_pinned_version_is_the_version_autogen_emits() -> None: + """autogen's models pin profileVersion v1.1 -> schemaVersion 1.1.0. + + Guards against a silent bump of the vendored release without updating the models. + """ + common = _load_json(CONTRACT_ROOT / "common.schema.json") + schema_version_const = common["$defs"]["lifecycleMetadata"]["properties"]["schemaVersion"]["const"] + assert schema_version_const == PINNED_SCHEMA_VERSION + + request = _load_json(CONTRACT_ROOT / "phase-execution-request.schema.json") + profile_version_const = ( + request["allOf"][1]["properties"]["profileVersion"]["const"] + ) + assert profile_version_const == PINNED_PROFILE_VERSION + + +def test_phase_execution_request_wire_payload_conforms() -> None: + payload = { + **_lifecycle(), + "kind": "PhaseExecutionRequest", + "profileVersion": PINNED_PROFILE_VERSION, + "phase": "implement", + "batch": "change", + "goal": "Apply the bounded change for the current work item.", + "constraints": ["No secrets", "Stay within budget"], + } + _validate("phase-execution-request.schema.json", payload) + + +def test_phase_execution_result_wire_payload_conforms() -> None: + payload = { + **_lifecycle(), + "kind": "PhaseExecutionResult", + "phase": "implement", + "batch": "change", + "status": "passed", + "promptDigest": "a" * 64, + "artifacts": [{"kind": "patch", "uri": "cas://evidence/patch/1"}], + "verifier": "mutation-owner", + } + _validate("phase-execution-result.schema.json", payload) + + +def test_phase_verification_result_wire_payload_conforms() -> None: + payload = { + **_lifecycle(), + "kind": "PhaseVerificationResult", + "phase": "verify", + "verifier": "verifier", + "outcome": "passed", + "invalidatedPhaseIds": [], + } + _validate("phase-verification-result.schema.json", payload) + + +def test_sdlc_profile_wire_payload_conforms() -> None: + # v1.1 sdlc-profile requires exactly 12 phases — the same 12 autogen models enumerate. + phase_ids = [ + "understand", "research", "analyze", "plan", "risk-assessment", "implement", + "verify", "review", "improve", "document", "update-memory", "finished", + ] + batch_for = { + "understand": "discovery", "research": "discovery", "analyze": "discovery", + "plan": "design", "risk-assessment": "design", "implement": "change", + "verify": "assurance", "review": "assurance", "improve": "assurance", + "document": "closure", "update-memory": "closure", "finished": "closure", + } + payload = { + **_lifecycle(), + "kind": "SdlcProfile", + "profileId": "cas-sdlc-v1", + "profileVersion": PINNED_PROFILE_VERSION, + "goalBudget": 17, + "phases": [ + { + "id": pid, + "name": pid.replace("-", " ").title(), + "batch": batch_for[pid], + "dependencies": [] if i == 0 else [phase_ids[i - 1]], + "verifier": "repo-verifier", + "successCriteria": ["criterion met"], + } + for i, pid in enumerate(phase_ids) + ], + } + _validate("sdlc-profile.schema.json", payload) + + +@pytest.mark.skipif( + not UPSTREAM_ROOT.exists(), + reason="sibling cas-contracts checkout not present (expected in isolated CI)", +) +def test_vendored_release_matches_upstream_source_of_truth() -> None: + """Local-only drift guard: vendored copy must equal the sibling cas-contracts release. + + Skipped automatically in isolated CI where the sibling repo is not checked out. + """ + for path in CONTRACT_ROOT.glob("*.json"): + upstream = UPSTREAM_ROOT / path.name + assert upstream.exists(), f"upstream missing {path.name}" + assert ( + hashlib.sha256(path.read_bytes()).hexdigest() + == hashlib.sha256(upstream.read_bytes()).hexdigest() + ), f"vendored {path.name} drifted from upstream cas-contracts {PINNED_SCHEMA_VERSION}" From ee503b61a846949869647e77bbd27d75f9256c5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kim=20Harjam=C3=A4ki?= Date: Fri, 3 Jul 2026 18:07:37 +0300 Subject: [PATCH 3/3] fix(contracts): re-vendor authoritative v1.1.0 schemas; pin LF via gitattributes The vendored common.schema.json content diverged from the pinned cas-contracts release manifest; the compatibility test correctly caught it. Re-vendored byte-identical from registry/releases/v1.1.0 and marked contracts as -text. Co-Authored-By: Claude Opus 4.8 --- .gitattributes | 2 + .../cas-contracts/v1.1.0/common.schema.json | 206 +++++++++--------- .../phase-execution-request.schema.json | 70 +++--- .../v1.1.0/phase-execution-result.schema.json | 54 ++--- .../phase-verification-result.schema.json | 54 ++--- .../v1.1.0/sdlc-lifecycle-event.schema.json | 46 ++-- .../v1.1.0/sdlc-profile.schema.json | 134 ++++++------ 7 files changed, 284 insertions(+), 282 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6936c48 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Vendored cas-contracts schemas are hashed byte-for-byte — store exactly, no EOL conversion. +tests/contracts/** -text diff --git a/tests/contracts/cas-contracts/v1.1.0/common.schema.json b/tests/contracts/cas-contracts/v1.1.0/common.schema.json index b23a790..60ab249 100644 --- a/tests/contracts/cas-contracts/v1.1.0/common.schema.json +++ b/tests/contracts/cas-contracts/v1.1.0/common.schema.json @@ -1,103 +1,103 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://schemas.coding-autopilot.dev/v1.1/common.schema.json", - "title": "CAS Common Definitions v1.1", - "$defs": { - "actor": { - "type": "object", - "additionalProperties": false, - "required": ["id", "type"], - "properties": { - "id": { "type": "string", "minLength": 1, "maxLength": 256 }, - "type": { - "type": "string", - "enum": ["human", "agent", "service", "workflow"] - }, - "displayName": { "type": "string", "minLength": 1, "maxLength": 256 } - } - }, - "traceContext": { - "type": "object", - "additionalProperties": false, - "required": ["traceparent"], - "properties": { - "traceparent": { - "type": "string", - "pattern": "^[\\da-f]{2}-[\\da-f]{32}-[\\da-f]{16}-[\\da-f]{2}$" - }, - "tracestate": { "type": "string", "maxLength": 512 } - } - }, - "lifecycleMetadata": { - "type": "object", - "required": [ - "correlationId", - "promptId", - "runId", - "repo", - "actor", - "timestamp", - "schemaVersion", - "traceContext" - ], - "properties": { - "correlationId": { "type": "string", "minLength": 1, "maxLength": 128 }, - "promptId": { "type": "string", "minLength": 1, "maxLength": 128 }, - "runId": { "type": "string", "minLength": 1, "maxLength": 128 }, - "repo": { - "type": "string", - "pattern": "^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$" - }, - "actor": { "$ref": "#/$defs/actor" }, - "timestamp": { "type": "string", "format": "date-time" }, - "schemaVersion": { "const": "1.1.0" }, - "traceContext": { "$ref": "#/$defs/traceContext" } - } - }, - "evidence": { - "type": "object", - "additionalProperties": false, - "required": ["kind", "uri"], - "properties": { - "kind": { "type": "string", "minLength": 1, "maxLength": 64 }, - "uri": { "type": "string", "format": "uri" }, - "sha256": { "type": "string", "pattern": "^[\\da-f]{64}$" } - } - }, - "phaseId": { - "type": "string", - "enum": [ - "understand", - "research", - "analyze", - "plan", - "risk-assessment", - "implement", - "verify", - "review", - "improve", - "document", - "update-memory", - "finished" - ] - }, - "executionBatch": { - "type": "string", - "enum": ["discovery", "design", "change", "assurance", "closure"] - }, - "phaseStatus": { - "type": "string", - "enum": [ - "pending", - "ready", - "running", - "passed", - "failed", - "invalidated", - "rolled-back", - "waiting", - "terminal" - ] - } - } -} +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.coding-autopilot.dev/v1.1/common.schema.json", + "title": "CAS Common Definitions v1.1", + "$defs": { + "actor": { + "type": "object", + "additionalProperties": false, + "required": ["id", "type"], + "properties": { + "id": { "type": "string", "minLength": 1, "maxLength": 256 }, + "type": { + "type": "string", + "enum": ["human", "agent", "service", "workflow"] + }, + "displayName": { "type": "string", "minLength": 1, "maxLength": 256 } + } + }, + "traceContext": { + "type": "object", + "additionalProperties": false, + "required": ["traceparent"], + "properties": { + "traceparent": { + "type": "string", + "pattern": "^[\\da-f]{2}-[\\da-f]{32}-[\\da-f]{16}-[\\da-f]{2}$" + }, + "tracestate": { "type": "string", "maxLength": 512 } + } + }, + "lifecycleMetadata": { + "type": "object", + "required": [ + "correlationId", + "promptId", + "runId", + "repo", + "actor", + "timestamp", + "schemaVersion", + "traceContext" + ], + "properties": { + "correlationId": { "type": "string", "minLength": 1, "maxLength": 128 }, + "promptId": { "type": "string", "minLength": 1, "maxLength": 128 }, + "runId": { "type": "string", "minLength": 1, "maxLength": 128 }, + "repo": { + "type": "string", + "pattern": "^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$" + }, + "actor": { "$ref": "#/$defs/actor" }, + "timestamp": { "type": "string", "format": "date-time" }, + "schemaVersion": { "const": "1.1.0" }, + "traceContext": { "$ref": "#/$defs/traceContext" } + } + }, + "evidence": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "uri"], + "properties": { + "kind": { "type": "string", "minLength": 1, "maxLength": 64 }, + "uri": { "type": "string", "format": "uri" }, + "sha256": { "type": "string", "pattern": "^[\\da-f]{64}$" } + } + }, + "phaseId": { + "type": "string", + "enum": [ + "understand", + "research", + "analyze", + "plan", + "risk-assessment", + "implement", + "verify", + "review", + "improve", + "document", + "update-memory", + "finished" + ] + }, + "executionBatch": { + "type": "string", + "enum": ["discovery", "design", "change", "assurance", "closure"] + }, + "phaseStatus": { + "type": "string", + "enum": [ + "pending", + "ready", + "running", + "passed", + "failed", + "invalidated", + "rolled-back", + "waiting", + "terminal" + ] + } + } +} diff --git a/tests/contracts/cas-contracts/v1.1.0/phase-execution-request.schema.json b/tests/contracts/cas-contracts/v1.1.0/phase-execution-request.schema.json index e7ad5a8..a9b9ab7 100644 --- a/tests/contracts/cas-contracts/v1.1.0/phase-execution-request.schema.json +++ b/tests/contracts/cas-contracts/v1.1.0/phase-execution-request.schema.json @@ -1,35 +1,35 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://schemas.coding-autopilot.dev/v1.1/phase-execution-request.schema.json", - "title": "PhaseExecutionRequest", - "type": "object", - "allOf": [ - { "$ref": "common.schema.json#/$defs/lifecycleMetadata" }, - { - "type": "object", - "required": ["kind", "profileVersion", "phase", "batch", "goal", "constraints"], - "properties": { - "kind": { "const": "PhaseExecutionRequest" }, - "profileVersion": { "type": "string", "const": "v1.1" }, - "phase": { "$ref": "common.schema.json#/$defs/phaseId" }, - "batch": { "$ref": "common.schema.json#/$defs/executionBatch" }, - "goal": { "type": "string", "minLength": 1, "maxLength": 5000 }, - "constraints": { - "type": "array", - "items": { "type": "string", "minLength": 1, "maxLength": 1000 } - }, - "validatedInputs": { "type": "array", "items": { "type": "string" } }, - "priorEvidence": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/evidence" } }, - "requiredOutputSchema": { "type": "string", "minLength": 1, "maxLength": 256 }, - "requiredArtifacts": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 256 } }, - "successCriteria": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 1000 } }, - "verifier": { "type": "string", "minLength": 1, "maxLength": 256 }, - "failureBehavior": { "type": "string", "minLength": 1, "maxLength": 5000 }, - "rollbackBehavior": { "type": "string", "minLength": 1, "maxLength": 5000 }, - "memoryCandidateFields": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 256 } }, - "humanEscalationConditions": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 1000 } } - } - } - ], - "unevaluatedProperties": false -} +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.coding-autopilot.dev/v1.1/phase-execution-request.schema.json", + "title": "PhaseExecutionRequest", + "type": "object", + "allOf": [ + { "$ref": "common.schema.json#/$defs/lifecycleMetadata" }, + { + "type": "object", + "required": ["kind", "profileVersion", "phase", "batch", "goal", "constraints"], + "properties": { + "kind": { "const": "PhaseExecutionRequest" }, + "profileVersion": { "type": "string", "const": "v1.1" }, + "phase": { "$ref": "common.schema.json#/$defs/phaseId" }, + "batch": { "$ref": "common.schema.json#/$defs/executionBatch" }, + "goal": { "type": "string", "minLength": 1, "maxLength": 5000 }, + "constraints": { + "type": "array", + "items": { "type": "string", "minLength": 1, "maxLength": 1000 } + }, + "validatedInputs": { "type": "array", "items": { "type": "string" } }, + "priorEvidence": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/evidence" } }, + "requiredOutputSchema": { "type": "string", "minLength": 1, "maxLength": 256 }, + "requiredArtifacts": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 256 } }, + "successCriteria": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 1000 } }, + "verifier": { "type": "string", "minLength": 1, "maxLength": 256 }, + "failureBehavior": { "type": "string", "minLength": 1, "maxLength": 5000 }, + "rollbackBehavior": { "type": "string", "minLength": 1, "maxLength": 5000 }, + "memoryCandidateFields": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 256 } }, + "humanEscalationConditions": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 1000 } } + } + } + ], + "unevaluatedProperties": false +} diff --git a/tests/contracts/cas-contracts/v1.1.0/phase-execution-result.schema.json b/tests/contracts/cas-contracts/v1.1.0/phase-execution-result.schema.json index 5aa2623..db58ea3 100644 --- a/tests/contracts/cas-contracts/v1.1.0/phase-execution-result.schema.json +++ b/tests/contracts/cas-contracts/v1.1.0/phase-execution-result.schema.json @@ -1,27 +1,27 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://schemas.coding-autopilot.dev/v1.1/phase-execution-result.schema.json", - "title": "PhaseExecutionResult", - "type": "object", - "allOf": [ - { "$ref": "common.schema.json#/$defs/lifecycleMetadata" }, - { - "type": "object", - "required": ["kind", "phase", "status", "promptDigest"], - "properties": { - "kind": { "const": "PhaseExecutionResult" }, - "phase": { "$ref": "common.schema.json#/$defs/phaseId" }, - "batch": { "$ref": "common.schema.json#/$defs/executionBatch" }, - "status": { "$ref": "common.schema.json#/$defs/phaseStatus" }, - "promptDigest": { "type": "string", "pattern": "^[\\da-f]{64}$" }, - "artifacts": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/evidence" } }, - "output": { "type": "object" }, - "promptMetadata": { "type": "object" }, - "sanitizedPrompt": { "type": "string", "maxLength": 50000 }, - "verifier": { "type": "string", "minLength": 1, "maxLength": 256 }, - "checkpoint": { "type": "string", "minLength": 1, "maxLength": 256 } - } - } - ], - "unevaluatedProperties": false -} +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.coding-autopilot.dev/v1.1/phase-execution-result.schema.json", + "title": "PhaseExecutionResult", + "type": "object", + "allOf": [ + { "$ref": "common.schema.json#/$defs/lifecycleMetadata" }, + { + "type": "object", + "required": ["kind", "phase", "status", "promptDigest"], + "properties": { + "kind": { "const": "PhaseExecutionResult" }, + "phase": { "$ref": "common.schema.json#/$defs/phaseId" }, + "batch": { "$ref": "common.schema.json#/$defs/executionBatch" }, + "status": { "$ref": "common.schema.json#/$defs/phaseStatus" }, + "promptDigest": { "type": "string", "pattern": "^[\\da-f]{64}$" }, + "artifacts": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/evidence" } }, + "output": { "type": "object" }, + "promptMetadata": { "type": "object" }, + "sanitizedPrompt": { "type": "string", "maxLength": 50000 }, + "verifier": { "type": "string", "minLength": 1, "maxLength": 256 }, + "checkpoint": { "type": "string", "minLength": 1, "maxLength": 256 } + } + } + ], + "unevaluatedProperties": false +} diff --git a/tests/contracts/cas-contracts/v1.1.0/phase-verification-result.schema.json b/tests/contracts/cas-contracts/v1.1.0/phase-verification-result.schema.json index 083d947..90b6819 100644 --- a/tests/contracts/cas-contracts/v1.1.0/phase-verification-result.schema.json +++ b/tests/contracts/cas-contracts/v1.1.0/phase-verification-result.schema.json @@ -1,27 +1,27 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://schemas.coding-autopilot.dev/v1.1/phase-verification-result.schema.json", - "title": "PhaseVerificationResult", - "type": "object", - "allOf": [ - { "$ref": "common.schema.json#/$defs/lifecycleMetadata" }, - { - "type": "object", - "required": ["kind", "phase", "verifier", "outcome"], - "properties": { - "kind": { "const": "PhaseVerificationResult" }, - "phase": { "$ref": "common.schema.json#/$defs/phaseId" }, - "verifier": { "type": "string", "minLength": 1, "maxLength": 256 }, - "outcome": { "enum": ["passed", "failed", "inconclusive"] }, - "invalidatedPhaseIds": { - "type": "array", - "items": { "$ref": "common.schema.json#/$defs/phaseId" }, - "uniqueItems": true - }, - "evidence": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/evidence" } }, - "reason": { "type": "string", "maxLength": 5000 } - } - } - ], - "unevaluatedProperties": false -} +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.coding-autopilot.dev/v1.1/phase-verification-result.schema.json", + "title": "PhaseVerificationResult", + "type": "object", + "allOf": [ + { "$ref": "common.schema.json#/$defs/lifecycleMetadata" }, + { + "type": "object", + "required": ["kind", "phase", "verifier", "outcome"], + "properties": { + "kind": { "const": "PhaseVerificationResult" }, + "phase": { "$ref": "common.schema.json#/$defs/phaseId" }, + "verifier": { "type": "string", "minLength": 1, "maxLength": 256 }, + "outcome": { "enum": ["passed", "failed", "inconclusive"] }, + "invalidatedPhaseIds": { + "type": "array", + "items": { "$ref": "common.schema.json#/$defs/phaseId" }, + "uniqueItems": true + }, + "evidence": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/evidence" } }, + "reason": { "type": "string", "maxLength": 5000 } + } + } + ], + "unevaluatedProperties": false +} diff --git a/tests/contracts/cas-contracts/v1.1.0/sdlc-lifecycle-event.schema.json b/tests/contracts/cas-contracts/v1.1.0/sdlc-lifecycle-event.schema.json index b062c81..0d7d8bf 100644 --- a/tests/contracts/cas-contracts/v1.1.0/sdlc-lifecycle-event.schema.json +++ b/tests/contracts/cas-contracts/v1.1.0/sdlc-lifecycle-event.schema.json @@ -1,23 +1,23 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://schemas.coding-autopilot.dev/v1.1/sdlc-lifecycle-event.schema.json", - "title": "SdlcLifecycleEvent", - "type": "object", - "allOf": [ - { "$ref": "common.schema.json#/$defs/lifecycleMetadata" }, - { - "type": "object", - "required": ["kind", "eventType", "phase"], - "properties": { - "kind": { "const": "SdlcLifecycleEvent" }, - "eventType": { "type": "string", "minLength": 1, "maxLength": 128 }, - "phase": { "$ref": "common.schema.json#/$defs/phaseId" }, - "batch": { "$ref": "common.schema.json#/$defs/executionBatch" }, - "status": { "$ref": "common.schema.json#/$defs/phaseStatus" }, - "message": { "type": "string", "maxLength": 5000 }, - "evidence": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/evidence" } } - } - } - ], - "unevaluatedProperties": false -} +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.coding-autopilot.dev/v1.1/sdlc-lifecycle-event.schema.json", + "title": "SdlcLifecycleEvent", + "type": "object", + "allOf": [ + { "$ref": "common.schema.json#/$defs/lifecycleMetadata" }, + { + "type": "object", + "required": ["kind", "eventType", "phase"], + "properties": { + "kind": { "const": "SdlcLifecycleEvent" }, + "eventType": { "type": "string", "minLength": 1, "maxLength": 128 }, + "phase": { "$ref": "common.schema.json#/$defs/phaseId" }, + "batch": { "$ref": "common.schema.json#/$defs/executionBatch" }, + "status": { "$ref": "common.schema.json#/$defs/phaseStatus" }, + "message": { "type": "string", "maxLength": 5000 }, + "evidence": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/evidence" } } + } + } + ], + "unevaluatedProperties": false +} diff --git a/tests/contracts/cas-contracts/v1.1.0/sdlc-profile.schema.json b/tests/contracts/cas-contracts/v1.1.0/sdlc-profile.schema.json index d9dbd62..92a0404 100644 --- a/tests/contracts/cas-contracts/v1.1.0/sdlc-profile.schema.json +++ b/tests/contracts/cas-contracts/v1.1.0/sdlc-profile.schema.json @@ -1,67 +1,67 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://schemas.coding-autopilot.dev/v1.1/sdlc-profile.schema.json", - "title": "SdlcProfile", - "type": "object", - "allOf": [ - { "$ref": "common.schema.json#/$defs/lifecycleMetadata" }, - { - "type": "object", - "required": ["kind", "profileId", "profileVersion", "phases", "goalBudget"], - "properties": { - "kind": { "const": "SdlcProfile" }, - "profileId": { "type": "string", "minLength": 1, "maxLength": 128 }, - "profileVersion": { "type": "string", "pattern": "^v1\\.1$" }, - "goalBudget": { "type": "integer", "minimum": 1 }, - "phases": { - "type": "array", - "minItems": 12, - "maxItems": 12, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["id", "name", "batch", "dependencies", "verifier"], - "properties": { - "id": { "$ref": "common.schema.json#/$defs/phaseId" }, - "name": { "type": "string", "minLength": 1, "maxLength": 128 }, - "batch": { "$ref": "common.schema.json#/$defs/executionBatch" }, - "dependencies": { - "type": "array", - "items": { "$ref": "common.schema.json#/$defs/phaseId" }, - "uniqueItems": true - }, - "verifier": { "type": "string", "minLength": 1, "maxLength": 256 }, - "requiredArtifacts": { - "type": "array", - "items": { "type": "string", "minLength": 1, "maxLength": 256 } - }, - "successCriteria": { - "type": "array", - "minItems": 1, - "items": { "type": "string", "minLength": 1, "maxLength": 1000 } - }, - "rollbackTo": { "$ref": "common.schema.json#/$defs/phaseId" }, - "maxAttempts": { "type": "integer", "minimum": 1 } - } - } - }, - "goalAttempts": { "type": "integer", "minimum": 1 }, - "iterations": { "type": "integer", "minimum": 1 }, - "runtimeMinutes": { "type": "integer", "minimum": 1 }, - "modelCalls": { "type": "integer", "minimum": 1 }, - "noProgressLimit": { "type": "integer", "minimum": 1 }, - "repositoryOverrides": { - "type": "object", - "additionalProperties": false, - "properties": { - "promptFragments": { "type": "object" }, - "verifierCommands": { "type": "object" }, - "requiredArtifacts": { "type": "object" }, - "phaseLimits": { "type": "object" } - } - } - } - } - ], - "unevaluatedProperties": false -} +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.coding-autopilot.dev/v1.1/sdlc-profile.schema.json", + "title": "SdlcProfile", + "type": "object", + "allOf": [ + { "$ref": "common.schema.json#/$defs/lifecycleMetadata" }, + { + "type": "object", + "required": ["kind", "profileId", "profileVersion", "phases", "goalBudget"], + "properties": { + "kind": { "const": "SdlcProfile" }, + "profileId": { "type": "string", "minLength": 1, "maxLength": 128 }, + "profileVersion": { "type": "string", "pattern": "^v1\\.1$" }, + "goalBudget": { "type": "integer", "minimum": 1 }, + "phases": { + "type": "array", + "minItems": 12, + "maxItems": 12, + "items": { + "type": "object", + "additionalProperties": false, + "required": ["id", "name", "batch", "dependencies", "verifier"], + "properties": { + "id": { "$ref": "common.schema.json#/$defs/phaseId" }, + "name": { "type": "string", "minLength": 1, "maxLength": 128 }, + "batch": { "$ref": "common.schema.json#/$defs/executionBatch" }, + "dependencies": { + "type": "array", + "items": { "$ref": "common.schema.json#/$defs/phaseId" }, + "uniqueItems": true + }, + "verifier": { "type": "string", "minLength": 1, "maxLength": 256 }, + "requiredArtifacts": { + "type": "array", + "items": { "type": "string", "minLength": 1, "maxLength": 256 } + }, + "successCriteria": { + "type": "array", + "minItems": 1, + "items": { "type": "string", "minLength": 1, "maxLength": 1000 } + }, + "rollbackTo": { "$ref": "common.schema.json#/$defs/phaseId" }, + "maxAttempts": { "type": "integer", "minimum": 1 } + } + } + }, + "goalAttempts": { "type": "integer", "minimum": 1 }, + "iterations": { "type": "integer", "minimum": 1 }, + "runtimeMinutes": { "type": "integer", "minimum": 1 }, + "modelCalls": { "type": "integer", "minimum": 1 }, + "noProgressLimit": { "type": "integer", "minimum": 1 }, + "repositoryOverrides": { + "type": "object", + "additionalProperties": false, + "properties": { + "promptFragments": { "type": "object" }, + "verifierCommands": { "type": "object" }, + "requiredArtifacts": { "type": "object" }, + "phaseLimits": { "type": "object" } + } + } + } + } + ], + "unevaluatedProperties": false +}