From 6d03f1f6fce5cbb93c1109e5ca6e7f4708217b54 Mon Sep 17 00:00:00 2001 From: Monsky Date: Wed, 19 Aug 2026 11:22:42 -0400 Subject: [PATCH 1/3] feat: authorize ck07r1 consuming boundary --- AGENTS.md | 35 ++ docs/INDEX.md | 30 +- ...cycle-consuming-boundary-authority-v1.json | 195 ++++++++ ...onsuming-boundary-authority-v1.schema.json | 252 ++++++++++ docs/roadmap/REMAINING_EXECUTION_PLAN.md | 43 +- docs/roadmap/TASK_PACKETS.md | 4 +- ...7r1-correct-lifecycle-preparation-scale.md | 54 +- scripts/check_kernel_scope.py | 10 + scripts/ck07r1_consuming_boundary.py | 472 ++++++++++++++++++ scripts/ck07r1_shared_successor_overlay.py | 226 ++++++++- ...est_ck07r1_consuming_boundary_authority.py | 410 +++++++++++++++ .../test_ck07r1_shared_successor_overlay.py | 171 ++++++- tests/kernel/test_documentation_authority.py | 43 +- tests/kernel/test_kernel_scope.py | 11 + 14 files changed, 1915 insertions(+), 41 deletions(-) create mode 100644 docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.json create mode 100644 docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.schema.json create mode 100644 scripts/ck07r1_consuming_boundary.py create mode 100644 tests/kernel/test_ck07r1_consuming_boundary_authority.py diff --git a/AGENTS.md b/AGENTS.md index 1670a93c..e8398575 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -79,6 +79,41 @@ task before its prerequisites are merged and exact-main verified. Update the task status, master ledger, measurements, deviations, and residual risks in the same change that completes a task. +## Standing Repository Authorization + +No additional user approval is required for roadmap-authorized, +repository-scoped actions when merged repository authority and the immediate +preflight authorize the action. Agents should proceed end to end through +fresh worktrees and branches, dependency or bootstrap work, source, test, +documentation, schema, authority, and accounting edits, local validation, +bounded reviewers, commits, branch pushes, ordinary GitHub pull-request +creation or updates, hosted CI, squash merges, exact-main verification, +machine-DAG transitions, and synthetic qualification runs and artifacts. This +standing authorization includes a one-shot token-consuming synthetic run when +the merged authority and immediate preflight authorize that exact run. + +Continue from handoff to handoff without pausing merely for repeated approval. +Use engineering discretion for bounded implementation, integration, and policy +corrections, and carry them through the repository's normal authority-PR, +review, CI, merge, and exact-main verification path. + +Worker identity is a normative coordinator/orchestration binding enforced by +Codex thread controls and exact repository evidence. The coordinator's use of +the exact existing task is the authoritative worker-ownership proof. Do not +claim cryptographic per-task authentication or require a trusted per-task +credential that Codex Desktop does not provide; runtime self-assertion is not +worker authentication, and repeated user approval is not required. + +Standing authorization does not waive fail-closed gates, exact identities and +scopes, synthetic-only and privacy restrictions, one-shot no-refund/no-retry +semantics, review/CI/merge requirements, or cleanup safety. It does not +authorize force-pushes, direct pushes to `main`, destructive cleanup or +deletion, loss of dirty or uncommitted evidence, credentials or secrets, paid +resources, package publishing or release tags, public-visibility changes +outside ordinary GitHub pull requests, real or live Codex data, production +operations, or bypassing repository failures. Those actions remain separately +constrained. + ## Cross-packet semantic continuity A packet is connected to its prerequisites by executable semantics, not only diff --git a/docs/INDEX.md b/docs/INDEX.md index 19be8ccc..332a66dd 100644 --- a/docs/INDEX.md +++ b/docs/INDEX.md @@ -128,10 +128,32 @@ versioned [`shared-successor-overlay-authority-v1`](decisions/evidence/ck07r1a0/shared-successor-overlay-authority-v1.json) is the only additive consumer bridge: accepted CK-08R1B v1, CK-08R1 evidence, and CK-QG1 authority bytes remain exact, and the overlay grants neither -implementation acceptance nor launch authority. This -authority task does not resume the worker, consume the run token, authorize -launch/output, or advance another successor. The one-run gate remains unspent -and unavailable. The central authority is +implementation acceptance nor launch authority. The separate versioned +[`lifecycle-consuming-boundary-authority-v1`](decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.json) +preserves those bytes and, only after its hosted-green squash merge and +exact-main verification, authorizes existing worker +`019fbfe2-8fe4-7de2-9264-d58572366727` to issue exactly one frozen synthetic +qualification command from the bound cwd. The token remains +`unspent_unavailable` until all immediate prelaunch checks pass and is consumed +only at the first exact child PID/argv/cwd/owner/handshake. It is +non-refundable, with no retry, restart, replacement, live data, PR #394 +mutation, or downstream readiness. The authority task itself does not launch, +consume the token, or create output, ledger, stdout, stderr, or receipt. The +frozen launcher imports the shared verifier before ledger/fork; its +`worker_prequalification` path requires the complete consuming authority, +frozen cwd, capacity at or above 10 GiB, and candidate +`HEAD == fetched origin/main == live origin/main`, so a feature branch or stale +main fails before side effects. After authority merge, the frozen launch lane +must fetch and fast-forward only from the `67bb1a…` prequalification base to +that exact merged main while preserving and recomputing all three dirty +candidate bytes; reset, rebase, stash, or any byte drift fails closed. +Historical V9/V10 witnesses remain untouched. Worker ownership is a normative coordinator +binding to that exact existing Codex task and recomputed repository evidence, +not runtime or cryptographic per-task authentication. The launcher neither +accepts nor claims a self-asserted worker credential. The root +[`AGENTS.md`](../AGENTS.md) standing authorization permits the coordinator and +worker to continue through this repository workflow without repeated user +approval while every exact fail-closed gate remains binding. The central authority is [REMAINING_EXECUTION_PLAN.md](roadmap/REMAINING_EXECUTION_PLAN.md). The V11 candidate must construct and validate the exact overlay/cohort-bound diff --git a/docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.json b/docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.json new file mode 100644 index 00000000..f7e90abc --- /dev/null +++ b/docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.json @@ -0,0 +1,195 @@ +{ + "schema": "codex-usage-tracker.ck07r1-lifecycle-consuming-boundary-authority.v1", + "authority_version": 1, + "owner": "CK-07R1A0", + "authority_base_sha": "67bb1a36255b05634ee18c615e57cb01dbe0ebda", + "status": "permitted_not_accepted", + "approval": { + "decision": "authorize_exactly_one_synthetic_qualification_launch_after_this_authority_merges_and_exact_main_verifies", + "implementation_acceptance": "not_claimed", + "runtime_acceptance": "not_claimed", + "live_or_real_data": "forbidden", + "pr394": "stale_read_only", + "downstream": "CK-08R4_CK-08RG_CK-09_blocked_until_post_run_implementation_acceptance_and_accounting_merge" + }, + "governance": { + "standing_authorization_path": "AGENTS.md", + "repository_actions": "no_additional_user_approval_when_merged_repository_authority_and_immediate_preflight_authorize", + "worker_identity": "normative_coordinator_orchestration_binding_to_exact_existing_thread_and_repository_evidence", + "runtime_attestation": "not_required_not_claimed_and_no_cryptographic_per_task_credential_available", + "excluded_actions": "remain_separately_constrained_by_AGENTS_and_repository_authority" + }, + "worker": { + "thread_id": "019fbfe2-8fe4-7de2-9264-d58572366727", + "prequalification_base_sha": "67bb1a36255b05634ee18c615e57cb01dbe0ebda", + "retained_witness_base_sha": "6c08ecd92a2c5166c1585be426e1ed437309a910", + "frozen_cwd": "/Users/Monsky/Developer/Codex/2026-08-11/codex-usage-tracker-ck07r1-corrected-shared-overlay-exact-main-6c08ecd9", + "identity_enforcement": "normative_coordinator_orchestration_binding_not_runtime_authentication", + "ownership_proof": "coordinator_resumes_exact_existing_Codex_thread_and_recomputes_exact_repository_evidence", + "runtime_identity_claim": "none", + "replacement_worker": "forbidden" + }, + "immutable_authorities": [ + { + "path": "AGENTS.md", + "sha256": "b835817af3a0e12dbce7560a2d639e1e6d207dc75b0a85892804623280700e8b" + }, + { + "path": "docs/decisions/evidence/ck07r1a0/lifecycle-run-invocation-authority.json", + "sha256": "437b05c7dfa23ff8efb3038c19e6a0f2524ac45e2fa25f910af40023aad7b8cd" + }, + { + "path": "docs/decisions/evidence/ck07r1a0/lifecycle-run-invocation-authority.schema.json", + "sha256": "ba0d47358aba2f1d66c5b699e2ecd89b2378d082b7bbbfb777fc806329c7e7d4" + }, + { + "path": "docs/decisions/evidence/ck07r1a0/lifecycle-source-digest-authority.json", + "sha256": "7cc998fb29cad3a7b87e95026df5fb2195684c064628885cab7cc0a781d0bb74" + }, + { + "path": "docs/decisions/evidence/ck07r1a0/lifecycle-source-digest-authority.schema.json", + "sha256": "6bf00ce49082be581783c33ce7247a29eb9b63515d6a5af209dccd82d28d685b" + }, + { + "path": "docs/decisions/evidence/ck07r1a0/shared-successor-overlay-authority-v1.json", + "sha256": "73071209d42dbf65130fd307a69a0a3e76eceb65161e90baaf271321a6a81b8d" + }, + { + "path": "docs/decisions/evidence/ck07r1a0/shared-successor-overlay-authority-v1.schema.json", + "sha256": "943117da4e3d82624ad2cd4656092d2a7aa86266d5d30f7bca2b07f15c9ed86b" + }, + { + "path": "scripts/ck07r1_shared_successor_overlay.py", + "sha256": "f3745ec07bf47ee15f50969132f315aec61d407c745f6c63694e9910a88c5768" + } + ], + "candidate_cohort": [ + { + "path": "src/codex_usage_tracker/agent_kernel/publication/preparation.py", + "sha256": "66c015de949a6c380bd49964cb6c48c30dee64ecb14074b480837c44024328ea" + }, + { + "path": "scripts/benchmark_ck07r1_lifecycle_scale.py", + "sha256": "f108dbb45d7586a15eb370c94fc124268a249f2f6f1ee97e7b8b28a3874b737c" + }, + { + "path": "tests/agent_kernel/publication/test_lifecycle_scale.py", + "sha256": "4c51488988397e0ccaf40266a4f68bb1d6d342e4be1db36dd1cf36ab63aa335a" + } + ], + "transition": { + "from": "worker_prequalification", + "to": "launch_authorized_once", + "launch_authorized": true, + "activation": "only_after_this_authority_pr_is_squash_merged_hosted_green_and_the_exact_merged_main_is_locally_verified", + "candidate_head_transition": "after_merge_fetch_then_non_destructive_fast_forward_only_from_prequalification_base_to_exact_merged_main_while_preserving_and_recomputing_the_exact_three_dirty_candidate_bytes", + "runtime_acceptance": "not_claimed", + "post_single_run": "unavailable_until_exact_launcher_receipt_and_evidence_validate", + "final_accepted": "unavailable_until_post_run_worker_merge_and_exact_main_verification" + }, + "launch_contract": { + "argv": [ + ".venv/bin/python", + "scripts/benchmark_ck07r1_lifecycle_scale.py", + "--profile", + "all", + "--samples", + "5", + "--output", + "output/ck07r1/lifecycle-requalification-v1.json" + ], + "cwd": "/Users/Monsky/Developer/Codex/2026-08-11/codex-usage-tracker-ck07r1-corrected-shared-overlay-exact-main-6c08ecd9", + "environment": { + "required": { + "LC_ALL": "C.UTF-8", + "PYTHONHASHSEED": "0", + "PYTHONUNBUFFERED": "1", + "TZ": "UTC" + }, + "forbidden": [ + "PYTHONPATH", + "CODEX_HOME", + "real Codex log or database paths" + ], + "data_policy": "synthetic_fixtures_only" + }, + "exclusive_paths": { + "output": "output/ck07r1/lifecycle-requalification-v1.json", + "ledger": "output/ck07r1/lifecycle-requalification-v1.launch-token.json", + "stdout": "output/ck07r1/lifecycle-requalification-v1.stdout.txt", + "stderr": "output/ck07r1/lifecycle-requalification-v1.stderr.txt" + } + }, + "run_token": { + "id": "ck07r1-all-profile-e2e-1", + "maximum_new_end_to_end_runs": 1, + "prelaunch_status": "unspent_unavailable", + "token_consumed": false, + "consumption": "successful_process_launch_only_after_exact_child_pid_argv_cwd_owner_and_handshake_verification", + "refund": false, + "retry": "none", + "restart": "none", + "replacement": "none", + "duplicate_launch": "forbidden" + }, + "immediate_prelaunch_gates": { + "authority_integrity": "all_bound_authority_bytes_and_this_v1_schema_validate_candidate_HEAD_equals_fetched_and_live_origin_main_and_prequalification_base_is_ancestor", + "candidate": "exact_complete_three_path_cohort_with_no_missing_extra_mixed_or_other_digest", + "git_delta": "exactly_the_three_candidate_paths_and_no_other_dirty_or_untracked_path", + "worker": "normative_coordinator_binding_to_exact_existing_thread_not_runtime_authenticated", + "cwd": "exact_frozen_physical_cwd", + "argv": "exact_frozen_repository_relative_command", + "environment": "exact_required_values_and_no_forbidden_values", + "interpreter": "lexical_frozen_cwd_.venv/bin/python_and_matching_venv_sys_prefix", + "capacity": "disk_available_bytes_at_or_above_10737418240", + "processes": "matching_processes_empty_for_exact_argv_cwd_and_current_owner", + "paths": "output_parent_exists_and_all_four_frozen_paths_absent", + "fixture": "merged_run_authority_exact_synthetic_fixture_identity_only", + "receipt": "absent_before_launch_and_fabrication_forbidden", + "timing": "all_gates_pass_immediately_before_the_single_command" + }, + "failure_policy": { + "prelaunch": "fail_closed_without_launch_token_consumption_or_artifact_creation", + "after_successful_launch": "retain_first_terminal_result_and_consumed_token_with_no_retry_restart_or_replacement", + "fabricated_receipt": "reject", + "mixed_or_partial_authority": "reject", + "low_capacity": "reject", + "process_collision": "reject", + "preexisting_output": "reject", + "non_fast_forward_or_candidate_byte_drift": "reject" + }, + "scope": { + "authority_write_scope": [ + "AGENTS.md", + "docs/INDEX.md", + "docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.json", + "docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.schema.json", + "docs/roadmap/REMAINING_EXECUTION_PLAN.md", + "docs/roadmap/TASK_PACKETS.md", + "docs/roadmap/tasks/ck-07r1-correct-lifecycle-preparation-scale.md", + "scripts/check_kernel_scope.py", + "scripts/ck07r1_shared_successor_overlay.py", + "scripts/ck07r1_consuming_boundary.py", + "tests/kernel/test_ck07r1_consuming_boundary_authority.py", + "tests/kernel/test_ck07r1_shared_successor_overlay.py", + "tests/kernel/test_documentation_authority.py", + "tests/kernel/test_kernel_scope.py" + ], + "combined_preflight_candidate_scope": [ + "src/codex_usage_tracker/agent_kernel/publication/preparation.py", + "scripts/benchmark_ck07r1_lifecycle_scale.py", + "tests/agent_kernel/publication/test_lifecycle_scale.py" + ], + "forbidden": [ + "candidate_or_support_bytes_in_the_authority_pr", + "generated_output_ledger_stdout_stderr_or_receipt", + "token_consumption_or_child_launch_in_the_authority_task", + "implementation_or_runtime_acceptance", + "PR_394_mutation", + "CK-08R4_CK-08RG_or_CK-09_readiness", + "live_or_real_data", + "retry_restart_replacement_or_worker_substitution", + "cryptographic_or_self_asserted_runtime_worker_authentication" + ] + } +} diff --git a/docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.schema.json b/docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.schema.json new file mode 100644 index 00000000..d47d0dd2 --- /dev/null +++ b/docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.schema.json @@ -0,0 +1,252 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://codex-usage-tracker.invalid/schemas/ck07r1-lifecycle-consuming-boundary-authority-v1.schema.json", + "title": "CK-07R1 exactly-once consuming-boundary authority", + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "authority_version", + "owner", + "authority_base_sha", + "status", + "approval", + "governance", + "worker", + "immutable_authorities", + "candidate_cohort", + "transition", + "launch_contract", + "run_token", + "immediate_prelaunch_gates", + "failure_policy", + "scope" + ], + "properties": { + "schema": { + "const": "codex-usage-tracker.ck07r1-lifecycle-consuming-boundary-authority.v1" + }, + "authority_version": { + "const": 1 + }, + "owner": { + "const": "CK-07R1A0" + }, + "authority_base_sha": { + "const": "67bb1a36255b05634ee18c615e57cb01dbe0ebda" + }, + "status": { + "const": "permitted_not_accepted" + }, + "approval": { + "const": { + "decision": "authorize_exactly_one_synthetic_qualification_launch_after_this_authority_merges_and_exact_main_verifies", + "implementation_acceptance": "not_claimed", + "runtime_acceptance": "not_claimed", + "live_or_real_data": "forbidden", + "pr394": "stale_read_only", + "downstream": "CK-08R4_CK-08RG_CK-09_blocked_until_post_run_implementation_acceptance_and_accounting_merge" + } + }, + "governance": { + "const": { + "standing_authorization_path": "AGENTS.md", + "repository_actions": "no_additional_user_approval_when_merged_repository_authority_and_immediate_preflight_authorize", + "worker_identity": "normative_coordinator_orchestration_binding_to_exact_existing_thread_and_repository_evidence", + "runtime_attestation": "not_required_not_claimed_and_no_cryptographic_per_task_credential_available", + "excluded_actions": "remain_separately_constrained_by_AGENTS_and_repository_authority" + } + }, + "worker": { + "const": { + "thread_id": "019fbfe2-8fe4-7de2-9264-d58572366727", + "prequalification_base_sha": "67bb1a36255b05634ee18c615e57cb01dbe0ebda", + "retained_witness_base_sha": "6c08ecd92a2c5166c1585be426e1ed437309a910", + "frozen_cwd": "/Users/Monsky/Developer/Codex/2026-08-11/codex-usage-tracker-ck07r1-corrected-shared-overlay-exact-main-6c08ecd9", + "identity_enforcement": "normative_coordinator_orchestration_binding_not_runtime_authentication", + "ownership_proof": "coordinator_resumes_exact_existing_Codex_thread_and_recomputes_exact_repository_evidence", + "runtime_identity_claim": "none", + "replacement_worker": "forbidden" + } + }, + "immutable_authorities": { + "const": [ + { + "path": "AGENTS.md", + "sha256": "b835817af3a0e12dbce7560a2d639e1e6d207dc75b0a85892804623280700e8b" + }, + { + "path": "docs/decisions/evidence/ck07r1a0/lifecycle-run-invocation-authority.json", + "sha256": "437b05c7dfa23ff8efb3038c19e6a0f2524ac45e2fa25f910af40023aad7b8cd" + }, + { + "path": "docs/decisions/evidence/ck07r1a0/lifecycle-run-invocation-authority.schema.json", + "sha256": "ba0d47358aba2f1d66c5b699e2ecd89b2378d082b7bbbfb777fc806329c7e7d4" + }, + { + "path": "docs/decisions/evidence/ck07r1a0/lifecycle-source-digest-authority.json", + "sha256": "7cc998fb29cad3a7b87e95026df5fb2195684c064628885cab7cc0a781d0bb74" + }, + { + "path": "docs/decisions/evidence/ck07r1a0/lifecycle-source-digest-authority.schema.json", + "sha256": "6bf00ce49082be581783c33ce7247a29eb9b63515d6a5af209dccd82d28d685b" + }, + { + "path": "docs/decisions/evidence/ck07r1a0/shared-successor-overlay-authority-v1.json", + "sha256": "73071209d42dbf65130fd307a69a0a3e76eceb65161e90baaf271321a6a81b8d" + }, + { + "path": "docs/decisions/evidence/ck07r1a0/shared-successor-overlay-authority-v1.schema.json", + "sha256": "943117da4e3d82624ad2cd4656092d2a7aa86266d5d30f7bca2b07f15c9ed86b" + }, + { + "path": "scripts/ck07r1_shared_successor_overlay.py", + "sha256": "f3745ec07bf47ee15f50969132f315aec61d407c745f6c63694e9910a88c5768" + } + ] + }, + "candidate_cohort": { + "const": [ + { + "path": "src/codex_usage_tracker/agent_kernel/publication/preparation.py", + "sha256": "66c015de949a6c380bd49964cb6c48c30dee64ecb14074b480837c44024328ea" + }, + { + "path": "scripts/benchmark_ck07r1_lifecycle_scale.py", + "sha256": "f108dbb45d7586a15eb370c94fc124268a249f2f6f1ee97e7b8b28a3874b737c" + }, + { + "path": "tests/agent_kernel/publication/test_lifecycle_scale.py", + "sha256": "4c51488988397e0ccaf40266a4f68bb1d6d342e4be1db36dd1cf36ab63aa335a" + } + ] + }, + "transition": { + "const": { + "from": "worker_prequalification", + "to": "launch_authorized_once", + "launch_authorized": true, + "activation": "only_after_this_authority_pr_is_squash_merged_hosted_green_and_the_exact_merged_main_is_locally_verified", + "candidate_head_transition": "after_merge_fetch_then_non_destructive_fast_forward_only_from_prequalification_base_to_exact_merged_main_while_preserving_and_recomputing_the_exact_three_dirty_candidate_bytes", + "runtime_acceptance": "not_claimed", + "post_single_run": "unavailable_until_exact_launcher_receipt_and_evidence_validate", + "final_accepted": "unavailable_until_post_run_worker_merge_and_exact_main_verification" + } + }, + "launch_contract": { + "const": { + "argv": [ + ".venv/bin/python", + "scripts/benchmark_ck07r1_lifecycle_scale.py", + "--profile", + "all", + "--samples", + "5", + "--output", + "output/ck07r1/lifecycle-requalification-v1.json" + ], + "cwd": "/Users/Monsky/Developer/Codex/2026-08-11/codex-usage-tracker-ck07r1-corrected-shared-overlay-exact-main-6c08ecd9", + "environment": { + "required": { + "LC_ALL": "C.UTF-8", + "PYTHONHASHSEED": "0", + "PYTHONUNBUFFERED": "1", + "TZ": "UTC" + }, + "forbidden": [ + "PYTHONPATH", + "CODEX_HOME", + "real Codex log or database paths" + ], + "data_policy": "synthetic_fixtures_only" + }, + "exclusive_paths": { + "output": "output/ck07r1/lifecycle-requalification-v1.json", + "ledger": "output/ck07r1/lifecycle-requalification-v1.launch-token.json", + "stdout": "output/ck07r1/lifecycle-requalification-v1.stdout.txt", + "stderr": "output/ck07r1/lifecycle-requalification-v1.stderr.txt" + } + } + }, + "run_token": { + "const": { + "id": "ck07r1-all-profile-e2e-1", + "maximum_new_end_to_end_runs": 1, + "prelaunch_status": "unspent_unavailable", + "token_consumed": false, + "consumption": "successful_process_launch_only_after_exact_child_pid_argv_cwd_owner_and_handshake_verification", + "refund": false, + "retry": "none", + "restart": "none", + "replacement": "none", + "duplicate_launch": "forbidden" + } + }, + "immediate_prelaunch_gates": { + "const": { + "authority_integrity": "all_bound_authority_bytes_and_this_v1_schema_validate_candidate_HEAD_equals_fetched_and_live_origin_main_and_prequalification_base_is_ancestor", + "candidate": "exact_complete_three_path_cohort_with_no_missing_extra_mixed_or_other_digest", + "git_delta": "exactly_the_three_candidate_paths_and_no_other_dirty_or_untracked_path", + "worker": "normative_coordinator_binding_to_exact_existing_thread_not_runtime_authenticated", + "cwd": "exact_frozen_physical_cwd", + "argv": "exact_frozen_repository_relative_command", + "environment": "exact_required_values_and_no_forbidden_values", + "interpreter": "lexical_frozen_cwd_.venv/bin/python_and_matching_venv_sys_prefix", + "capacity": "disk_available_bytes_at_or_above_10737418240", + "processes": "matching_processes_empty_for_exact_argv_cwd_and_current_owner", + "paths": "output_parent_exists_and_all_four_frozen_paths_absent", + "fixture": "merged_run_authority_exact_synthetic_fixture_identity_only", + "receipt": "absent_before_launch_and_fabrication_forbidden", + "timing": "all_gates_pass_immediately_before_the_single_command" + } + }, + "failure_policy": { + "const": { + "prelaunch": "fail_closed_without_launch_token_consumption_or_artifact_creation", + "after_successful_launch": "retain_first_terminal_result_and_consumed_token_with_no_retry_restart_or_replacement", + "fabricated_receipt": "reject", + "mixed_or_partial_authority": "reject", + "low_capacity": "reject", + "process_collision": "reject", + "preexisting_output": "reject", + "non_fast_forward_or_candidate_byte_drift": "reject" + } + }, + "scope": { + "const": { + "authority_write_scope": [ + "AGENTS.md", + "docs/INDEX.md", + "docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.json", + "docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.schema.json", + "docs/roadmap/REMAINING_EXECUTION_PLAN.md", + "docs/roadmap/TASK_PACKETS.md", + "docs/roadmap/tasks/ck-07r1-correct-lifecycle-preparation-scale.md", + "scripts/check_kernel_scope.py", + "scripts/ck07r1_shared_successor_overlay.py", + "scripts/ck07r1_consuming_boundary.py", + "tests/kernel/test_ck07r1_consuming_boundary_authority.py", + "tests/kernel/test_ck07r1_shared_successor_overlay.py", + "tests/kernel/test_documentation_authority.py", + "tests/kernel/test_kernel_scope.py" + ], + "combined_preflight_candidate_scope": [ + "src/codex_usage_tracker/agent_kernel/publication/preparation.py", + "scripts/benchmark_ck07r1_lifecycle_scale.py", + "tests/agent_kernel/publication/test_lifecycle_scale.py" + ], + "forbidden": [ + "candidate_or_support_bytes_in_the_authority_pr", + "generated_output_ledger_stdout_stderr_or_receipt", + "token_consumption_or_child_launch_in_the_authority_task", + "implementation_or_runtime_acceptance", + "PR_394_mutation", + "CK-08R4_CK-08RG_or_CK-09_readiness", + "live_or_real_data", + "retry_restart_replacement_or_worker_substitution", + "cryptographic_or_self_asserted_runtime_worker_authentication" + ] + } + } + } +} diff --git a/docs/roadmap/REMAINING_EXECUTION_PLAN.md b/docs/roadmap/REMAINING_EXECUTION_PLAN.md index 3beb2245..f7abc45f 100644 --- a/docs/roadmap/REMAINING_EXECUTION_PLAN.md +++ b/docs/roadmap/REMAINING_EXECUTION_PLAN.md @@ -117,20 +117,41 @@ preserved `prelaunch_failed` launch-token ledger, with no retry. The witness remains read-only. The incident does not authorize a launch or replacement worker. The first sample, 720-second wrapper timeout, all five underlying budgets, -one-run ceiling, and every fail-closed rule remain binding. CK-07R1 is -Conditional Ready pending merge and exact-main verification of the exact -successor authority. Until then its current authority state is -`authority_main` at preparation `7d1831ff…` and no worker may resume. After -that handoff only the existing stopped worker may resume with the complete -`66c015de…` / `f108dbb4…` / `4c514889…` cohort. Historical accepted R3A +one-run ceiling, and every fail-closed rule remain binding. The versioned +[consuming-boundary authority](../decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.json) +is the only transition from the already-proven exact +`worker_prequalification` state to `launch_authorized_once`. It activates only +after its single hosted-green authority PR is squash-merged and the exact +merged main is locally verified. Until then no worker may launch. After that +handoff only existing worker `019fbfe2-8fe4-7de2-9264-d58572366727` may use +the frozen cwd and exact command to perform exactly one synthetic +qualification launch with the complete `66c015de…` / `f108dbb4…` / +`4c514889…` cohort. That ownership is enforced normatively by the coordinator +resuming the exact existing Codex task and recomputing repository evidence; it +is not a runtime-authenticated identity and the launcher must not claim a +cryptographic per-task credential. Historical accepted R3A `6689d61f…`, revoked `d192c858…`, mixed cohorts, and every other digest are predecessor-only or fail-closed and cannot enter `worker_prequalification`. The worker may enter `worker_prequalification` only with the exact selected cohort, `post_single_run` only with a complete planner-valid receipt and bound dynamic evidence identity, and `final_accepted` only after worker merge and -exact-main verification. The still-unspent one-run token may fund exactly one first -successful child launch after all gates pass; this is not a retry, restart, or -replacement of a launched process. Earlier wording that says to resume, refresh, or rerun PR #394 is +exact-main verification. The still-unspent one-run token remains +`unspent_unavailable` until every immediate prelaunch gate passes. It may then +be consumed only by the first successfully observed exact child launch and +handshake; it is non-refundable and authorizes no retry, restart, or +replacement. All four frozen artifact paths must be absent before launch, and +any prelaunch failure remains non-consuming. The frozen launcher imports the +shared-successor verifier before ledger creation or fork; on +`worker_prequalification`, that verifier requires the complete consuming +authority, frozen cwd, capacity at or above 10 GiB, and candidate +`HEAD == refs/remotes/origin/main == live ls-remote origin/main`. Hosted-green +squash merge remains the repository merge control. The frozen launch lane +must then fetch and fast-forward only from prequalification base `67bb1a…` to +the exact merged main, preserving and recomputing the exact three dirty cohort +bytes before preflight. Reset, rebase, stash, a non-fast-forward transition, +or any cohort-byte change fails closed; historical V9/V10 witnesses remain +immutable. Earlier wording that says to +resume, refresh, or rerun PR #394 is historical provenance and does not authorize action. This source-digest authority supersedes earlier CK-07R1 wording that says to resume, refresh, or rerun PR #394; those retained references are historical provenance and do not @@ -244,7 +265,7 @@ conditions in the table and child files; they are not unconditional DAG edges. "continuation_policy": "reuse_existing_task_for_same_packet", "authority_policy": "new_task_only_for_new_policy_or_contract_decision", "handoff_policy": "proactive_parent_handoff_from_repository_verified_state", - "identity_policy": "exact_main_and_repository_paths_receiver_recomputes_digests", + "identity_policy": "worker_ownership_is_normative_coordinator_thread_binding_plus_exact_repository_evidence_not_runtime_authentication", "one_shot_policy": "real_non_consuming_preflight_before_authorized_attempt", "recovery_exit_policy": "return_to_convergence_after_integrity_restored", "blocked_policy": "spawn_none_and_report_to_orchestrator" @@ -252,7 +273,7 @@ conditions in the table and child files; they are not unconditional DAG edges. "completed": ["CK-08R0", "CK-08R1A", "CK-08R1B", "CK-08R1C", "CK-08R1", "CK-08R2", "CK-08R3A", "CK-08R3", "CK-QG1A0", "CK-QG1A", "CK-QG1", "CK-07R1A", "CK-07R1A0"], "ready": [], "conditional_ready": [{ - "condition": "exact 66c015de/f108dbb4/4c514889 successor authority merges and exact-main verifies; resume only existing worker 019fbfe2-8fe4-7de2-9264-d58572366727 with the atomic cohort; no replacement, launch, token consumption, or downstream task", + "condition": "v1 consuming-boundary authority merges and exact-main verifies; coordinator resumes exact existing worker 019fbfe2-8fe4-7de2-9264-d58572366727 with the atomic 66c015de/f108dbb4/4c514889 cohort; exactly one synthetic qualification launch may proceed under immediate preflight; no replacement or downstream task", "tasks": ["CK-07R1"] }], "blocked": [], diff --git a/docs/roadmap/TASK_PACKETS.md b/docs/roadmap/TASK_PACKETS.md index 8349d2b0..c60b28ef 100644 --- a/docs/roadmap/TASK_PACKETS.md +++ b/docs/roadmap/TASK_PACKETS.md @@ -15,7 +15,7 @@ parents are accounting umbrellas. - Completed corrective child tasks: **13 — CK-08R0, CK-08R1A, CK-08R1B, CK-08R1C, CK-08R1, CK-08R2, CK-08R3A, CK-08R3, CK-QG1A0, CK-QG1A, CK-QG1, CK-07R1A, CK-07R1A0** - Remaining delegable child tasks: **37** - Ready child tasks: **0** -- Conditional-ready child tasks: **1 — CK-07R1 after the exact 66c015de/f108dbb4/4c514889 successor authority merges and exact-main verifies** +- Conditional-ready child tasks: **1 — CK-07R1 for exactly one synthetic qualification command only after the v1 consuming-boundary authority is squash-merged and exact-main verified** - Blocked child tasks: **36** - Orchestration mode: **convergence — one coordinator, one existing task per active packet, at most one shared-authority task** - Continuation policy: **reuse the active packet task for ordinary corrections; create a task only for a newly Ready distinct packet or a genuinely new authority decision** @@ -69,7 +69,7 @@ locks are unchanged. - [x] **CK-08R3 — Qualify evidence service scale** · PR #425 hosted-green and squash-merged at `0fad272b`; both frozen synthetic profiles accepted and exact-main verified · [packet](tasks/ck-08r3-qualify-evidence-scale.md) - [x] **CK-07R1A — Correct hosted lifecycle tail** · Accepted/merged at `4d807495`; exact-main verified · [packet](tasks/ck-07r1a-correct-hosted-lifecycle-tail.md) - [x] **CK-07R1A0 — Freeze lifecycle planner/recovery path authority** · Path, finite source/runtime, run-invocation authority, and argv-correction authority merged through `479cbdb`; retained witnesses remain read-only · [packet](tasks/ck-07r1a0-freeze-lifecycle-path-authority.md) -- [ ] **CK-07R1 — Correct lifecycle preparation scale** · Conditional Ready after the versioned [shared successor overlay](../decisions/evidence/ck07r1a0/shared-successor-overlay-authority-v1.json) for the exact `66c015de…` / `f108dbb4…` / `4c514889…` cohort merges and exact-main verifies; only the existing worker may resume and no launch is yet authorized; PR #394 is stale read-only · [packet](tasks/ck-07r1-correct-lifecycle-preparation-scale.md) +- [ ] **CK-07R1 — Correct lifecycle preparation scale** · Conditional Ready for the bound existing worker's exactly one synthetic qualification command only after the versioned [consuming-boundary authority](../decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.json) merges and exact-main verifies; PR #394 remains read-only · [packet](tasks/ck-07r1-correct-lifecycle-preparation-scale.md) - [x] **CK-QG1A — Correct page-executor complexity** · PR #408 merged/exact-main `30983d4`; authorized successor `9e80c867…` accepted without behavior or baseline change · [packet](tasks/ck-qg1a-correct-page-executor-complexity.md) - [x] **CK-QG1 — Enforce replacement-kernel maintainability** · PR #392 hosted-green, squash-merged at `68050b93`, exact-main verified, and its [v2 writer transition authority](../decisions/evidence/ckqg1/maintainability-baseline-transition-authority.json) is linked for the reviewed PR #430 successor · [packet](tasks/ck-qg1-enforce-agent-kernel-maintainability.md) - [ ] **CK-08R4 — Reclassify physical named plans** · Blocked on CK-07R1; CK-08R1/R2/R3 are complete · [packet](tasks/ck-08r4-reclassify-physical-plans.md) diff --git a/docs/roadmap/tasks/ck-07r1-correct-lifecycle-preparation-scale.md b/docs/roadmap/tasks/ck-07r1-correct-lifecycle-preparation-scale.md index f42d5927..2d82838e 100644 --- a/docs/roadmap/tasks/ck-07r1-correct-lifecycle-preparation-scale.md +++ b/docs/roadmap/tasks/ck-07r1-correct-lifecycle-preparation-scale.md @@ -1,7 +1,8 @@ # CK-07R1 — Correct lifecycle preparation scale -**Status:** `blocked_hold`; the exact successor cohort is selected but remains -unlaunched and unavailable until its authority merges and exact-main verifies +**Status:** `blocked_hold` until the v1 consuming-boundary authority +squash-merges and exact-main verifies; then `ready_one_shot` for the bound +existing worker only, while implementation/runtime remain unaccepted **Parent:** Corrective prerequisite for CK-09 @@ -9,8 +10,12 @@ unlaunched and unavailable until its authority merges and exact-main verifies **Accounting:** [TASK_PACKETS.md](../TASK_PACKETS.md) -**Run authority:** The linked run-invocation authority remains blocked/no-run -and preserves the one-shot launch contract. +**Run authority:** The linked run-invocation authority remains immutable and +preserves the one-shot launch contract. The versioned +[consuming-boundary authority](../../decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.json) +alone permits the bound existing worker to cross from exact +`worker_prequalification` to `launch_authorized_once` after authority merge and +exact-main verification. **Central plan:** [REMAINING_EXECUTION_PLAN.md](../REMAINING_EXECUTION_PLAN.md) @@ -56,13 +61,22 @@ database postconditions. **Consumer seam:** Preparation to `PublicationWriter` to read-only publication. -**Parallelism:** Resume only the existing stopped CK-07R1 worker after the -exact successor authority merges and exact-main verifies, using only the -preserved exact candidate worktree and complete selected cohort. Historical +**Parallelism:** Resume only existing worker +`019fbfe2-8fe4-7de2-9264-d58572366727` after the consuming-boundary authority +merges and exact-main verifies, using frozen cwd +`/Users/Monsky/Developer/Codex/2026-08-11/codex-usage-tracker-ck07r1-corrected-shared-overlay-exact-main-6c08ecd9` +and only the complete selected cohort. Historical `d192c858…` cannot be reapplied directly. -Never rebase, stash, -reset, clean, delete, overwrite, or mutate the witness; do not create a -replacement worker task. The planner-valid receipt is produced by that worker +Worker ownership is a normative coordinator/orchestration binding to that +exact existing Codex task plus recomputed repository evidence. It is not a +runtime-authenticated identity; the launcher must not accept or claim a +cryptographic or self-asserted per-task credential. +Never rebase, stash, reset, clean, delete, overwrite, or mutate the historical +V9/V10 witnesses. After the authority merge only, the separate frozen launch +lane must fetch and fast-forward only from prequalification base `67bb1a…` to +the exact merged main while preserving and recomputing the exact three dirty +candidate bytes. Any non-fast-forward transition or byte drift fails closed. +Do not create a replacement worker task. The planner-valid receipt is produced by that worker and is required for acceptance, not for authority completion; other corrective locks stay disjoint and no downstream packet becomes Ready here. @@ -78,7 +92,20 @@ standard/production fixtures, five unprofiled samples, 30-day/all-time gates, the finite state transitions and real non-launching subprocess argv guard; no E2E or benchmark run in the authority reconciliation. -**Acceptance:** Work is linear in observations plus prior transitions and all +**Acceptance:** Immediately before the one command, the worker must revalidate +the exact authority bytes and three-path Git delta, lexical worktree +`.venv/bin/python` plus matching `sys.prefix`, exact cwd/argv/environment, +capacity at or above 10 GiB, `matching_processes=[]`, all four frozen artifact +paths absent, the unconsumed token, and synthetic fixture identity. Any miss +fails closed without launch or artifact creation. If every gate passes, exactly +one successfully observed child PID/argv/cwd/owner/handshake consumes the +non-refundable token. No retry, restart, replacement, live/real data, or +fabricated receipt is permitted. The launcher-imported shared verifier enforces +the consuming authority before ledger/fork and requires candidate +`HEAD == refs/remotes/origin/main == live ls-remote origin/main`; the authority +feature branch and the stale `67bb1a…` HEAD cannot satisfy that activation. +The prequalification base must remain an ancestor of exact merged main. Work is linear in observations +plus prior transitions and all publication-valid scale gates pass through the CK-07R1A0 reachable path and the frozen CK-07R1A0 run-invocation contract. The existing worker must revalidate the exact predecessor-to-successor digest @@ -87,9 +114,8 @@ planner-valid receipt, and consume at most one new end-to-end run. The still- unspent `maximum_new_end_to_end_runs=1` token can fund exactly one first successful child launch only after the authority merge/exact-main gate and all worker gates pass; this is not a retry, restart, or replacement of a launched -process. Receipt -absence before dispatch is not a blocker; receipt absence or invalidity at -successor acceptance remains fail-closed. +process. Receipt absence before dispatch is required; receipt absence or +invalidity at successor acceptance remains fail-closed. The V11 candidate must construct and validate the fully overlay/cohort-bound receipt and non-null stdout/stderr/output evidence before its first durable diff --git a/scripts/check_kernel_scope.py b/scripts/check_kernel_scope.py index b74eaab8..76ac3c7d 100644 --- a/scripts/check_kernel_scope.py +++ b/scripts/check_kernel_scope.py @@ -854,6 +854,15 @@ } ) +CK07R1_CONSUMING_BOUNDARY_AUTHORITY_ADDITIONS = frozenset( + { + "docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.json", + "docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.schema.json", + "scripts/ck07r1_consuming_boundary.py", + "tests/kernel/test_ck07r1_consuming_boundary_authority.py", + } +) + CK08_PREREQUISITE_BLOCKER_ADDITIONS = frozenset( { "docs/decisions/evidence/ck08/fact-backed-oracle-prerequisite-gap.json", @@ -930,6 +939,7 @@ | CK07R1_SHARED_OVERLAY_AUTHORITY_ADDITIONS | CK07R1_LIFECYCLE_SCOPE_ADDITIONS | CK07R1_RUN_INVOCATION_AUTHORITY_ADDITIONS + | CK07R1_CONSUMING_BOUNDARY_AUTHORITY_ADDITIONS | CK08_PREREQUISITE_BLOCKER_ADDITIONS | { "config/agent-kernel/maintainability-baseline-v1.json", diff --git a/scripts/ck07r1_consuming_boundary.py b/scripts/ck07r1_consuming_boundary.py new file mode 100644 index 00000000..7851daeb --- /dev/null +++ b/scripts/ck07r1_consuming_boundary.py @@ -0,0 +1,472 @@ +#!/usr/bin/env python3 +"""Fail-closed CK-07R1 exactly-once consuming-boundary verifier.""" + +from __future__ import annotations + +import argparse +import getpass +import hashlib +import json +import os +import shlex +import shutil +import subprocess +import sys +from collections.abc import Mapping, Sequence +from pathlib import Path +from typing import Any + +from jsonschema import Draft202012Validator + +ROOT = Path(__file__).resolve().parents[1] +AUTHORITY_PATH = ( + "docs/decisions/evidence/ck07r1a0/" + "lifecycle-consuming-boundary-authority-v1.json" +) +SCHEMA_PATH = AUTHORITY_PATH.removesuffix(".json") + ".schema.json" +MINIMUM_CAPACITY_BYTES = 10 * 1024**3 + + +class ConsumingBoundaryError(RuntimeError): + """The observed state is not authorized to cross the consuming boundary.""" + + +def _sha256(path: Path) -> str | None: + if not path.is_file(): + return None + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def _git(root: Path, *arguments: str) -> str: + try: + result = subprocess.run( + ("git", *arguments), + cwd=root, + check=True, + capture_output=True, + text=True, + ) + except (OSError, subprocess.CalledProcessError) as exc: + raise ConsumingBoundaryError( + f"cannot verify git {' '.join(arguments)}" + ) from exc + return result.stdout.strip() + + +def _git_paths(root: Path, *arguments: str) -> set[str]: + return set(filter(None, _git(root, *arguments).splitlines())) + + +def verify_current_exact_main( + root: Path, + *, + observed_head: str | None = None, + observed_tracking_main: str | None = None, + observed_remote_main: str | None = None, +) -> str: + """Require HEAD to equal both fetched and live origin/main.""" + + head = observed_head or _git(root, "rev-parse", "HEAD") + tracking = observed_tracking_main or _git( + root, "rev-parse", "refs/remotes/origin/main" + ) + if observed_remote_main is None: + remote = _git(root, "ls-remote", "origin", "refs/heads/main") + fields = remote.split() + if len(fields) != 2 or fields[1] != "refs/heads/main": + raise ConsumingBoundaryError("live origin/main response malformed") + observed_remote_main = fields[0] + if head != tracking or head != observed_remote_main: + raise ConsumingBoundaryError( + "consuming boundary requires fresh exact origin/main" + ) + return head + + +def load_authority(root: Path = ROOT) -> dict[str, Any]: + authority = json.loads((root / AUTHORITY_PATH).read_text(encoding="utf-8")) + schema = json.loads((root / SCHEMA_PATH).read_text(encoding="utf-8")) + Draft202012Validator.check_schema(schema) + Draft202012Validator(schema).validate(authority) + return authority + + +def verify_bound_authority_bytes( + authority: Mapping[str, Any], root: Path = ROOT +) -> None: + records = authority.get("immutable_authorities") + if not isinstance(records, list): + raise ConsumingBoundaryError("immutable authority records missing") + for record in records: + if not isinstance(record, Mapping): + raise ConsumingBoundaryError("immutable authority record malformed") + relative = record.get("path") + expected = record.get("sha256") + if not isinstance(relative, str) or not isinstance(expected, str): + raise ConsumingBoundaryError("immutable authority identity malformed") + actual = _sha256(root / relative) + if actual != expected: + raise ConsumingBoundaryError( + f"bound authority bytes drifted: {relative}" + ) + + +def verify_candidate_cohort( + authority: Mapping[str, Any], candidate_root: Path +) -> None: + records = authority.get("candidate_cohort") + if not isinstance(records, list) or len(records) != 3: + raise ConsumingBoundaryError("candidate cohort must contain exactly three paths") + observed: set[str] = set() + for record in records: + if not isinstance(record, Mapping): + raise ConsumingBoundaryError("candidate cohort record malformed") + relative = record.get("path") + expected = record.get("sha256") + if not isinstance(relative, str) or not isinstance(expected, str): + raise ConsumingBoundaryError("candidate identity malformed") + if relative in observed: + raise ConsumingBoundaryError(f"duplicate candidate path: {relative}") + observed.add(relative) + if _sha256(candidate_root / relative) != expected: + raise ConsumingBoundaryError( + f"candidate cohort identity mismatch: {relative}" + ) + + +def observed_worktree_delta(root: Path) -> set[str]: + return ( + _git_paths(root, "diff", "--name-only", "--no-renames", "HEAD") + | _git_paths(root, "diff", "--cached", "--name-only", "--no-renames", "HEAD") + | _git_paths(root, "ls-files", "--others", "--exclude-standard") + ) + + +def verify_exact_candidate_delta( + authority: Mapping[str, Any], + candidate_root: Path, + *, + observed: set[str] | None = None, +) -> None: + scope = authority.get("scope") + if not isinstance(scope, Mapping): + raise ConsumingBoundaryError("authority scope missing") + expected = scope.get("combined_preflight_candidate_scope") + if not isinstance(expected, list) or not all( + isinstance(path, str) for path in expected + ): + raise ConsumingBoundaryError("candidate scope malformed") + actual = observed_worktree_delta(candidate_root) if observed is None else observed + if actual != set(expected): + raise ConsumingBoundaryError( + "exact candidate Git delta mismatch; " + f"missing={sorted(set(expected) - actual)!r}; " + f"extra={sorted(actual - set(expected))!r}" + ) + + +def verify_exact_authority_delta( + authority: Mapping[str, Any], + authority_root: Path, + *, + committed: bool, + observed: set[str] | None = None, +) -> None: + scope = authority.get("scope") + if not isinstance(scope, Mapping): + raise ConsumingBoundaryError("authority scope missing") + expected = scope.get("authority_write_scope") + if not isinstance(expected, list) or not all( + isinstance(path, str) for path in expected + ): + raise ConsumingBoundaryError("authority write scope malformed") + if observed is None: + if committed: + base = authority.get("authority_base_sha") + if not isinstance(base, str): + raise ConsumingBoundaryError("authority base malformed") + if subprocess.run( + ("git", "merge-base", "--is-ancestor", base, "HEAD"), + cwd=authority_root, + check=False, + capture_output=True, + ).returncode: + raise ConsumingBoundaryError("authority base is not an ancestor") + actual = _git_paths( + authority_root, + "diff", + "--name-only", + "--no-renames", + f"{base}...HEAD", + ) + verify_current_exact_main(authority_root) + else: + actual = observed_worktree_delta(authority_root) + else: + actual = observed + if actual != set(expected): + raise ConsumingBoundaryError( + "exact authority Git delta mismatch; " + f"missing={sorted(set(expected) - actual)!r}; " + f"extra={sorted(actual - set(expected))!r}" + ) + + +def verify_combined_preflight( + authority_root: Path, + candidate_root: Path, + *, + authority_committed: bool, +) -> dict[str, Any]: + authority = load_authority(authority_root) + verify_bound_authority_bytes(authority, authority_root) + verify_exact_authority_delta( + authority, authority_root, committed=authority_committed + ) + verify_candidate_cohort(authority, candidate_root) + verify_exact_candidate_delta(authority, candidate_root) + worker = authority["worker"] + if _git(candidate_root, "rev-parse", "HEAD") != worker[ + "prequalification_base_sha" + ]: + raise ConsumingBoundaryError("worker prequalification base drifted") + return { + "authority_schema": authority["schema"], + "authority_status": authority["status"], + "authority_base_sha": authority["authority_base_sha"], + "candidate_paths": [record["path"] for record in authority["candidate_cohort"]], + "candidate_sha256": { + record["path"]: record["sha256"] for record in authority["candidate_cohort"] + }, + "launch_authorized_in_authority_task": False, + "token_consumed": False, + "output_artifacts_created": False, + "verification": "passed", + } + + +def verify_post_merge_candidate_head( + authority: Mapping[str, Any], candidate_root: Path +) -> str: + """Require the frozen launch lane at exact merged main above its proof base.""" + + worker = authority.get("worker") + if not isinstance(worker, Mapping): + raise ConsumingBoundaryError("worker binding missing") + base = worker.get("prequalification_base_sha") + if not isinstance(base, str) or len(base) != 40: + raise ConsumingBoundaryError("prequalification base malformed") + head = verify_current_exact_main(candidate_root) + if head == base: + raise ConsumingBoundaryError( + "consuming authority is not present in candidate HEAD" + ) + result = subprocess.run( + ("git", "merge-base", "--is-ancestor", base, head), + cwd=candidate_root, + check=False, + capture_output=True, + ) + if result.returncode: + raise ConsumingBoundaryError( + "prequalification base is not an ancestor of exact merged main" + ) + return head + + +def evaluate_prelaunch( + authority: Mapping[str, Any], observation: Mapping[str, Any] +) -> dict[str, Any]: + expected = { + "cwd": authority["worker"]["frozen_cwd"], + "argv": authority["launch_contract"]["argv"], + "environment": authority["launch_contract"]["environment"]["required"], + "interpreter": ( + authority["worker"]["frozen_cwd"] + "/.venv/bin/python" + ), + "venv_prefix": authority["worker"]["frozen_cwd"] + "/.venv", + "prequalification_base_sha": authority["worker"][ + "prequalification_base_sha" + ], + "candidate_head_transition": ( + "non_destructive_fast_forward_to_exact_merged_main" + ), + "matching_processes": [], + "output_paths_present": [], + "receipt": "absent", + "token_status": "unspent_unavailable", + "token_consumed": False, + "retry": "none", + "restart": "none", + "replacement": "none", + "authority_integrity": "passed", + "candidate_cohort": "passed", + "candidate_delta": "passed", + "synthetic_fixture": True, + } + for field, value in expected.items(): + if observation.get(field) != value: + raise ConsumingBoundaryError(f"prelaunch gate failed: {field}") + capacity = observation.get("disk_available_bytes") + if not isinstance(capacity, int) or capacity < MINIMUM_CAPACITY_BYTES: + raise ConsumingBoundaryError("prelaunch gate failed: disk_available_bytes") + forbidden = authority["launch_contract"]["environment"]["forbidden"] + if any( + name in observation.get("environment_present", {}) + for name in forbidden + if name != "real Codex log or database paths" + ): + raise ConsumingBoundaryError("prelaunch gate failed: forbidden environment") + if observation.get("live_or_real_data") is not False: + raise ConsumingBoundaryError("prelaunch gate failed: live_or_real_data") + return { + "decision": "launch_authorized_once", + "run_token_id": authority["run_token"]["id"], + "maximum_new_end_to_end_runs": 1, + "consume_only_after_successful_child_handshake": True, + "refund": False, + "retry": "none", + "restart": "none", + "replacement": "none", + } + + +def _normalized_argv(argv: Sequence[str], cwd: Path) -> tuple[str, ...]: + values = list(argv) + indexes = {0, 1} + if "--output" in values: + indexes.add(values.index("--output") + 1) + return tuple( + str((cwd / value).absolute()) if index in indexes else value + for index, value in enumerate(values) + ) + + +def _process_cwd(pid: int) -> Path | None: + command = shutil.which("lsof") or "/usr/sbin/lsof" + result = subprocess.run( + (command, "-a", "-p", str(pid), "-d", "cwd", "-Fn"), + check=False, + capture_output=True, + text=True, + ) + for line in result.stdout.splitlines(): + if line.startswith("n"): + return Path(line[1:]).resolve() + return None + + +def _matching_processes(argv: Sequence[str], cwd: Path) -> list[dict[str, Any]]: + expected = _normalized_argv(argv, cwd) + owner = getpass.getuser() + result = subprocess.run( + ("ps", "-ww", "-axo", "pid=,user=,command="), + check=True, + capture_output=True, + text=True, + ) + matches: list[dict[str, Any]] = [] + for line in result.stdout.splitlines(): + parts = line.strip().split(None, 2) + if len(parts) != 3: + continue + pid_text, user, command = parts + if user != owner: + continue + try: + pid = int(pid_text) + process_argv = shlex.split(command) + except ValueError: + continue + if pid == os.getpid() or _normalized_argv(process_argv, cwd) != expected: + continue + process_cwd = _process_cwd(pid) + if process_cwd is None: + raise ConsumingBoundaryError( + f"cannot verify cwd of matching process {pid}" + ) + if process_cwd == cwd: + matches.append({"pid": pid, "owner": user, "cwd": str(process_cwd)}) + return matches + + +def observe_live_prelaunch( + authority_root: Path, candidate_root: Path +) -> dict[str, Any]: + authority = load_authority(authority_root) + verify_bound_authority_bytes(authority, authority_root) + verify_exact_authority_delta(authority, authority_root, committed=True) + verify_candidate_cohort(authority, candidate_root) + verify_exact_candidate_delta(authority, candidate_root) + verify_post_merge_candidate_head(authority, candidate_root) + + cwd = candidate_root.absolute() + required = authority["launch_contract"]["environment"]["required"] + exclusive = authority["launch_contract"]["exclusive_paths"] + output_paths_present = [ + relative for relative in exclusive.values() if (cwd / relative).exists() + ] + output_parent = (cwd / exclusive["output"]).parent + if not output_parent.is_dir(): + raise ConsumingBoundaryError("prelaunch gate failed: output parent absent") + observation = { + "cwd": str(cwd), + "argv": authority["launch_contract"]["argv"], + "environment": {name: os.environ.get(name) for name in required}, + "environment_present": dict(os.environ), + "interpreter": str(Path(sys.executable).absolute()), + "venv_prefix": str(Path(sys.prefix).absolute()), + "prequalification_base_sha": authority["worker"][ + "prequalification_base_sha" + ], + "candidate_head_transition": ( + "non_destructive_fast_forward_to_exact_merged_main" + ), + "matching_processes": _matching_processes( + authority["launch_contract"]["argv"], cwd + ), + "output_paths_present": output_paths_present, + "receipt": "absent", + "token_status": "unspent_unavailable", + "token_consumed": False, + "retry": "none", + "restart": "none", + "replacement": "none", + "authority_integrity": "passed", + "candidate_cohort": "passed", + "candidate_delta": "passed", + "synthetic_fixture": True, + "live_or_real_data": False, + "disk_available_bytes": shutil.disk_usage(cwd).free, + } + return evaluate_prelaunch(authority, observation) + + +def main() -> int: + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers(dest="command", required=True) + combined = subparsers.add_parser("combined") + combined.add_argument("--authority-root", type=Path, required=True) + combined.add_argument("--candidate-root", type=Path, required=True) + combined.add_argument("--authority-committed", action="store_true") + preflight = subparsers.add_parser("preflight") + preflight.add_argument("--authority-root", type=Path, required=True) + preflight.add_argument("--candidate-root", type=Path, required=True) + arguments = parser.parse_args() + if arguments.command == "combined": + result = verify_combined_preflight( + arguments.authority_root, + arguments.candidate_root, + authority_committed=arguments.authority_committed, + ) + else: + result = observe_live_prelaunch( + arguments.authority_root, + arguments.candidate_root, + ) + print(json.dumps(result, sort_keys=True, separators=(",", ":"))) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/ck07r1_shared_successor_overlay.py b/scripts/ck07r1_shared_successor_overlay.py index dab7f974..39d1d855 100644 --- a/scripts/ck07r1_shared_successor_overlay.py +++ b/scripts/ck07r1_shared_successor_overlay.py @@ -4,6 +4,7 @@ import hashlib import json +import shutil import subprocess from collections.abc import Mapping from pathlib import Path @@ -14,7 +15,13 @@ ROOT = Path(__file__).resolve().parents[1] AUTHORITY_PATH = "docs/decisions/evidence/ck07r1a0/shared-successor-overlay-authority-v1.json" SCHEMA_PATH = AUTHORITY_PATH.removesuffix(".json") + ".schema.json" +CONSUMING_AUTHORITY_PATH = ( + "docs/decisions/evidence/ck07r1a0/" + "lifecycle-consuming-boundary-authority-v1.json" +) +CONSUMING_SCHEMA_PATH = CONSUMING_AUTHORITY_PATH.removesuffix(".json") + ".schema.json" PREPARATION_PATH = "src/codex_usage_tracker/agent_kernel/publication/preparation.py" +MINIMUM_CAPACITY_BYTES = 10 * 1024**3 class SharedSuccessorOverlayError(RuntimeError): @@ -42,6 +49,195 @@ def load_overlay(root: Path = ROOT) -> dict[str, Any]: return authority +def load_consuming_boundary(root: Path = ROOT) -> dict[str, Any] | None: + """Load the complete additive consuming authority, or reject a partial pair.""" + + authority_path = root / CONSUMING_AUTHORITY_PATH + schema_path = root / CONSUMING_SCHEMA_PATH + if not authority_path.exists() and not schema_path.exists(): + return None + if not authority_path.is_file() or not schema_path.is_file(): + raise SharedSuccessorOverlayError( + "partial CK-07R1 consuming-boundary authority" + ) + authority = json.loads(authority_path.read_text(encoding="utf-8")) + schema = json.loads(schema_path.read_text(encoding="utf-8")) + Draft202012Validator.check_schema(schema) + Draft202012Validator(schema).validate(authority) + immutable = authority.get("immutable_authorities") + if not isinstance(immutable, list): + raise SharedSuccessorOverlayError("consuming-boundary bindings missing") + for record in immutable: + if not isinstance(record, Mapping): + raise SharedSuccessorOverlayError( + "consuming-boundary binding malformed" + ) + relative = record.get("path") + expected = record.get("sha256") + if not isinstance(relative, str) or not isinstance(expected, str): + raise SharedSuccessorOverlayError( + "consuming-boundary identity malformed" + ) + if sha256_path(root, relative) != expected: + raise SharedSuccessorOverlayError( + f"consuming-boundary bound bytes drifted: {relative}" + ) + return authority + + +def _consuming_authority_scope( + consuming: Mapping[str, Any] | None, +) -> set[str]: + if consuming is None: + return set() + scope = consuming.get("scope") + if not isinstance(scope, Mapping): + raise SharedSuccessorOverlayError("consuming-boundary scope missing") + paths = scope.get("authority_write_scope") + if not isinstance(paths, list) or not all(isinstance(path, str) for path in paths): + raise SharedSuccessorOverlayError("consuming-boundary scope malformed") + return set(paths) + + +def _git_text(root: Path, *arguments: str) -> str: + try: + result = subprocess.run( + ("git", *arguments), + cwd=root, + check=True, + capture_output=True, + text=True, + ) + except (OSError, subprocess.CalledProcessError) as exc: + raise SharedSuccessorOverlayError( + f"cannot verify git {' '.join(arguments)}" + ) from exc + return result.stdout.strip() + + +def verify_current_exact_main( + root: Path, + *, + observed_head: str | None = None, + observed_tracking_main: str | None = None, + observed_remote_main: str | None = None, +) -> str: + """Require HEAD to equal both fetched and live origin/main.""" + + head = observed_head or _git_text(root, "rev-parse", "HEAD") + tracking = observed_tracking_main or _git_text( + root, "rev-parse", "refs/remotes/origin/main" + ) + if observed_remote_main is None: + remote = _git_text(root, "ls-remote", "origin", "refs/heads/main") + fields = remote.split() + if len(fields) != 2 or fields[1] != "refs/heads/main": + raise SharedSuccessorOverlayError("live origin/main response malformed") + observed_remote_main = fields[0] + if head != tracking or head != observed_remote_main: + raise SharedSuccessorOverlayError( + "consuming-boundary requires fresh exact origin/main" + ) + return head + + +def verify_consuming_boundary_activation( + overlay: Mapping[str, Any], + consuming: Mapping[str, Any], + root: Path, + *, + observed_head: str | None = None, + observed_tracking_main: str | None = None, + observed_remote_main: str | None = None, + observed_capacity_bytes: int | None = None, + observed_base_is_ancestor: bool | None = None, +) -> None: + """Enforce repository/runtime gates without claiming worker authentication.""" + + transition = consuming.get("transition") + governance = consuming.get("governance") + worker = consuming.get("worker") + if ( + not isinstance(transition, Mapping) + or not isinstance(governance, Mapping) + or not isinstance(worker, Mapping) + ): + raise SharedSuccessorOverlayError("consuming-boundary activation malformed") + if ( + transition.get("from") != "worker_prequalification" + or transition.get("to") != "launch_authorized_once" + or transition.get("launch_authorized") is not True + or transition.get("candidate_head_transition") + != "after_merge_fetch_then_non_destructive_fast_forward_only_from_prequalification_base_to_exact_merged_main_while_preserving_and_recomputing_the_exact_three_dirty_candidate_bytes" + or transition.get("runtime_acceptance") != "not_claimed" + ): + raise SharedSuccessorOverlayError("consuming-boundary transition drifted") + if ( + governance.get("worker_identity") + != "normative_coordinator_orchestration_binding_to_exact_existing_thread_and_repository_evidence" + or governance.get("runtime_attestation") + != "not_required_not_claimed_and_no_cryptographic_per_task_credential_available" + or worker.get("identity_enforcement") + != "normative_coordinator_orchestration_binding_not_runtime_authentication" + or worker.get("runtime_identity_claim") != "none" + ): + raise SharedSuccessorOverlayError( + "consuming-boundary worker orchestration policy drifted" + ) + if str(root.absolute()) != worker.get("frozen_cwd"): + raise SharedSuccessorOverlayError("consuming-boundary frozen cwd drifted") + head = verify_current_exact_main( + root, + observed_head=observed_head, + observed_tracking_main=observed_tracking_main, + observed_remote_main=observed_remote_main, + ) + base = worker.get("prequalification_base_sha") + if not isinstance(base, str) or len(base) != 40 or head == base: + raise SharedSuccessorOverlayError( + "consuming-boundary merged-main transition missing" + ) + if observed_base_is_ancestor is None: + observed_base_is_ancestor = ( + subprocess.run( + ("git", "merge-base", "--is-ancestor", base, head), + cwd=root, + check=False, + capture_output=True, + ).returncode + == 0 + ) + if not observed_base_is_ancestor: + raise SharedSuccessorOverlayError( + "consuming-boundary prequalification base is not an ancestor" + ) + capacity = ( + shutil.disk_usage(root).free + if observed_capacity_bytes is None + else observed_capacity_bytes + ) + if capacity < MINIMUM_CAPACITY_BYTES: + raise SharedSuccessorOverlayError( + "consuming-boundary capacity below 10 GiB" + ) + states = overlay.get("states") + candidate = consuming.get("candidate_cohort") + if not isinstance(states, Mapping) or not isinstance(candidate, list): + raise SharedSuccessorOverlayError("consuming-boundary candidate malformed") + successor = states.get("successor") + if not isinstance(successor, Mapping): + raise SharedSuccessorOverlayError("overlay successor missing") + overlay_identity = [ + {"path": record.get("path"), "sha256": record.get("sha256")} + for record in successor.get("artifacts", []) + if isinstance(record, Mapping) + ] + if candidate != overlay_identity: + raise SharedSuccessorOverlayError( + "consuming-boundary candidate does not match exact overlay successor" + ) + + def verify_bound_authority_bytes( authority: Mapping[str, Any], root: Path = ROOT, @@ -205,7 +401,11 @@ def verify_exact_worktree_delta( actual = observed_worktree_delta(root) if observed is None else set(observed) expected = expected_worktree_delta(authority, state) - if actual != expected: + consuming_scope = _consuming_authority_scope(load_consuming_boundary(root)) + additive_authority_preflight = ( + state == "authority_main" and bool(consuming_scope) and actual == consuming_scope + ) + if actual != expected and not additive_authority_preflight: missing = sorted(expected - actual) extra = sorted(actual - expected) raise SharedSuccessorOverlayError( @@ -256,10 +456,17 @@ def verify_exact_committed_delta( if observed is None else set(observed) ) - expected = set(authority_paths) - if actual != expected: - missing = sorted(expected - actual) - extra = sorted(actual - expected) + predecessor_expected = set(authority_paths) + consuming_scope = _consuming_authority_scope(load_consuming_boundary(root)) + successor_expected = predecessor_expected | consuming_scope + additive_authority_preflight = ( + actual == predecessor_expected + and bool(consuming_scope) + and observed_worktree_delta(root) == consuming_scope + ) + if actual != successor_expected and not additive_authority_preflight: + missing = sorted(successor_expected - actual) + extra = sorted(actual - successor_expected) raise SharedSuccessorOverlayError( f"exact committed authority delta mismatch; missing={missing!r}; " f"extra={extra!r}" @@ -358,12 +565,20 @@ def verify_shared_successor_overlay( observed_candidate_artifacts(authority, root), ) verify_exact_worktree_delta(authority, state, root) + consuming = load_consuming_boundary(root) + if state == "worker_prequalification": + if consuming is None: + raise SharedSuccessorOverlayError( + "consuming-boundary authority unavailable" + ) + verify_consuming_boundary_activation(authority, consuming, root) return authority, state def overlay_changed_path_allowance( authority: Mapping[str, Any], state: str, + root: Path = ROOT, ) -> set[str]: """Return exact base-to-HEAD paths admitted for an authority/preflight lane.""" @@ -377,6 +592,7 @@ def overlay_changed_path_allowance( raise SharedSuccessorOverlayError("authority write scope malformed") allowed = set(authority_paths) + allowed.update(_consuming_authority_scope(load_consuming_boundary(root))) if state == "worker_prequalification": allowed.update(expected_worktree_delta(authority, state)) elif state != "authority_main": diff --git a/tests/kernel/test_ck07r1_consuming_boundary_authority.py b/tests/kernel/test_ck07r1_consuming_boundary_authority.py new file mode 100644 index 00000000..2d14c65d --- /dev/null +++ b/tests/kernel/test_ck07r1_consuming_boundary_authority.py @@ -0,0 +1,410 @@ +from __future__ import annotations + +import hashlib +import json +import subprocess +from copy import deepcopy +from pathlib import Path +from typing import Any + +import pytest +from jsonschema import Draft202012Validator + +from scripts.ck07r1_consuming_boundary import ( + AUTHORITY_PATH, + MINIMUM_CAPACITY_BYTES, + SCHEMA_PATH, + ConsumingBoundaryError, + evaluate_prelaunch, + load_authority, + verify_bound_authority_bytes, + verify_candidate_cohort, + verify_current_exact_main, + verify_exact_authority_delta, + verify_exact_candidate_delta, + verify_post_merge_candidate_head, +) + +ROOT = Path(__file__).resolve().parents[2] + + +def _authority() -> dict[str, Any]: + return load_authority(ROOT) + + +def _valid_observation(authority: dict[str, Any]) -> dict[str, Any]: + cwd = authority["worker"]["frozen_cwd"] + return { + "cwd": cwd, + "argv": authority["launch_contract"]["argv"], + "environment": authority["launch_contract"]["environment"]["required"], + "environment_present": authority["launch_contract"]["environment"]["required"], + "interpreter": cwd + "/.venv/bin/python", + "venv_prefix": cwd + "/.venv", + "prequalification_base_sha": authority["worker"][ + "prequalification_base_sha" + ], + "candidate_head_transition": ( + "non_destructive_fast_forward_to_exact_merged_main" + ), + "matching_processes": [], + "output_paths_present": [], + "receipt": "absent", + "token_status": "unspent_unavailable", + "token_consumed": False, + "retry": "none", + "restart": "none", + "replacement": "none", + "authority_integrity": "passed", + "candidate_cohort": "passed", + "candidate_delta": "passed", + "synthetic_fixture": True, + "live_or_real_data": False, + "disk_available_bytes": MINIMUM_CAPACITY_BYTES, + } + + +def test_consuming_boundary_schema_is_strict_and_exact() -> None: + authority = _authority() + schema = json.loads((ROOT / SCHEMA_PATH).read_text(encoding="utf-8")) + Draft202012Validator.check_schema(schema) + Draft202012Validator(schema).validate(authority) + assert authority["schema"].endswith(".v1") + assert authority["authority_base_sha"] == ( + "67bb1a36255b05634ee18c615e57cb01dbe0ebda" + ) + assert authority["status"] == "permitted_not_accepted" + assert authority["transition"]["launch_authorized"] is True + assert authority["transition"]["runtime_acceptance"] == "not_claimed" + assert authority["governance"]["worker_identity"].startswith( + "normative_coordinator_orchestration_binding" + ) + assert authority["worker"]["runtime_identity_claim"] == "none" + + +def test_consuming_boundary_preserves_every_bound_authority_byte() -> None: + verify_bound_authority_bytes(_authority(), ROOT) + + +def test_consuming_boundary_binds_only_exact_atomic_candidate() -> None: + authority = _authority() + assert [record["sha256"] for record in authority["candidate_cohort"]] == [ + "66c015de949a6c380bd49964cb6c48c30dee64ecb14074b480837c44024328ea", + "f108dbb45d7586a15eb370c94fc124268a249f2f6f1ee97e7b8b28a3874b737c", + "4c51488988397e0ccaf40266a4f68bb1d6d342e4be1db36dd1cf36ab63aa335a", + ] + verify_exact_candidate_delta( + authority, + ROOT, + observed=set(authority["scope"]["combined_preflight_candidate_scope"]), + ) + for changed in ( + set(), + {authority["scope"]["combined_preflight_candidate_scope"][0]}, + { + *authority["scope"]["combined_preflight_candidate_scope"], + "docs/decisions/evidence/ckqg1/maintainability-baseline-transition-authority.json", + }, + ): + with pytest.raises(ConsumingBoundaryError, match="candidate Git delta"): + verify_exact_candidate_delta(authority, ROOT, observed=changed) + + +def test_authority_delta_rejects_missing_and_extra_paths() -> None: + authority = _authority() + expected = set(authority["scope"]["authority_write_scope"]) + verify_exact_authority_delta(authority, ROOT, committed=False, observed=expected) + for changed in ( + expected - {next(iter(expected))}, + expected | {"src/codex_usage_tracker/agent_kernel/publication/writer.py"}, + ): + with pytest.raises(ConsumingBoundaryError, match="authority Git delta"): + verify_exact_authority_delta( + authority, ROOT, committed=False, observed=changed + ) + + +@pytest.mark.parametrize( + ("field", "replacement"), + [ + ("cwd", "/wrong/worktree"), + ("argv", [".venv/bin/python", "wrong.py"]), + ("environment", {"LC_ALL": "C"}), + ("interpreter", "/usr/bin/python3"), + ("venv_prefix", "/wrong/.venv"), + ("prequalification_base_sha", "0" * 40), + ("candidate_head_transition", "stale_prequalification_head"), + ("matching_processes", [{"pid": 123}]), + ("output_paths_present", ["output/ck07r1/lifecycle-requalification-v1.json"]), + ("receipt", {"fabricated": True}), + ("token_status", "consumed"), + ("token_consumed", True), + ("retry", "allowed"), + ("restart", "allowed"), + ("replacement", "allowed"), + ("authority_integrity", "failed"), + ("candidate_cohort", "partial"), + ("candidate_delta", "extra"), + ("synthetic_fixture", False), + ("live_or_real_data", True), + ("disk_available_bytes", MINIMUM_CAPACITY_BYTES - 1), + ], +) +def test_prelaunch_negative_mutations_fail_closed( + field: str, replacement: Any +) -> None: + authority = _authority() + observation = _valid_observation(authority) + observation[field] = replacement + with pytest.raises(ConsumingBoundaryError, match="prelaunch gate failed"): + evaluate_prelaunch(authority, observation) + + +def test_forbidden_environment_fails_closed() -> None: + authority = _authority() + observation = _valid_observation(authority) + observation["environment_present"] = { + **observation["environment_present"], + "CODEX_HOME": "/synthetic/not-used", + } + with pytest.raises(ConsumingBoundaryError, match="forbidden environment"): + evaluate_prelaunch(authority, observation) + + +def test_exact_prelaunch_authorizes_only_one_nonrefundable_launch() -> None: + authority = _authority() + decision = evaluate_prelaunch(authority, _valid_observation(authority)) + assert decision == { + "decision": "launch_authorized_once", + "run_token_id": "ck07r1-all-profile-e2e-1", + "maximum_new_end_to_end_runs": 1, + "consume_only_after_successful_child_handshake": True, + "refund": False, + "retry": "none", + "restart": "none", + "replacement": "none", + } + assert authority["run_token"]["prelaunch_status"] == "unspent_unavailable" + assert authority["run_token"]["token_consumed"] is False + + +def test_live_authorization_requires_fetched_and_remote_exact_main() -> None: + exact_main = "a" * 40 + assert ( + verify_current_exact_main( + ROOT, + observed_head=exact_main, + observed_tracking_main=exact_main, + observed_remote_main=exact_main, + ) + == exact_main + ) + with pytest.raises(ConsumingBoundaryError, match="fresh exact"): + verify_current_exact_main( + ROOT, + observed_head=exact_main, + observed_tracking_main=exact_main, + observed_remote_main="b" * 40, + ) + + +def test_physical_post_merge_fast_forward_preserves_exact_dirty_cohort( + tmp_path: Path, +) -> None: + remote = tmp_path / "remote.git" + seed = tmp_path / "seed" + candidate = tmp_path / "candidate" + subprocess.run(("git", "init", "--bare", str(remote)), check=True) + seed.mkdir() + subprocess.run(("git", "init"), cwd=seed, check=True, capture_output=True) + subprocess.run( + ("git", "config", "user.email", "synthetic@example.invalid"), + cwd=seed, + check=True, + ) + subprocess.run( + ("git", "config", "user.name", "Synthetic Test"), + cwd=seed, + check=True, + ) + preparation = ( + seed / "src/codex_usage_tracker/agent_kernel/publication/preparation.py" + ) + preparation.parent.mkdir(parents=True) + preparation.write_text("predecessor\n", encoding="utf-8") + subprocess.run(("git", "add", "."), cwd=seed, check=True) + subprocess.run( + ("git", "commit", "-m", "base"), + cwd=seed, + check=True, + capture_output=True, + ) + base = subprocess.run( + ("git", "rev-parse", "HEAD"), + cwd=seed, + check=True, + capture_output=True, + text=True, + ).stdout.strip() + subprocess.run(("git", "branch", "-M", "main"), cwd=seed, check=True) + subprocess.run( + ("git", "remote", "add", "origin", str(remote)), + cwd=seed, + check=True, + ) + subprocess.run( + ("git", "push", "-u", "origin", "main"), + cwd=seed, + check=True, + capture_output=True, + ) + (seed / "authority.txt").write_text("merged authority\n", encoding="utf-8") + subprocess.run(("git", "add", "authority.txt"), cwd=seed, check=True) + subprocess.run( + ("git", "commit", "-m", "authority"), + cwd=seed, + check=True, + capture_output=True, + ) + merged = subprocess.run( + ("git", "rev-parse", "HEAD"), + cwd=seed, + check=True, + capture_output=True, + text=True, + ).stdout.strip() + subprocess.run( + ("git", "push", "origin", "main"), + cwd=seed, + check=True, + capture_output=True, + ) + subprocess.run( + ("git", "clone", "--branch", "main", str(remote), str(candidate)), + check=True, + capture_output=True, + ) + subprocess.run( + ("git", "checkout", "--detach", base), + cwd=candidate, + check=True, + capture_output=True, + ) + + authority = deepcopy(_authority()) + authority["worker"]["prequalification_base_sha"] = base + authority["worker"]["frozen_cwd"] = str(candidate) + contents = (b"successor preparation\n", b"benchmark\n", b"lifecycle test\n") + before: dict[str, str] = {} + for record, content in zip(authority["candidate_cohort"], contents, strict=True): + path = candidate / record["path"] + path.parent.mkdir(parents=True, exist_ok=True) + path.write_bytes(content) + record["sha256"] = hashlib.sha256(content).hexdigest() + before[record["path"]] = record["sha256"] + + subprocess.run( + ("git", "merge", "--ff-only", merged), + cwd=candidate, + check=True, + capture_output=True, + ) + assert verify_post_merge_candidate_head(authority, candidate) == merged + verify_candidate_cohort(authority, candidate) + verify_exact_candidate_delta(authority, candidate) + assert { + record["path"]: hashlib.sha256( + (candidate / record["path"]).read_bytes() + ).hexdigest() + for record in authority["candidate_cohort"] + } == before + + +def test_schema_rejects_scope_status_acceptance_and_launch_weakening() -> None: + authority = _authority() + schema = json.loads((ROOT / SCHEMA_PATH).read_text(encoding="utf-8")) + mutations = [ + lambda value: value.__setitem__("status", "final_accepted"), + lambda value: value["approval"].__setitem__( + "runtime_acceptance", "accepted" + ), + lambda value: value["worker"].__setitem__( + "thread_id", "replacement-worker" + ), + lambda value: value["worker"].__setitem__( + "runtime_identity_claim", "self_asserted_runtime_identity" + ), + lambda value: value["governance"].__setitem__( + "runtime_attestation", "required" + ), + lambda value: value["candidate_cohort"].pop(), + lambda value: value["candidate_cohort"].append( + {"path": "extra.py", "sha256": "0" * 64} + ), + lambda value: value["run_token"].__setitem__( + "maximum_new_end_to_end_runs", 2 + ), + lambda value: value["run_token"].__setitem__("refund", True), + lambda value: value["run_token"].__setitem__("retry", "allowed"), + lambda value: value["launch_contract"].__setitem__("cwd", "/wrong"), + lambda value: value["transition"].__setitem__( + "candidate_head_transition", "reset_or_rebase" + ), + lambda value: value["scope"]["authority_write_scope"].append( + "src/codex_usage_tracker/agent_kernel/publication/writer.py" + ), + lambda value: value["scope"]["combined_preflight_candidate_scope"].pop(), + lambda value: value["failure_policy"].__setitem__( + "fabricated_receipt", "allow" + ), + lambda value: value["failure_policy"].__setitem__( + "non_fast_forward_or_candidate_byte_drift", "allow" + ), + ] + for mutate in mutations: + changed = deepcopy(authority) + mutate(changed) + assert list(Draft202012Validator(schema).iter_errors(changed)) + + +def test_candidate_byte_verification_rejects_other_digest( + tmp_path: Path, +) -> None: + authority = deepcopy(_authority()) + for index, record in enumerate(authority["candidate_cohort"]): + path = tmp_path / record["path"] + path.parent.mkdir(parents=True, exist_ok=True) + path.write_bytes(f"synthetic candidate {index}\n".encode()) + record["sha256"] = hashlib.sha256(path.read_bytes()).hexdigest() + first = tmp_path / authority["candidate_cohort"][0]["path"] + first.write_bytes(b"other synthetic digest\n") + with pytest.raises(ConsumingBoundaryError, match="identity mismatch"): + verify_candidate_cohort(authority, tmp_path) + + +def test_authority_task_itself_remains_non_consuming() -> None: + authority = _authority() + assert authority["approval"]["implementation_acceptance"] == "not_claimed" + assert authority["approval"]["runtime_acceptance"] == "not_claimed" + assert authority["run_token"]["token_consumed"] is False + assert "token_consumption_or_child_launch_in_the_authority_task" in authority[ + "scope" + ]["forbidden"] + assert Path(AUTHORITY_PATH).name.endswith("-v1.json") + + +def test_worker_ownership_is_orchestration_bound_not_runtime_self_asserted() -> None: + authority = _authority() + script = (ROOT / "scripts/ck07r1_consuming_boundary.py").read_text( + encoding="utf-8" + ) + assert authority["worker"]["thread_id"] == ( + "019fbfe2-8fe4-7de2-9264-d58572366727" + ) + assert authority["worker"]["identity_enforcement"].endswith( + "not_runtime_authentication" + ) + assert authority["governance"]["runtime_attestation"].startswith( + "not_required_not_claimed" + ) + assert "--worker-id" not in script diff --git a/tests/kernel/test_ck07r1_shared_successor_overlay.py b/tests/kernel/test_ck07r1_shared_successor_overlay.py index c302a5e1..f2741d4b 100644 --- a/tests/kernel/test_ck07r1_shared_successor_overlay.py +++ b/tests/kernel/test_ck07r1_shared_successor_overlay.py @@ -7,17 +7,22 @@ import pytest from jsonschema import Draft202012Validator +import scripts.ck07r1_shared_successor_overlay as overlay_module from scripts.ck07r1_shared_successor_overlay import ( + CONSUMING_AUTHORITY_PATH, ROOT, SCHEMA_PATH, SharedSuccessorOverlayError, classify_observed_state, expected_worktree_delta, + load_consuming_boundary, load_overlay, observed_candidate_artifacts, overlay_changed_path_allowance, sha256_path, verify_bound_authority_bytes, + verify_consuming_boundary_activation, + verify_current_exact_main, verify_exact_committed_delta, verify_exact_worktree_delta, verify_launcher_safety_contract, @@ -65,7 +70,171 @@ def test_overlay_is_exact_and_live_state_is_authorized() -> None: "data_policy": "synthetic_only", } state_key = "predecessor" if state == "authority_main" else "successor" - assert observed_candidate_artifacts(authority) == _state_observed(authority, state_key) + assert observed_candidate_artifacts(authority) == _state_observed( + authority, state_key + ) + + +def test_complete_consuming_boundary_is_the_only_additive_authority_delta() -> None: + overlay = load_overlay() + consuming = load_consuming_boundary() + assert consuming is not None + scope = set(consuming["scope"]["authority_write_scope"]) + predecessor_scope = set(overlay["scope"]["authority_write_scope"]) + + verify_exact_worktree_delta( + overlay, "authority_main", observed=scope + ) + verify_exact_committed_delta( + overlay, + observed=predecessor_scope | scope, + base_is_ancestor=True, + ) + for changed in ( + scope - {next(iter(scope))}, + scope | {"src/codex_usage_tracker/agent_kernel/publication/writer.py"}, + ): + with pytest.raises(SharedSuccessorOverlayError, match="Git delta mismatch"): + verify_exact_worktree_delta( + overlay, "authority_main", observed=changed + ) + + +def test_partial_consuming_boundary_pair_fails_closed(tmp_path: Path) -> None: + path = tmp_path / CONSUMING_AUTHORITY_PATH + path.parent.mkdir(parents=True) + path.write_text("{}\n", encoding="utf-8") + with pytest.raises(SharedSuccessorOverlayError, match="partial"): + load_consuming_boundary(tmp_path) + + +def test_consuming_activation_requires_exact_main_cwd_capacity_and_cohort() -> None: + overlay = load_overlay() + consuming = load_consuming_boundary() + assert consuming is not None + frozen_root = Path(consuming["worker"]["frozen_cwd"]) + exact_main = "a" * 40 + + verify_consuming_boundary_activation( + overlay, + consuming, + frozen_root, + observed_head=exact_main, + observed_tracking_main=exact_main, + observed_remote_main=exact_main, + observed_capacity_bytes=10 * 1024**3, + observed_base_is_ancestor=True, + ) + with pytest.raises(SharedSuccessorOverlayError, match="fresh exact"): + verify_current_exact_main( + frozen_root, + observed_head=exact_main, + observed_tracking_main=exact_main, + observed_remote_main="b" * 40, + ) + with pytest.raises(SharedSuccessorOverlayError, match="frozen cwd"): + verify_consuming_boundary_activation( + overlay, + consuming, + Path("/wrong/worktree"), + observed_head=exact_main, + observed_tracking_main=exact_main, + observed_remote_main=exact_main, + observed_capacity_bytes=10 * 1024**3, + observed_base_is_ancestor=True, + ) + with pytest.raises(SharedSuccessorOverlayError, match="capacity"): + verify_consuming_boundary_activation( + overlay, + consuming, + frozen_root, + observed_head=exact_main, + observed_tracking_main=exact_main, + observed_remote_main=exact_main, + observed_capacity_bytes=10 * 1024**3 - 1, + observed_base_is_ancestor=True, + ) + with pytest.raises(SharedSuccessorOverlayError, match="not an ancestor"): + verify_consuming_boundary_activation( + overlay, + consuming, + frozen_root, + observed_head=exact_main, + observed_tracking_main=exact_main, + observed_remote_main=exact_main, + observed_capacity_bytes=10 * 1024**3, + observed_base_is_ancestor=False, + ) + changed = deepcopy(consuming) + changed["worker"]["runtime_identity_claim"] = "self_asserted" + with pytest.raises(SharedSuccessorOverlayError, match="orchestration policy"): + verify_consuming_boundary_activation( + overlay, + changed, + frozen_root, + observed_head=exact_main, + observed_tracking_main=exact_main, + observed_remote_main=exact_main, + observed_capacity_bytes=10 * 1024**3, + observed_base_is_ancestor=True, + ) + + +def test_worker_state_reaches_consuming_activation_before_verifier_returns( + monkeypatch: pytest.MonkeyPatch, +) -> None: + overlay = load_overlay() + consuming = load_consuming_boundary() + assert consuming is not None + calls: list[str] = [] + monkeypatch.setattr(overlay_module, "load_overlay", lambda root: overlay) + monkeypatch.setattr( + overlay_module, "verify_bound_authority_bytes", lambda *_: None + ) + monkeypatch.setattr( + overlay_module, "verify_launcher_safety_contract", lambda *_: None + ) + monkeypatch.setattr( + overlay_module, "verify_exact_committed_delta", lambda *_: None + ) + monkeypatch.setattr( + overlay_module, "observed_candidate_artifacts", lambda *_: {} + ) + monkeypatch.setattr( + overlay_module, + "classify_observed_state", + lambda *_: "worker_prequalification", + ) + monkeypatch.setattr( + overlay_module, "verify_exact_worktree_delta", lambda *_: None + ) + monkeypatch.setattr( + overlay_module, "load_consuming_boundary", lambda *_: consuming + ) + monkeypatch.setattr( + overlay_module, + "verify_consuming_boundary_activation", + lambda *_: calls.append("consuming_activation"), + ) + + _, state = overlay_module.verify_shared_successor_overlay(Path("/synthetic")) + assert state == "worker_prequalification" + assert calls == ["consuming_activation"] + + +def test_frozen_launcher_imports_verifier_before_any_side_effect() -> None: + consuming = load_consuming_boundary() + assert consuming is not None + launcher = ( + Path(consuming["worker"]["frozen_cwd"]) + / "scripts/benchmark_ck07r1_lifecycle_scale.py" + ).read_text(encoding="utf-8") + launch = launcher[ + launcher.index("def _launch_exact()") : launcher.index("\ndef main()") + ] + assert "verifier.verify_shared_successor_overlay(root)" in launcher + assert launch.index("_verify_overlay_cohort()") < launch.index("os.pipe()") + assert launch.index("_verify_overlay_cohort()") < launch.index("os.fork()") def test_overlay_admits_only_the_complete_exact_successor() -> None: diff --git a/tests/kernel/test_documentation_authority.py b/tests/kernel/test_documentation_authority.py index aad137ed..994ad1c3 100644 --- a/tests/kernel/test_documentation_authority.py +++ b/tests/kernel/test_documentation_authority.py @@ -204,7 +204,7 @@ def test_remaining_execution_plan_is_complete_acyclic_and_fail_closed() -> None: "continuation_policy": "reuse_existing_task_for_same_packet", "authority_policy": "new_task_only_for_new_policy_or_contract_decision", "handoff_policy": "proactive_parent_handoff_from_repository_verified_state", - "identity_policy": "exact_main_and_repository_paths_receiver_recomputes_digests", + "identity_policy": "worker_ownership_is_normative_coordinator_thread_binding_plus_exact_repository_evidence_not_runtime_authentication", "one_shot_policy": "real_non_consuming_preflight_before_authorized_attempt", "recovery_exit_policy": "return_to_convergence_after_integrity_restored", "blocked_policy": "spawn_none_and_report_to_orchestrator", @@ -239,9 +239,11 @@ def test_remaining_execution_plan_is_complete_acyclic_and_fail_closed() -> None: assert manifest["conditional_ready"] == [ { "condition": ( - "exact 66c015de/f108dbb4/4c514889 successor authority merges and exact-main " - "verifies; resume only existing worker 019fbfe2-8fe4-7de2-9264-d58572366727 " - "with the atomic cohort; no replacement, launch, token consumption, or downstream task" + "v1 consuming-boundary authority merges and exact-main verifies; coordinator " + "resumes exact existing worker 019fbfe2-8fe4-7de2-9264-d58572366727 with " + "the atomic 66c015de/f108dbb4/4c514889 cohort; exactly one synthetic " + "qualification launch may proceed under immediate preflight; no replacement " + "or downstream task" ), "tasks": ["CK-07R1"], }, @@ -1226,3 +1228,36 @@ def test_obsolete_planning_framework_is_absent_from_active_authority() -> None: not any(marker in path.read_text(encoding="utf-8") for marker in resolved_pull_request_refs) for path in active_paths ) +def test_ck07r1_consuming_boundary_is_documented_without_downstream_readiness() -> None: + agents = _read("AGENTS.md") + index = _read("docs/INDEX.md") + central = _read("docs/roadmap/REMAINING_EXECUTION_PLAN.md") + accounting = _read("docs/roadmap/TASK_PACKETS.md") + packet = _read( + "docs/roadmap/tasks/ck-07r1-correct-lifecycle-preparation-scale.md" + ) + + for body in (index, central, accounting, packet): + assert "lifecycle-consuming-boundary-authority-v1" in body or ( + "consuming-boundary authority" in body + ) + assert "019fbfe2-8fe4-7de2-9264-d58572366727" in central + assert "019fbfe2-8fe4-7de2-9264-d58572366727" in packet + assert "launch_authorized_once" in central + assert "launch_authorized_once" in packet + assert "CK-08R4_CK-08RG_CK-09_blocked" in _json( + "docs/decisions/evidence/ck07r1a0/" + "lifecycle-consuming-boundary-authority-v1.json" + )["approval"]["downstream"] + assert "Ready child tasks: **0**" in accounting + assert "Conditional-ready child tasks: **1 — CK-07R1" in accounting + assert "## Standing Repository Authorization" in agents + assert "No additional user approval is required" in agents + assert "normative coordinator/orchestration binding" in agents + assert "cryptographic per-task authentication" in agents + assert "force-pushes" in agents + for body in (index, central, packet): + assert "runtime" in body + assert "cryptographic" in body + assert "fast-forward" in body + assert "67bb1a" in body diff --git a/tests/kernel/test_kernel_scope.py b/tests/kernel/test_kernel_scope.py index a95bd6f6..a6d4552a 100644 --- a/tests/kernel/test_kernel_scope.py +++ b/tests/kernel/test_kernel_scope.py @@ -18,6 +18,7 @@ CK07C_PLAN_OPERAND_FACT_ADDITIONS, CK07D_EFFECTIVE_DATED_VALUATION_ADDITIONS, CK07E_INDEPENDENT_FACT_ADAPTER_ADDITIONS, + CK07R1_CONSUMING_BOUNDARY_AUTHORITY_ADDITIONS, CK07R1_LIFECYCLE_SCOPE_ADDITIONS, CK07R1_RUN_INVOCATION_AUTHORITY_ADDITIONS, CK07R1_SHARED_OVERLAY_AUTHORITY_ADDITIONS, @@ -698,6 +699,7 @@ def test_k6_additions_are_explicit_and_bounded() -> None: | CK07R1A0_AUTHORITY_ADDITIONS | CK07R1_SHARED_OVERLAY_AUTHORITY_ADDITIONS | CK07R1_LIFECYCLE_SCOPE_ADDITIONS + | CK07R1_CONSUMING_BOUNDARY_AUTHORITY_ADDITIONS | CK07R1_RUN_INVOCATION_AUTHORITY_ADDITIONS | CK08_PREREQUISITE_BLOCKER_ADDITIONS | { @@ -799,6 +801,15 @@ def test_ck07r1_shared_overlay_additions_are_explicit_and_bounded() -> None: } == CK07R1_SHARED_OVERLAY_AUTHORITY_ADDITIONS +def test_ck07r1_consuming_boundary_additions_are_explicit_and_bounded() -> None: + assert { + "docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.json", + "docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.schema.json", + "scripts/ck07r1_consuming_boundary.py", + "tests/kernel/test_ck07r1_consuming_boundary_authority.py", + } == CK07R1_CONSUMING_BOUNDARY_AUTHORITY_ADDITIONS + + def test_kernel_skeleton_imports_without_legacy_runtime() -> None: import codex_usage_tracker.kernel as kernel From 1fb5824767fadb87bdf61d20db16691a2d5b58ae Mon Sep 17 00:00:00 2001 From: Monsky Date: Wed, 19 Aug 2026 11:30:05 -0400 Subject: [PATCH 2/3] test(kernel): make CK-07 authority checks CI-portable --- .../kernel/test_ck07r1_shared_successor_overlay.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tests/kernel/test_ck07r1_shared_successor_overlay.py b/tests/kernel/test_ck07r1_shared_successor_overlay.py index f2741d4b..e82ad459 100644 --- a/tests/kernel/test_ck07r1_shared_successor_overlay.py +++ b/tests/kernel/test_ck07r1_shared_successor_overlay.py @@ -225,10 +225,13 @@ def test_worker_state_reaches_consuming_activation_before_verifier_returns( def test_frozen_launcher_imports_verifier_before_any_side_effect() -> None: consuming = load_consuming_boundary() assert consuming is not None - launcher = ( + launcher_path = ( Path(consuming["worker"]["frozen_cwd"]) / "scripts/benchmark_ck07r1_lifecycle_scale.py" - ).read_text(encoding="utf-8") + ) + if not launcher_path.is_file(): + pytest.skip("retained frozen candidate witness is unavailable") + launcher = launcher_path.read_text(encoding="utf-8") launch = launcher[ launcher.index("def _launch_exact()") : launcher.index("\ndef main()") ] @@ -403,7 +406,11 @@ def test_overlay_requires_exact_all_or_none_git_delta() -> None: def test_overlay_requires_exact_committed_authority_delta() -> None: authority = load_overlay() - expected = set(authority["scope"]["authority_write_scope"]) + consuming = load_consuming_boundary() + assert consuming is not None + expected = set(authority["scope"]["authority_write_scope"]) | set( + consuming["scope"]["authority_write_scope"] + ) verify_exact_committed_delta( authority, From d41817ddfbb41be94dd78e585fa0d15ca8426b15 Mon Sep 17 00:00:00 2001 From: Monsky Date: Wed, 19 Aug 2026 12:43:45 -0400 Subject: [PATCH 3/3] ci(kernel): bound Console dependency install --- .github/workflows/ci.yml | 8 ++++++++ docs/INDEX.md | 5 ++++- .../lifecycle-consuming-boundary-authority-v1.json | 5 +++++ ...ycle-consuming-boundary-authority-v1.schema.json | 5 +++++ docs/roadmap/REMAINING_EXECUTION_PLAN.md | 5 ++++- .../ck-07r1-correct-lifecycle-preparation-scale.md | 6 ++++++ .../test_ck07r1_consuming_boundary_authority.py | 13 +++++++++++++ 7 files changed, 45 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5292e9a6..e020613a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -87,6 +87,7 @@ jobs: console: name: Focused Evidence Console runs-on: ubuntu-latest + timeout-minutes: 20 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -103,6 +104,13 @@ jobs: run: | python -m pip install ".[dev]" npm ci --ignore-scripts + - name: Pin Ubuntu archive for browser dependencies + run: | + printf '%s\n' 'https://archive.ubuntu.com/ubuntu' \ + | sudo tee /etc/apt/apt-mirrors.txt >/dev/null + - name: Install Chromium + timeout-minutes: 10 + run: | npx playwright install --with-deps chromium - name: Verify deterministic Console run: | diff --git a/docs/INDEX.md b/docs/INDEX.md index 332a66dd..2bb4bbe9 100644 --- a/docs/INDEX.md +++ b/docs/INDEX.md @@ -137,7 +137,10 @@ qualification command from the bound cwd. The token remains `unspent_unavailable` until all immediate prelaunch checks pass and is consumed only at the first exact child PID/argv/cwd/owner/handshake. It is non-refundable, with no retry, restart, replacement, live data, PR #394 -mutation, or downstream readiness. The authority task itself does not launch, +mutation, or downstream readiness. Its hosted Console gate keeps Chromium +coverage while pinning the canonical HTTPS Ubuntu archive and bounding both +browser installation and the complete job; a mirror stall fails closed and +cannot be treated as hosted-green. The authority task itself does not launch, consume the token, or create output, ledger, stdout, stderr, or receipt. The frozen launcher imports the shared verifier before ledger/fork; its `worker_prequalification` path requires the complete consuming authority, diff --git a/docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.json b/docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.json index f7e90abc..72e4bbe2 100644 --- a/docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.json +++ b/docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.json @@ -61,6 +61,10 @@ { "path": "scripts/ck07r1_shared_successor_overlay.py", "sha256": "f3745ec07bf47ee15f50969132f315aec61d407c745f6c63694e9910a88c5768" + }, + { + "path": ".github/workflows/ci.yml", + "sha256": "f25ea89fb207b2d7a9ff1c18953865ef91cb73cfe23796f545d304a40cc8959c" } ], "candidate_cohort": [ @@ -160,6 +164,7 @@ }, "scope": { "authority_write_scope": [ + ".github/workflows/ci.yml", "AGENTS.md", "docs/INDEX.md", "docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.json", diff --git a/docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.schema.json b/docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.schema.json index d47d0dd2..2274c105 100644 --- a/docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.schema.json +++ b/docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.schema.json @@ -102,6 +102,10 @@ { "path": "scripts/ck07r1_shared_successor_overlay.py", "sha256": "f3745ec07bf47ee15f50969132f315aec61d407c745f6c63694e9910a88c5768" + }, + { + "path": ".github/workflows/ci.yml", + "sha256": "f25ea89fb207b2d7a9ff1c18953865ef91cb73cfe23796f545d304a40cc8959c" } ] }, @@ -215,6 +219,7 @@ "scope": { "const": { "authority_write_scope": [ + ".github/workflows/ci.yml", "AGENTS.md", "docs/INDEX.md", "docs/decisions/evidence/ck07r1a0/lifecycle-consuming-boundary-authority-v1.json", diff --git a/docs/roadmap/REMAINING_EXECUTION_PLAN.md b/docs/roadmap/REMAINING_EXECUTION_PLAN.md index f7abc45f..f0529919 100644 --- a/docs/roadmap/REMAINING_EXECUTION_PLAN.md +++ b/docs/roadmap/REMAINING_EXECUTION_PLAN.md @@ -129,7 +129,10 @@ qualification launch with the complete `66c015de…` / `f108dbb4…` / `4c514889…` cohort. That ownership is enforced normatively by the coordinator resuming the exact existing Codex task and recomputing repository evidence; it is not a runtime-authenticated identity and the launcher must not claim a -cryptographic per-task credential. Historical accepted R3A +cryptographic per-task credential. The hosted Console gate retains Chromium +dependency/browser coverage, pins the canonical HTTPS Ubuntu archive, and +fails closed under bounded install/job timeouts rather than accepting a +stalled or skipped Console result. Historical accepted R3A `6689d61f…`, revoked `d192c858…`, mixed cohorts, and every other digest are predecessor-only or fail-closed and cannot enter `worker_prequalification`. The worker may enter `worker_prequalification` only with the exact selected diff --git a/docs/roadmap/tasks/ck-07r1-correct-lifecycle-preparation-scale.md b/docs/roadmap/tasks/ck-07r1-correct-lifecycle-preparation-scale.md index 2d82838e..221d746b 100644 --- a/docs/roadmap/tasks/ck-07r1-correct-lifecycle-preparation-scale.md +++ b/docs/roadmap/tasks/ck-07r1-correct-lifecycle-preparation-scale.md @@ -138,6 +138,12 @@ Interpreter identity requires the lexical repository-worktree `sys.prefix`; base interpreters, symlink/resolved equivalence, wrong-worktree venvs, and prefix mismatch are rejected before side effects. +The hosted Console gate retains Chromium dependency and browser coverage. It +pins the canonical HTTPS Ubuntu archive before Playwright installs system +dependencies, bounds the Chromium install step at 10 minutes, and bounds the +complete Console job at 20 minutes. A mirror stall therefore fails closed +instead of hanging or bypassing Console evidence. + **Failure/rollback:** Retain the profile and create one narrow follow-up for a new dominant blocker; never weaken the gate. diff --git a/tests/kernel/test_ck07r1_consuming_boundary_authority.py b/tests/kernel/test_ck07r1_consuming_boundary_authority.py index 2d14c65d..626ba6b0 100644 --- a/tests/kernel/test_ck07r1_consuming_boundary_authority.py +++ b/tests/kernel/test_ck07r1_consuming_boundary_authority.py @@ -86,6 +86,19 @@ def test_consuming_boundary_preserves_every_bound_authority_byte() -> None: verify_bound_authority_bytes(_authority(), ROOT) +def test_consuming_boundary_binds_bounded_console_browser_install() -> None: + authority = _authority() + workflow_path = ".github/workflows/ci.yml" + workflow = (ROOT / workflow_path).read_text(encoding="utf-8") + + assert workflow_path in authority["scope"]["authority_write_scope"] + assert "name: Focused Evidence Console\n runs-on: ubuntu-latest\n timeout-minutes: 20" in workflow + assert "name: Pin Ubuntu archive for browser dependencies" in workflow + assert "https://archive.ubuntu.com/ubuntu" in workflow + assert "name: Install Chromium\n timeout-minutes: 10" in workflow + assert "npx playwright install --with-deps chromium" in workflow + + def test_consuming_boundary_binds_only_exact_atomic_candidate() -> None: authority = _authority() assert [record["sha256"] for record in authority["candidate_cohort"]] == [