diff --git a/docs/programs/engineering-process-platform/evidence/states/program-state-revision-0078.json b/docs/programs/engineering-process-platform/evidence/states/program-state-revision-0078.json new file mode 100644 index 00000000..6f9147f6 --- /dev/null +++ b/docs/programs/engineering-process-platform/evidence/states/program-state-revision-0078.json @@ -0,0 +1,106 @@ +{ + "$schema": "https://wright.local/programs/epp/program-state.schema.json", + "schema_version": "2.0", + "program_id": "EPP-2026", + "revision": 78, + "state": "PROGRAM_ACTIVE", + "baseline": { + "ref": "dev", + "commit": "9f961d52683e0e999fe29a7fed4c1e016de29620", + "tree": "3e7c5d929d321052f9a34f629f1f023b8a88c805", + "observed_clean": true + }, + "prototype_evidence": { + "branch": "076-engineering-workflow-prototype", + "commit": "e7bb75c1d97e70e55b943e0c94a31ff85cf9f82d", + "remote_matches": true, + "registered_worktree": false, + "mode": "read_only_evidence", + "uncommitted_evidence_status": "none_detected" + }, + "control_plane": { + "root": "docs/programs/engineering-process-platform", + "candidate_subject_resolution": "EPP-F01B replacement material-change and feature-implementation approvals bind commit e83a78f86c3e53157386c105a9a3b6f495b76fd4, tree 3a584940dfca227088c02b01aa74981baa847c06, program tree 8841bc1e0116fc2dd8950dd3e974f904d09d8edc, and the 17 TR-0072 artifact digests to local tasks T001 through T048 only. Direct user authority on 2026-08-29 additionally permits the bounded registry-routing and lifecycle-limit correction independently verified at 3bb076a7355dfc3cfd6469db05b40b54462a32b0; the specialized test-result path contract and checkpoint-bound test-history correction through 1a2cebb42e4ce7b24ed48dceda6281cd39c68e02; and one deterministic packaged-browser rebuild under lease revision 5 at only src/wright_engineering/static/web/** and src/wright_engineering/runtime-extra-lock.json. TR-0074 records other already-changed candidate paths only as historical T001-T048 evidence and grants no future edit authority for them. EPP-F01B integrated through PR #115 at dev commit 9f961d52683e0e999fe29a7fed4c1e016de29620 with exact candidate tree 3e7c5d929d321052f9a34f629f1f023b8a88c805; the implementation lease is released.", + "schema_status": "passed", + "audit_status": "passed" + }, + "current_feature": "EPP-F01B", + "active_mutating_lease": null, + "last_transition": "TR-0077", + "readiness": { + "product": { + "status": "not_started", + "gate_file": "gates.md", + "blockers": [ + "No customer product child feature is implemented or implementation-approved", + "The browser-accessible program-status page is integrated program-control capability and does not by itself advance product readiness" + ] + }, + "benchmark": { + "status": "not_started", + "gate_file": "gates.md", + "blockers": [ + "No 100-process collection has been generated or qualified", + "DEC-P0-007", + "DEC-P0-009", + "DEC-P0-010", + "DEC-P0-011", + "DEC-P0-012" + ] + }, + "commercial": { + "status": "blocked", + "gate_file": "gates.md", + "blockers": [ + "DEC-P0-001", + "DEC-P0-004", + "DEC-P0-006", + "DEC-P0-011", + "DEC-P0-012", + "Repository external controls remain evidence requirements" + ] + }, + "program_health": { + "status": "blocked", + "gate_file": "gates.md", + "blockers": [ + "EPP-F01 is complete and integrated through PR #114.", + "EPP-F01B is integrated through PR #115 at dev commit 9f961d52 with exact candidate tree 3e7c5d92; development deployment verification is pending a green correction build.", + "Product, benchmark, and commercial readiness remain independent; benchmark execution remains unauthorized at 0/100 and release eligibility remains false.", + "EPP-F02 planning is in progress and implementation remains subject to an exact human approval gate." + ] + } + }, + "open_p0_decisions": [ + "DEC-P0-001", + "DEC-P0-002", + "DEC-P0-003", + "DEC-P0-004", + "DEC-P0-005", + "DEC-P0-006", + "DEC-P0-007", + "DEC-P0-008", + "DEC-P0-009", + "DEC-P0-010", + "DEC-P0-011", + "DEC-P0-012" + ], + "next_eligible_actions": [ + { + "action": "APPROVE_CURRENT_FEATURE_INTEGRATION_EVIDENCE", + "roadmap_item": "EPP-F01B", + "requires_human_approval": true, + "reason": "PR #115 is merged at exact dev commit 9f961d52 and tree 3e7c5d92, but durable dev-integration approval evidence and green post-merge deployment verification are not yet both present." + } + ], + "approval": { + "status": "approved", + "record": "evidence/approvals/APR-EPP-F01B-MC-002.json", + "required_records": [ + "evidence/approvals/APR-EPP-F01B-MC-002.json", + "evidence/approvals/APR-EPP-F01B-IMPL-002.json" + ] + }, + "feature_state": "BLOCKED", + "policy_version": "EPP-LIFECYCLE-1" +} diff --git a/docs/programs/engineering-process-platform/evidence/transitions/TR-0077.json b/docs/programs/engineering-process-platform/evidence/transitions/TR-0077.json new file mode 100644 index 00000000..f29e0702 --- /dev/null +++ b/docs/programs/engineering-process-platform/evidence/transitions/TR-0077.json @@ -0,0 +1,147 @@ +{ + "$schema": "../../schemas/transition-evidence.schema.json", + "schema_version": "2.0", + "transition_id": "TR-0077", + "program_id": "EPP-2026", + "feature_id": "EPP-F01B", + "state_domain": "repair", + "event_kind": "repair_checkpoint", + "from_state": "IMPLEMENTATION_AUTHORIZED", + "to_state": "BLOCKED", + "prior_revision": 77, + "new_revision": 78, + "state_digest_algorithm": "wright-json-c14n-v1-sha256", + "prior_state_digest": "e5391c79d72caac1f039665d960f0f0ec650f27ea24bb29c4bed87bf6d7adf36", + "new_state_digest": "e34e8637b1df8a1692f13f126398c206000cf300a1f8adca45435fa0cbe71030", + "actor": { + "role": "coordinator", + "identity": "Codex primary sole writer" + }, + "action": "Record the exact PR #115 merge without claiming durable dev-integration approval or green deployment, release the completed implementation lease, and block at one explicit human integration-evidence gate.", + "started_at": "2026-08-30T16:47:16Z", + "finished_at": "2026-08-30T17:05:00Z", + "duration_ms": 1064000, + "classification": "blocked", + "git": { + "source_commit": "9f961d52683e0e999fe29a7fed4c1e016de29620", + "source_tree": "3e7c5d929d321052f9a34f629f1f023b8a88c805", + "source_program_tree": "a6d5849a0d61cb96528f10956fba3342c0096e3e", + "containing_commit": null, + "containing_commit_rule": "transition_blob_container", + "worktree_clean_before": true, + "worktree_clean_after": false, + "diff_check_passed": true, + "changed_paths_manifest": [ + "docs/programs/engineering-process-platform/evidence/states/program-state-revision-0078.json", + "docs/programs/engineering-process-platform/evidence/transitions/TR-0077.json", + "docs/programs/engineering-process-platform/lifecycle-policy.json", + "docs/programs/engineering-process-platform/program-state.json", + "docs/programs/engineering-process-platform/roadmap.json", + "scripts/program_control/validation.py", + "tests/program_control_plane/test_roadmap_approval_and_lease.py", + "tests/program_control_plane/test_transition_chain.py" + ], + "transition_path": "evidence/transitions/TR-0077.json" + }, + "inputs": [ + { + "path": "evidence/states/program-state-revision-0077.json", + "sha256": "1e88cfb8d667982e0443ff50a102801d72ad76541cad904bf2f02614272860ea", + "schema_version": "2.0", + "role": "append_only_evidence" + } + ], + "outputs": [ + { + "path": "evidence/states/program-state-revision-0078.json", + "sha256": "95580d9f83f58877b6aeb89d5623745809dc4e143f66fad076dee7e97dce2186", + "schema_version": "2.0", + "role": "append_only_evidence" + }, + { + "path": "program-state.json", + "sha256": "95580d9f83f58877b6aeb89d5623745809dc4e143f66fad076dee7e97dce2186", + "schema_version": "2.0", + "role": "operational_state" + }, + { + "path": "roadmap.json", + "sha256": "d3bd8fe56b4d95865e65df36b3a103ed60638b26e1a518595548ab114fd4c6c2", + "schema_version": "1.0", + "role": "immutable_policy" + }, + { + "path": "lifecycle-policy.json", + "sha256": "6c1a8eeca1504c9d185183360cc04a4df0992b0d78caac0848934463d4b88fe7", + "schema_version": "1.0", + "role": "immutable_policy" + } + ], + "checks": [ + { + "check_id": "EPP-F01B-DEV-SUBJECT-RECONCILIATION", + "method": "Require PR #115 to be merged at dev commit 9f961d52, require its tree to equal the frozen candidate tree 3e7c5d92, and release the implementation lease without claiming development deployment verification.", + "environment": "GitHub PR #115 terminal results plus exact local Git subjects; Windows integration lane", + "duration_ms": 0, + "result": "passed", + "failure_class": null, + "evidence": [ + "https://github.com/burhop/wright/pull/115", + "merged_dev:9f961d52683e0e999fe29a7fed4c1e016de29620", + "merged_tree:3e7c5d929d321052f9a34f629f1f023b8a88c805" + ] + }, + { + "check_id": "EPP-F01B-INTEGRATION-CLOSURE-NON-INTERFERENCE", + "method": "Require product, benchmark, commercial, and program-health statuses to remain unchanged; benchmark qualification remains 0/100 and release eligibility remains false.", + "environment": "Canonical revision 77 versus revision 78 comparison", + "duration_ms": 0, + "result": "passed", + "failure_class": null, + "evidence": [ + "evidence/states/program-state-revision-0077.json", + "evidence/states/program-state-revision-0078.json" + ] + } + ], + "authority": { + "required_scopes": [ + "material_change", + "feature_implementation" + ], + "approval_records": [ + "evidence/approvals/APR-EPP-F01B-MC-002.json", + "evidence/approvals/APR-EPP-F01B-IMPL-002.json" + ], + "subject": { + "git_commit": "e83a78f86c3e53157386c105a9a3b6f495b76fd4", + "git_tree": "3a584940dfca227088c02b01aa74981baa847c06", + "program_tree": "8841bc1e0116fc2dd8950dd3e974f904d09d8edc", + "artifact_count": 17, + "manifest_transition": "TR-0072" + }, + "legacy_checkpoint": { + "profile": "epp-bridge-v1-r10-r19", + "transition": "TR-0018", + "resolution_rule": "exact_material_change_approval_subject" + }, + "migration": { + "from_schema_version": "1.0", + "to_schema_version": "2.0", + "sole_successor": true + } + }, + "independent_verifier": "Bounded independent verification must pass before this transition is committed or pushed.", + "repair": { + "stable_cause_id": "EPP-F01B-DEV-CHECKOUT-LEASE-IDENTITY-001", + "attempt": 1, + "maximum": 2, + "remaining": 1 + }, + "blockers": [ + "Durable dev-integration approval evidence is not bound to this transition.", + "Post-merge python-quality and test-windows are red on the branch/worktree lease-identity defect; development deployment is not verified." + ], + "rollback_subject": "evidence/states/program-state-revision-0077.json", + "next_action": "APPROVE_CURRENT_FEATURE_INTEGRATION_EVIDENCE" +} diff --git a/docs/programs/engineering-process-platform/lifecycle-policy.json b/docs/programs/engineering-process-platform/lifecycle-policy.json index 4f2ce990..2a1b51aa 100644 --- a/docs/programs/engineering-process-platform/lifecycle-policy.json +++ b/docs/programs/engineering-process-platform/lifecycle-policy.json @@ -371,6 +371,12 @@ } ], "action_rules": [ + { + "program_state": "PROGRAM_ACTIVE", + "feature_state": "BLOCKED", + "action": "APPROVE_CURRENT_FEATURE_INTEGRATION_EVIDENCE", + "requires_human_approval": true + }, { "program_state": "PROGRAM_ACTIVE", "feature_state": "BLOCKED", @@ -419,10 +425,16 @@ "action": "APPROVE_EXACT_RELEASE_SUBJECT", "requires_human_approval": true }, + { + "program_state": "PROGRAM_ACTIVE", + "feature_state": "DEV_INTEGRATED", + "action": "VERIFY_CURRENT_FEATURE_DEV_DEPLOYMENT", + "requires_human_approval": false + }, { "program_state": "PROGRAM_ACTIVE", "feature_state": "DEV_DEPLOYMENT_VERIFIED", - "action": "SELECT_EPP_F01B_PLANNING", + "action": "SELECT_NEXT_FEATURE_PLANNING", "requires_human_approval": false }, { diff --git a/docs/programs/engineering-process-platform/program-state.json b/docs/programs/engineering-process-platform/program-state.json index 1ca543be..6f9147f6 100644 --- a/docs/programs/engineering-process-platform/program-state.json +++ b/docs/programs/engineering-process-platform/program-state.json @@ -2,12 +2,12 @@ "$schema": "https://wright.local/programs/epp/program-state.schema.json", "schema_version": "2.0", "program_id": "EPP-2026", - "revision": 77, + "revision": 78, "state": "PROGRAM_ACTIVE", "baseline": { "ref": "dev", - "commit": "b776b1182d5b6ee41364eb40b1bc95bf4eff797c", - "tree": "f22f61791a2385723934558d8557881862221eb1", + "commit": "9f961d52683e0e999fe29a7fed4c1e016de29620", + "tree": "3e7c5d929d321052f9a34f629f1f023b8a88c805", "observed_clean": true }, "prototype_evidence": { @@ -20,106 +20,20 @@ }, "control_plane": { "root": "docs/programs/engineering-process-platform", - "candidate_subject_resolution": "EPP-F01B replacement material-change and feature-implementation approvals bind commit e83a78f86c3e53157386c105a9a3b6f495b76fd4, tree 3a584940dfca227088c02b01aa74981baa847c06, program tree 8841bc1e0116fc2dd8950dd3e974f904d09d8edc, and the 17 TR-0072 artifact digests to local tasks T001 through T048 only. Direct user authority on 2026-08-29 additionally permits the bounded registry-routing and lifecycle-limit correction independently verified at 3bb076a7355dfc3cfd6469db05b40b54462a32b0; the specialized test-result path contract and checkpoint-bound test-history correction through 1a2cebb42e4ce7b24ed48dceda6281cd39c68e02; and one deterministic packaged-browser rebuild under lease revision 5 at only src/wright_engineering/static/web/** and src/wright_engineering/runtime-extra-lock.json. TR-0074 records other already-changed candidate paths only as historical T001-T048 evidence and grants no future edit authority for them.", + "candidate_subject_resolution": "EPP-F01B replacement material-change and feature-implementation approvals bind commit e83a78f86c3e53157386c105a9a3b6f495b76fd4, tree 3a584940dfca227088c02b01aa74981baa847c06, program tree 8841bc1e0116fc2dd8950dd3e974f904d09d8edc, and the 17 TR-0072 artifact digests to local tasks T001 through T048 only. Direct user authority on 2026-08-29 additionally permits the bounded registry-routing and lifecycle-limit correction independently verified at 3bb076a7355dfc3cfd6469db05b40b54462a32b0; the specialized test-result path contract and checkpoint-bound test-history correction through 1a2cebb42e4ce7b24ed48dceda6281cd39c68e02; and one deterministic packaged-browser rebuild under lease revision 5 at only src/wright_engineering/static/web/** and src/wright_engineering/runtime-extra-lock.json. TR-0074 records other already-changed candidate paths only as historical T001-T048 evidence and grants no future edit authority for them. EPP-F01B integrated through PR #115 at dev commit 9f961d52683e0e999fe29a7fed4c1e016de29620 with exact candidate tree 3e7c5d929d321052f9a34f629f1f023b8a88c805; the implementation lease is released.", "schema_status": "passed", "audit_status": "passed" }, "current_feature": "EPP-F01B", - "active_mutating_lease": { - "feature_id": "EPP-F01B", - "branch": "codex/epp-continued-development-reconciled", - "worktree_id": "wright", - "dev_baseline": { - "commit": "b776b1182d5b6ee41364eb40b1bc95bf4eff797c", - "tree": "f22f61791a2385723934558d8557881862221eb1" - }, - "worktree_start": { - "commit": "e83a78f86c3e53157386c105a9a3b6f495b76fd4", - "tree": "3a584940dfca227088c02b01aa74981baa847c06" - }, - "holder_role": "feature_owner", - "lease_mode": "implementation", - "lease_revision": 6, - "acquired_at": "2026-08-30T11:53:51Z", - "expires_at": "2026-08-31T11:53:51Z", - "allowed_paths": [ - "docs/programs/engineering-process-platform/**", - "specs/077-browser-program-status/**", - "scripts/program_status/**", - "scripts/program_control/validation.py", - "scripts/publish-engineering-program-status.py", - "tests/fixtures/program-status/**", - "tests/program_control_plane/test_contract_schemas.py", - "specs/076-control-plane-validator/contracts/lifecycle-policy.schema.json", - "tests/program_control_plane/test_program_status_publisher.py", - "packages/tool_registry/src/tool_registry/program_status.py", - "packages/tool_registry/src/tool_registry/__init__.py", - "packages/tool_registry/tests/test_program_status.py", - "apps/api/src/api/schemas/program_status.py", - "apps/api/src/api/routers/program_status.py", - "apps/api/src/api/main.py", - "apps/api/src/api/composition.py", - "apps/api/tests/test_program_status_api.py", - "apps/web/src/services/program-status.ts", - "apps/web/src/components/program-status/**", - "apps/web/src/components/pages/ProgramStatusPage.tsx", - "apps/web/src/App.tsx", - "apps/web/src/components/layout/Sidebar.tsx", - "apps/web/src/__tests__/**", - "tests/ui-integration/program-status.spec.ts", - "src/wright_engineering/static/program-status/**", - "tests/packaging/test_wheel_contents.py", - "tests/native_runtime/test_program_status_lifecycle.py", - "docs/getting-started/quickstart-local.md", - "docs/getting-started/program-status.md", - "tests/e2e/test_program_status.py", - "src/wright_engineering/static/web/**", - "src/wright_engineering/runtime-extra-lock.json", - "pyproject.toml" - ], - "path_restrictions": [ - { - "path": "specs/077-browser-program-status/**", - "restriction": "The e83a78f8 requirements remain frozen. Allowed exceptions are TR-0073 lifecycle-limit projection, the specialized test-result/checkpoint-binding corrections through 1a2cebb4, task completion marks, acceptance evidence, and bounded implementation results." - }, - { - "path": "docs/programs/engineering-process-platform/**", - "restriction": "Only approval, lease, task/checkpoint, verification, and truthful generated status evidence may change; readiness and governed benchmark results must not be promoted by implementation activity." - }, - { - "path": "tests/program_control_plane/test_contract_schemas.py", - "restriction": "Only the prior feature-neutral lease regression and the exact three-registry routing/non-interference tests independently verified at 3bb076a7 are permitted; no further EPP-F01B implementation edits may use this path." - } - ], - "allowed_actions": [ - "inspect", - "edit_allowlisted_paths", - "run_deterministic_checks", - "create_local_artifacts", - "create_local_commits" - ], - "recovery": { - "status": "reactivated", - "last_audit_transition": "TR-0076", - "rollback_state": "evidence/states/program-state-revision-0076.json", - "exhausted_cause_ids": [ - "EPP-FEATURE-NEUTRAL-PLANNING-AUTHORITY-001", - "EPP-F01B-FEATURE-NEUTRAL-ACTIVATION-001", - "EPP-F01B-PROGRESS-CONTRACT-001" - ], - "active_cause_id": "EPP-F01B-INTEGRATION-LEASE-EXPIRY-001", - "repair_maximum": 2, - "repair_remaining": 1 - } - }, - "last_transition": "TR-0076", + "active_mutating_lease": null, + "last_transition": "TR-0077", "readiness": { "product": { "status": "not_started", "gate_file": "gates.md", "blockers": [ - "No product child feature is implemented or implementation-approved", - "The browser-accessible program-status page is implementation-authorized and partially implemented through 3bb076a7 but is not yet complete, candidate-frozen, or independently verified as a full feature" + "No customer product child feature is implemented or implementation-approved", + "The browser-accessible program-status page is integrated program-control capability and does not by itself advance product readiness" ] }, "benchmark": { @@ -151,9 +65,9 @@ "gate_file": "gates.md", "blockers": [ "EPP-F01 is complete and integrated through PR #114.", - "EPP-F01B T001 through T048 are complete; lease revision 6 preserves the unchanged local path and authority boundary only while PR and merge-gate integration evidence is completed.", + "EPP-F01B is integrated through PR #115 at dev commit 9f961d52 with exact candidate tree 3e7c5d92; development deployment verification is pending a green correction build.", "Product, benchmark, and commercial readiness remain independent; benchmark execution remains unauthorized at 0/100 and release eligibility remains false.", - "RISK-017 remains open until the repository-owned browser program-status page is implemented and verified." + "EPP-F02 planning is in progress and implementation remains subject to an exact human approval gate." ] } }, @@ -173,10 +87,10 @@ ], "next_eligible_actions": [ { - "action": "START_CURRENT_FEATURE_IMPLEMENTATION", + "action": "APPROVE_CURRENT_FEATURE_INTEGRATION_EVIDENCE", "roadmap_item": "EPP-F01B", - "requires_human_approval": false, - "reason": "APR-EPP-F01B-MC-002 and APR-EPP-F01B-IMPL-002 remain the unchanged local authority for completed T001 through T048; lease revision 6 preserves that same boundary only while PR and merge-gate integration evidence is completed." + "requires_human_approval": true, + "reason": "PR #115 is merged at exact dev commit 9f961d52 and tree 3e7c5d92, but durable dev-integration approval evidence and green post-merge deployment verification are not yet both present." } ], "approval": { @@ -187,6 +101,6 @@ "evidence/approvals/APR-EPP-F01B-IMPL-002.json" ] }, - "feature_state": "IMPLEMENTATION_AUTHORIZED", + "feature_state": "BLOCKED", "policy_version": "EPP-LIFECYCLE-1" } diff --git a/docs/programs/engineering-process-platform/roadmap.json b/docs/programs/engineering-process-platform/roadmap.json index 7af9ee6e..ccaaeb4c 100644 --- a/docs/programs/engineering-process-platform/roadmap.json +++ b/docs/programs/engineering-process-platform/roadmap.json @@ -45,8 +45,8 @@ "kind": "program_control", "priority": 15, "title": "Browser program-status dashboard", - "outcome": "A maintainer can open an accessible read-only browser page that renders the validated committed dashboard snapshot, four independent readiness areas, 0-to-100 benchmark qualification progress, active feature and task/checkpoint progress, blockers, next action, evidence links and freshness without becoming a second authority.", - "status": "active", + "outcome": "Integrated through PR #115 as dev commit 9f961d52 with exact candidate tree 3e7c5d92. A maintainer can open an accessible read-only browser page that renders the validated committed dashboard snapshot, four independent readiness areas, 0-to-100 benchmark qualification progress, active feature and task/checkpoint progress, blockers, next action, evidence links and freshness without becoming a second authority.", + "status": "blocked", "depends_on": [ "EPP-F01" ], diff --git a/packages/model_registry/src/model_registry/runtime.py b/packages/model_registry/src/model_registry/runtime.py index bc0afcee..0c7bb0f1 100644 --- a/packages/model_registry/src/model_registry/runtime.py +++ b/packages/model_registry/src/model_registry/runtime.py @@ -821,6 +821,7 @@ async def start_session( architecture: str, execution_provider: str, health_fault_profile: str | None = None, + startup_timeout: float = 2.0, maximum_artifact_bytes: int = 1024 * 1024 * 1024, required_ram_bytes: int = 0, required_disk_bytes: int = 0, @@ -837,6 +838,14 @@ async def start_session( ) if not _IDENTITY.fullmatch(installation_id): raise RuntimeFailure("artifact_invalid", "Installation identity is invalid") + if ( + not math.isfinite(startup_timeout) + or startup_timeout <= 0 + or startup_timeout > 30 + ): + raise RuntimeFailure( + "resource_rejected", "Runtime startup timeout is invalid" + ) if not 1 <= maximum_artifact_bytes <= 1024 * 1024 * 1024 * 1024: raise RuntimeFailure( "resource_rejected", "Runtime artifact limit is invalid" @@ -904,7 +913,10 @@ async def start_session( ) self._sessions.add(session) health = await session._exchange( - "health", {}, timeout=2.0, fault_profile=health_fault_profile + "health", + {}, + timeout=startup_timeout, + fault_profile=health_fault_profile, ) descriptor = AdapterDescriptor.parse(health) self._check_descriptor(registration, descriptor) diff --git a/packages/model_registry/tests/test_runtime_supervisor.py b/packages/model_registry/tests/test_runtime_supervisor.py index 4306cdc1..da59a710 100644 --- a/packages/model_registry/tests/test_runtime_supervisor.py +++ b/packages/model_registry/tests/test_runtime_supervisor.py @@ -10,6 +10,7 @@ from model_registry.runtime import ( RuntimeAdapterRegistry, RuntimeFailure, + RuntimeSession, RuntimeSupervisor, ) @@ -34,6 +35,65 @@ async def opened(tmp_path, *, values=None): return supervisor, session +@pytest.mark.asyncio +async def test_supervisor_applies_one_bounded_startup_deadline( + tmp_path, monkeypatch +) -> None: + observed: list[float] = [] + exchange = RuntimeSession._exchange + + async def record_startup_timeout(self, operation, payload, **kwargs): + if operation == "health": + observed.append(kwargs["timeout"]) + return await exchange(self, operation, payload, **kwargs) + + monkeypatch.setattr(RuntimeSession, "_exchange", record_startup_timeout) + supervisor = RuntimeSupervisor( + RuntimeAdapterRegistry((registration(),)), scratch_root=tmp_path / "scratch" + ) + system, architecture = _platform() + session = await supervisor.start_session( + adapter_id="wright-deterministic", + installation_id="installation-affine", + artifacts=artifacts(tmp_path), + model_format="wright-affine-json", + task_id="predict", + platform=system, + architecture=architecture, + execution_provider="cpu", + startup_timeout=5.0, + ) + await session.shutdown() + + assert observed == [5.0] + + +@pytest.mark.asyncio +@pytest.mark.parametrize("startup_timeout", [0.0, -1.0, 30.1, float("inf")]) +async def test_supervisor_rejects_unbounded_startup_deadlines( + tmp_path, startup_timeout +) -> None: + supervisor = RuntimeSupervisor( + RuntimeAdapterRegistry((registration(),)), scratch_root=tmp_path / "scratch" + ) + system, architecture = _platform() + with pytest.raises(RuntimeFailure) as caught: + await supervisor.start_session( + adapter_id="wright-deterministic", + installation_id="installation-affine", + artifacts=artifacts(tmp_path), + model_format="wright-affine-json", + task_id="predict", + platform=system, + architecture=architecture, + execution_provider="cpu", + startup_timeout=startup_timeout, + ) + + assert caught.value.category == "resource_rejected" + assert supervisor.active_process_count == 0 + + @pytest.mark.asyncio async def test_supervisor_uses_clean_environment_and_confined_read_only_artifacts( tmp_path, monkeypatch diff --git a/packages/workspace_service/src/workspace_service/engineering_model_service.py b/packages/workspace_service/src/workspace_service/engineering_model_service.py index 12186e56..fda74416 100644 --- a/packages/workspace_service/src/workspace_service/engineering_model_service.py +++ b/packages/workspace_service/src/workspace_service/engineering_model_service.py @@ -1342,6 +1342,10 @@ async def _runtime_session( platform=platform_name, architecture=architecture, execution_provider="cpu", + startup_timeout=min( + 30.0, + max(2.0, variant.resources.load_timeout_ms / 1000), + ), maximum_artifact_bytes=max( variant.resources.installed_bytes, sum(item.size for item in variant.artifacts), diff --git a/scripts/program_control/validation.py b/scripts/program_control/validation.py index b266abf7..01033f9d 100644 --- a/scripts/program_control/validation.py +++ b/scripts/program_control/validation.py @@ -3438,9 +3438,20 @@ def validate_f01b_lease_checkpoint_correction( ) current_lease = successor_state.get("active_mutating_lease") expected_lease = expected_state["active_mutating_lease"] - if not isinstance(current_lease, Mapping): - valid = False - else: + if current_lease is None: + valid = valid and successor_state.get("feature_state") in { + "BLOCKED", + "CANDIDATE_FROZEN", + "INDEPENDENTLY_VERIFIED", + "PUSH_AUTHORIZATION_PENDING", + "PR_READY", + "DEV_MERGE_READY", + "DEV_INTEGRATED", + "DEV_DEPLOYMENT_VERIFIED", + "ROLLED_BACK", + "STOPPED", + } + elif isinstance(current_lease, Mapping): valid = valid and all( ( isinstance(successor_state.get("revision"), int), @@ -3451,6 +3462,8 @@ def validate_f01b_lease_checkpoint_correction( ), ) ) + else: + valid = False claims = { "/inputs/3/sha256": ( diff --git a/scripts/program_status/publisher.py b/scripts/program_status/publisher.py index 4ebc27be..34d6ac9c 100644 --- a/scripts/program_status/publisher.py +++ b/scripts/program_status/publisher.py @@ -2041,31 +2041,46 @@ def _project_delivery_lanes( "events": events, } - if not isinstance(lease, Mapping): - raise ProgramStatusPublishError( - "PROGRAM_STATUS_LANE_SOURCE_INVALID", - "The continued-development lane needs the exact active lease.", - "repair_delivery_lane_sources", + next_action_record = (state.get("next_eligible_actions") or [{}])[0] + action_id = str(next_action_record.get("action", "NO_ELIGIBLE_ACTION")) + action_reason = str( + next_action_record.get( + "reason", "No committed next-action reason is available." ) + ) + requires_approval = bool(next_action_record.get("requires_human_approval", False)) + if isinstance(lease, Mapping): + branch = str(lease["branch"]) + base_commit = str(lease["dev_baseline"]["commit"]) + authority_state = "authorized" + blocker = None + else: + branch = "unavailable" + base_commit = str(state["baseline"]["commit"]) + authority_state = "not_authorized" if requires_approval else "unavailable" + blocker = action_reason development = { "kind": "continued_development", - "branch": str(lease["branch"]), + "branch": branch, "milestone": str(current_item["title"]), "latest_capability": ( "Unavailable: no committed customer acceptance evidence demonstrates " "a customer-visible EPP-F01B capability yet." ), - "blocker": None, + "blocker": blocker, "next_action": _action( - str((state.get("next_eligible_actions") or [{}])[0].get("action")), - str((state.get("next_eligible_actions") or [{}])[0].get("reason")), + action_id, + action_reason, "lane_next_action", [state_ref], + eligible=isinstance(lease, Mapping) and not requires_approval, + blocker=action_reason, + requires_human_approval=requires_approval, ), "observed_at": str(subject["generated_at"]), "evidence": [state_ref, roadmap_ref, feature_tasks_ref], - "base_commit": str(lease["dev_baseline"]["commit"]), - "authority_state": "authorized", + "base_commit": base_commit, + "authority_state": authority_state, } return integration, development diff --git a/tests/program_control_plane/test_program_status_publisher.py b/tests/program_control_plane/test_program_status_publisher.py index 275836ff..1f74c4f3 100644 --- a/tests/program_control_plane/test_program_status_publisher.py +++ b/tests/program_control_plane/test_program_status_publisher.py @@ -474,8 +474,8 @@ def _git_blob_with_active_task(repository: Path, commit: str, path: str) -> byte "task_id": task_id, "task_title": task["title"], "task_state": "in_progress", - "branch": subject["state"]["active_mutating_lease"]["branch"], - "worktree_id": subject["state"]["active_mutating_lease"]["worktree_id"], + "branch": "test-assignment-branch", + "worktree_id": "test-assignment-worktree", "lane": "continued_development", "why_this_matters": "Closes false status claims before customer review.", "observed_at": subject["generated_at"], @@ -488,7 +488,13 @@ def _git_blob_with_active_task(repository: Path, commit: str, path: str) -> byte } ], } - + subject["state"] = { + **subject["state"], + "active_mutating_lease": { + "branch": "test-assignment-branch", + "worktree_id": "test-assignment-worktree", + }, + } result = publisher._registered_task_counts(REPOSITORY, subject, "EPP-F01B") registered, program_done, program_total, feature_done, feature_total = result[:5] @@ -852,12 +858,16 @@ def test_delivery_lanes_are_derived_from_closed_committed_sources() -> None: assert integration["latest_capability"].startswith("Verified integration evidence:") assert integration["next_action"]["authority_state"] == "not_required" - lease = subject["state"]["active_mutating_lease"] assert development["kind"] == "continued_development" - assert development["branch"] == lease["branch"] - assert development["base_commit"] == lease["dev_baseline"]["commit"] + assert development["branch"] == "unavailable" + assert development["base_commit"] == subject["state"]["baseline"]["commit"] assert development["milestone"] == "Browser program-status dashboard" - assert development["authority_state"] == "authorized" + assert development["authority_state"] == "not_authorized" + assert ( + development["blocker"] == subject["state"]["next_eligible_actions"][0]["reason"] + ) + assert development["next_action"]["requires_human_approval"] is True + assert development["next_action"]["authority_state"] == "not_authorized" assert state_ref in development["evidence"] assert tasks_ref in development["evidence"] assert development["latest_capability"] == ( diff --git a/tests/program_control_plane/test_roadmap_approval_and_lease.py b/tests/program_control_plane/test_roadmap_approval_and_lease.py index 5dcd0be2..9dba2ba0 100644 --- a/tests/program_control_plane/test_roadmap_approval_and_lease.py +++ b/tests/program_control_plane/test_roadmap_approval_and_lease.py @@ -37,18 +37,25 @@ def code_set(findings) -> set[str]: return {finding.code for finding in findings} +def lease_identity(state: dict) -> tuple[str, str]: + lease = state.get("active_mutating_lease") + if not isinstance(lease, dict): + return "", "" + return lease["branch"], lease["worktree_id"] + + def test_current_pointer_matches_lifecycle_action( repository_root: Path, ) -> None: documents = current_documents(repository_root) state = documents[f"{PROGRAM_ROOT}/program-state.json"] - lease = state["active_mutating_lease"] + branch, worktree_id = lease_identity(state) findings, action = validate_roadmap_approval_and_lease( documents, PROGRAM_ROOT, observed_at=OBSERVED, - actual_branch=lease["branch"], - worktree_id=lease["worktree_id"], + actual_branch=branch, + worktree_id=worktree_id, ) assert findings == [] policy = documents[f"{PROGRAM_ROOT}/lifecycle-policy.json"] @@ -66,7 +73,7 @@ def test_cycle_wip_and_pointer_mismatch_are_all_reported(repository_root: Path) documents = copy.deepcopy(current_documents(repository_root)) roadmap = documents[f"{PROGRAM_ROOT}/roadmap.json"] state = documents[f"{PROGRAM_ROOT}/program-state.json"] - lease = state["active_mutating_lease"] + branch, worktree_id = lease_identity(state) roadmap["items"][0]["depends_on"] = [roadmap["items"][-1]["id"]] next( item @@ -78,8 +85,8 @@ def test_cycle_wip_and_pointer_mismatch_are_all_reported(repository_root: Path) documents, PROGRAM_ROOT, observed_at=OBSERVED, - actual_branch=lease["branch"], - worktree_id=lease["worktree_id"], + actual_branch=branch, + worktree_id=worktree_id, ) assert {"ROADMAP_CYCLE", "WIP_LIMIT_EXCEEDED", "LEASE_IDENTITY_MISMATCH"}.issubset( code_set(findings) @@ -218,7 +225,7 @@ def test_active_item_requires_complete_dependencies_and_resolved_decisions( documents = copy.deepcopy(current_documents(repository_root)) roadmap = documents[f"{PROGRAM_ROOT}/roadmap.json"] state = documents[f"{PROGRAM_ROOT}/program-state.json"] - lease = state["active_mutating_lease"] + branch, worktree_id = lease_identity(state) active = next( item for item in roadmap["items"] if item["id"] == state["current_feature"] ) @@ -231,8 +238,8 @@ def test_active_item_requires_complete_dependencies_and_resolved_decisions( documents, PROGRAM_ROOT, observed_at=OBSERVED, - actual_branch=lease["branch"], - worktree_id=lease["worktree_id"], + actual_branch=branch, + worktree_id=worktree_id, ) assert { "ROADMAP_DEPENDENCY_INCOMPLETE", diff --git a/tests/program_control_plane/test_transition_chain.py b/tests/program_control_plane/test_transition_chain.py index 3060f289..2f51720b 100644 --- a/tests/program_control_plane/test_transition_chain.py +++ b/tests/program_control_plane/test_transition_chain.py @@ -222,9 +222,7 @@ def test_f01b_lease_checkpoint_correction_rejects_scope_expansion( if target == "transition": transition["action"] += " and widen authority" else: - successor_state["active_mutating_lease"]["allowed_paths"].append( - "src/unapproved/**" - ) + successor_state["feature_state"] = "IMPLEMENTING" findings, schema_targets, digest_targets = ( validation_module.validate_f01b_lease_checkpoint_correction(