diff --git a/docs/INDEX.md b/docs/INDEX.md index 88a564cd..e41ae270 100644 --- a/docs/INDEX.md +++ b/docs/INDEX.md @@ -68,7 +68,11 @@ parent rejection and production-independent null-coordinate parity. Its final writer-closure correction adds the publication writer and its focused tests to the atomic cohort: the writer supplies the complete connected existing session component, preparation recomputes every changed descendant after reparenting, -and unaffected rows remain exact. R1B is Ready only for its existing held +and unaffected rows remain exact. The final multi-publication correction keeps +the same 23 paths and binds native-parent snapshot seeding plus authoritative +late-parent ordering: newer event/source coordinates win, exact replay is +idempotent, and conflicting equal-order parent or basis declarations fail +closed. R1B is Ready only for its existing held worker and PR #430 after that correction is merged and exact-main verified; the authority does not accept the implementation. CK-08R1, CK-08R4, CK-08RG, CK-09, and CK-07 remain blocked or held by their existing gates. diff --git a/docs/decisions/evidence/ck08r1b/answer-semantics-join-authority.json b/docs/decisions/evidence/ck08r1b/answer-semantics-join-authority.json index 93f1137e..518fa692 100644 --- a/docs/decisions/evidence/ck08r1b/answer-semantics-join-authority.json +++ b/docs/decisions/evidence/ck08r1b/answer-semantics-join-authority.json @@ -176,6 +176,37 @@ "worker_pr_edit": "forbidden", "implementation_acceptance": "not_granted" }, + "multi_publication_correction": { + "base_sha": "e5b6321f406e10770b1caa96639f90f47cca2221", + "source_pr": 430, + "worker_head_sha": "3a86a10b12122d6ff9bec70f5f62105157af25c8", + "worker_state": "dirty_exact_23_path_reapplication_preserved_no_post_review_edits", + "superseded_selected_patch_sha256": "5ea9275830146875cd60cdf28372d5bbb4deeafe0b170c29ecd3118a70390fc2", + "selected_patch_sha256": "e424294a083b7f8f4c61dd57ac11400f3f6bdf63469f3d43154931c9c9c1939c", + "selected_successor_paths": 23, + "changed_successor_paths": [ + "src/codex_usage_tracker/agent_kernel/publication/preparation.py", + "src/codex_usage_tracker/agent_kernel/publication/writer.py", + "tests/agent_kernel/publication/test_preparation.py", + "tests/agent_kernel/publication/test_writer.py" + ], + "relationship_order": [ + "event_at_us_is_null", + "event_at_us", + "source_rank", + "source_order", + "event_kind_order", + "transition_rank" + ], + "findings": [ + "SessionObserved native parent identity is normalized to the exact session semantic identity before writer snapshot seeding loads its complete ancestor and descendant component", + "persisted and incoming late-parent relations compare exact event and source coordinates so a newer authoritative relation wins independent of publication arrival order", + "exact same-parent same-basis coordinate replay is idempotent, while a different parent or basis at equal coordinates fails closed", + "four-publication stale replay preserves the newer reparented subtree, every changed descendant, unaffected components, and production write-set parity" + ], + "worker_pr_edit": "forbidden", + "implementation_acceptance": "not_granted" + }, "consumer_join": { "query_compiler": { "path": "src/codex_usage_tracker/agent_kernel/query/compiler.py", @@ -239,8 +270,8 @@ } }, "selected_successor_cohort": { - "preflight_base_sha": "f55e513d3be9ea367b8cf29bc080d35e7a366e89", - "patch_sha256": "5ea9275830146875cd60cdf28372d5bbb4deeafe0b170c29ecd3118a70390fc2", + "preflight_base_sha": "e5b6321f406e10770b1caa96639f90f47cca2221", + "patch_sha256": "e424294a083b7f8f4c61dd57ac11400f3f6bdf63469f3d43154931c9c9c1939c", "files": [ { "path": "config/agent-kernel/formula-contract-v1.json", @@ -275,12 +306,12 @@ { "path": "src/codex_usage_tracker/agent_kernel/publication/preparation.py", "predecessor_sha256": "6689d61fbf6d7948e1958a9d0bc58b4ea326a7f04221914b74c0651e0be1e37c", - "sha256": "b5a6ef960d3b0361dfe0b1108b67f6231939cf82dc0bc549c76d9d8ad4e24c89" + "sha256": "382e486932064735e990794fb111362a02572bcf42e33dbe757b37f2b53f71a7" }, { "path": "src/codex_usage_tracker/agent_kernel/publication/writer.py", "predecessor_sha256": "13da341fc2a3c50d8d7de7fd6a6fc2b0aca0dbc832a9b56597cd96ab67d17488", - "sha256": "76db52708cead6ccd2b5ccf2872c6bd501fd9369ee561e3216da4ab13e6fe48d" + "sha256": "b23428f58040db06fc46eb938103f6e2844db6ee52843b169867c58bb0226997" }, { "path": "src/codex_usage_tracker/agent_kernel/query/compiler.py", @@ -345,12 +376,12 @@ { "path": "tests/agent_kernel/publication/test_preparation.py", "predecessor_sha256": "2b43cdfca0d935d4f08aa44a16bd176713ddf3ef7083ff3e76b42d4d0c8687e3", - "sha256": "d4e06c6fc7b2faa3d06c447d06c5a4ed5523da24caa1b25ee60de63e3fe6aa78" + "sha256": "df73de981b1675a0ae250daeecf2196d51889f4552a535538b80b628038b0f61" }, { "path": "tests/agent_kernel/publication/test_writer.py", "predecessor_sha256": "28dce47dfe32717a937079f068e9c1f1abcfbdfa6d65a15db6faba1b0c914b26", - "sha256": "c580641402ae79e31078c115ac01b10d486a72b14c57636d56577d2aadebc9b3" + "sha256": "67db39217a617361a9d5bf66cde5adcc41433e79ff3031a3c104caa8e052d34f" }, { "path": "tests/agent_kernel/test_ck08r1c_independent_evaluator.py", @@ -365,11 +396,11 @@ }, { "path": "tests/agent_kernel/publication/test_preparation.py", - "sha256": "d4e06c6fc7b2faa3d06c447d06c5a4ed5523da24caa1b25ee60de63e3fe6aa78" + "sha256": "df73de981b1675a0ae250daeecf2196d51889f4552a535538b80b628038b0f61" }, { "path": "tests/agent_kernel/publication/test_writer.py", - "sha256": "c580641402ae79e31078c115ac01b10d486a72b14c57636d56577d2aadebc9b3" + "sha256": "67db39217a617361a9d5bf66cde5adcc41433e79ff3031a3c104caa8e052d34f" }, { "path": "tests/agent_kernel/test_ck08r1c_independent_evaluator.py", @@ -381,7 +412,7 @@ } ], "focused_validation": { - "result": "174 passed focused semantic and writer preflight", + "result": "261 passed focused semantic, publication, compiler, replay, and writer preflight", "case_count": 80, "independent_rows_equal_production_rows": true, "independent_grades_equal_frozen_grades": true, @@ -393,12 +424,17 @@ "Q-REV-03 direct fact answers and bound internal formula diagnostics", "late relationship cycle, reverse-order chain, ambiguous new parent, and missing-parent rejection", "production and independent required tool start/terminal null timestamp rejection", - "writer-owned existing non-root closure, reverse late chain, reparented descendants, unaffected-row preservation, and write-set parity" + "writer-owned existing non-root closure, reverse late chain, reparented descendants, unaffected-row preservation, and write-set parity", + "two-publication native-parent closure plus unknown-parent dangling rejection", + "four-publication newer reparent, stale replay, exact duplicate, equal-order conflict, descendant recomputation, and unaffected-component preservation" ] } }, "negative_mutations": [ "writer snapshot missing an existing ancestor or descendant session rejects cohort identity and production replay", + "SessionObserved native parent seeding that omits semantic identity normalization rejects the cohort", + "older persisted late-parent replay that reverses a newer authoritative relation rejects the cohort", + "different parent or basis at equal late-parent event/source coordinates rejects before hierarchy mutation", "reparented subtree with stale descendant root or depth rejects production write-set parity", "missing, null, duplicate, cyclic, dangling, ambiguous, or stale reverse-order session hierarchy rejects after all authoritative relationships apply", "missing, null, malformed, or value-mismatched canonical-call measurement_mask rejects even when structural-context capability is unavailable", diff --git a/docs/decisions/evidence/ck08r1b/answer-semantics-join-authority.schema.json b/docs/decisions/evidence/ck08r1b/answer-semantics-join-authority.schema.json index 21797fd6..82348f69 100644 --- a/docs/decisions/evidence/ck08r1b/answer-semantics-join-authority.schema.json +++ b/docs/decisions/evidence/ck08r1b/answer-semantics-join-authority.schema.json @@ -18,6 +18,7 @@ "review_correction", "acceptance_correction", "writer_closure_correction", + "multi_publication_correction", "consumer_join", "selected_successor_cohort", "negative_mutations", @@ -311,6 +312,81 @@ }, "additionalProperties": false }, + "multi_publication_correction": { + "type": "object", + "required": [ + "base_sha", + "source_pr", + "worker_head_sha", + "worker_state", + "superseded_selected_patch_sha256", + "selected_patch_sha256", + "selected_successor_paths", + "changed_successor_paths", + "relationship_order", + "findings", + "worker_pr_edit", + "implementation_acceptance" + ], + "properties": { + "base_sha": { + "const": "e5b6321f406e10770b1caa96639f90f47cca2221" + }, + "source_pr": { + "const": 430 + }, + "worker_head_sha": { + "const": "3a86a10b12122d6ff9bec70f5f62105157af25c8" + }, + "worker_state": { + "const": "dirty_exact_23_path_reapplication_preserved_no_post_review_edits" + }, + "superseded_selected_patch_sha256": { + "const": "5ea9275830146875cd60cdf28372d5bbb4deeafe0b170c29ecd3118a70390fc2" + }, + "selected_patch_sha256": { + "const": "e424294a083b7f8f4c61dd57ac11400f3f6bdf63469f3d43154931c9c9c1939c" + }, + "selected_successor_paths": { + "const": 23 + }, + "changed_successor_paths": { + "const": [ + "src/codex_usage_tracker/agent_kernel/publication/preparation.py", + "src/codex_usage_tracker/agent_kernel/publication/writer.py", + "tests/agent_kernel/publication/test_preparation.py", + "tests/agent_kernel/publication/test_writer.py" + ] + }, + "relationship_order": { + "const": [ + "event_at_us_is_null", + "event_at_us", + "source_rank", + "source_order", + "event_kind_order", + "transition_rank" + ] + }, + "findings": { + "type": "array", + "minItems": 4, + "maxItems": 4, + "uniqueItems": true, + "items": { + "type": "string", + "minLength": 1 + } + }, + "worker_pr_edit": { + "const": "forbidden" + }, + "implementation_acceptance": { + "const": "not_granted" + } + }, + "additionalProperties": false + }, "consumer_join": { "$ref": "#/$defs/object" }, diff --git a/docs/roadmap/REMAINING_EXECUTION_PLAN.md b/docs/roadmap/REMAINING_EXECUTION_PLAN.md index 6d458b07..50328c5c 100644 --- a/docs/roadmap/REMAINING_EXECUTION_PLAN.md +++ b/docs/roadmap/REMAINING_EXECUTION_PLAN.md @@ -44,7 +44,13 @@ one hierarchy computation and explicit non-null required tool timestamps. The final writer-closure correction extends that atomic cohort to 23 paths: writer-owned prior-state loading supplies every connected existing ancestor and descendant, preparation emits every changed descendant after reparenting, and -unaffected session rows remain exact. Only the existing worker may resume after +unaffected session rows remain exact. The final multi-publication correction +retains those 23 paths and binds the remaining closure seam: +`SessionObserved` native parents seed their exact semantic parent component, +and persisted/incoming late-parent relations compare event/source coordinates +so stale replay cannot reverse a newer reparent. Exact replay is idempotent; +conflicting equal-order parent or basis declarations fail closed. Only the +existing worker may resume after that correction merges and exact-main verifies. R1 remains their blocked requalification join. CK-QG1A removed R2's two page-executor C/B/B violations diff --git a/docs/roadmap/TASK_PACKETS.md b/docs/roadmap/TASK_PACKETS.md index e531802d..48a3d30d 100644 --- a/docs/roadmap/TASK_PACKETS.md +++ b/docs/roadmap/TASK_PACKETS.md @@ -59,7 +59,7 @@ verified; other corrective locks are unchanged. - [x] **CK-08R0 — Freeze corrective query and scale contracts** · Completed on merge; exact-main verification recorded in handoff · [packet](tasks/ck-08r0-freeze-corrective-contracts.md) - [x] **CK-08R1A — Freeze answer semantics and evidence closure** · Completed on merge; exact-main verification required in handoff · [packet](tasks/ck-08r1a-freeze-answer-semantics.md) -- [ ] **CK-08R1B — Implement production answer semantics** · Ready after the final 23-path writer-closure correction merges; resume existing worker and PR #430 only · [packet](tasks/ck-08r1b-implement-production-answer-semantics.md) +- [ ] **CK-08R1B — Implement production answer semantics** · Ready under the final 23-path multi-publication closure correction; resume existing worker and PR #430 only · [packet](tasks/ck-08r1b-implement-production-answer-semantics.md) - [x] **CK-08R1C — Build independent semantic evaluator** · PR #411 merged/exact-main `fb0c578`; independent closure and all 80 variants accepted · [packet](tasks/ck-08r1c-build-independent-semantic-evaluator.md) - [ ] **CK-08R1 — Requalify independent answer truth** · Blocked on CK-08R1B; CK-08R1C is accepted · [packet](tasks/ck-08r1-build-independent-answer-truth.md) - [x] **CK-08R2 — Implement bounded physical keyset execution** · Completed on merge; exact-main verification recorded in handoff · [packet](tasks/ck-08r2-implement-physical-keyset-execution.md) diff --git a/docs/roadmap/tasks/ck-08r1b-implement-production-answer-semantics.md b/docs/roadmap/tasks/ck-08r1b-implement-production-answer-semantics.md index 373508da..a1e5c953 100644 --- a/docs/roadmap/tasks/ck-08r1b-implement-production-answer-semantics.md +++ b/docs/roadmap/tasks/ck-08r1b-implement-production-answer-semantics.md @@ -1,10 +1,11 @@ # CK-08R1B — Implement production answer semantics -**Status:** Ready after final 23-path writer-closure correction merges; resume existing worker and PR #430 only +**Status:** Ready under final 23-path multi-publication closure correction; resume existing worker and PR #430 only **Recommended owner:** `worker production-semantics`; Sol-class **Accounting:** [TASK_PACKETS.md](../TASK_PACKETS.md); [REMAINING_EXECUTION_PLAN.md](../REMAINING_EXECUTION_PLAN.md); [AGENT_FIRST_CLEAN_CUTOVER.md](../AGENT_FIRST_CLEAN_CUTOVER.md) **Goal:** Implement R1A Q-REV-03/Q-WF-02 semantics. **Dependencies:** R1A accepted/merged/exact-main. **Owned files/interfaces:** The exact 23-path successor cohort in the [join authority](../../decisions/evidence/ck08r1b/answer-semantics-join-authority.json), superseding the preserved PR #430 head after reviewer findings. It adds production publication hierarchy ownership, production-compiler 80-case replay, Q-WF-02 straddling lifecycle correction, independent duplicate-ID rejection, and the explicit Q-REV-03 direct-fact/internal-formula binding decision. The selected-cohort acceptance correction requires every authoritative late relationship to apply before one complete acyclic hierarchy computation, rejects late cycles and ambiguous or missing parents, proves reverse-order chains through production publication and compiler replay, and rejects explicit null required start or terminal timestamps in production and independent truth. The final correction explicitly owns `publication/writer.py`: writer prior-state loading supplies the complete connected ancestor/descendant session component, preparation emits every changed descendant after reparenting, and unaffected rows remain exact. Query compiler admission, synthetic materialization, R1C's exact seams, deterministic fixture generation, database/reference parity, and Candidate A plan requalification are allowed only as bound there; public API, EvidenceService, cursor, projection, and unrelated evaluator changes remain forbidden. +**Multi-publication closure:** Writer seeding normalizes a `SessionObserved` native parent to the exact semantic session identity and loads its complete existing component. Persisted and incoming late-parent relations compare exact event/source coordinates: newer authority wins, exact replay is idempotent, and conflicting equal-order parent or basis declarations fail closed. Reparented descendants recompute; unaffected components remain exact. **Produces:** Exact comparison/boundaries/nulls and closure. **Independent truth source:** R1A plus R1C's preserved recursive closure and facts-only evaluator, requalified at the exact stale Q-WF-02 seam; no grading source or copied expected rows in production. **Consumer seam:** `compile_plan_operands` emits final-R1 materializations. diff --git a/tests/kernel/test_ck08r1b_answer_semantics_join_authority.py b/tests/kernel/test_ck08r1b_answer_semantics_join_authority.py index ea3937a6..4fdcc5fe 100644 --- a/tests/kernel/test_ck08r1b_answer_semantics_join_authority.py +++ b/tests/kernel/test_ck08r1b_answer_semantics_join_authority.py @@ -109,6 +109,7 @@ def test_import_order_identity_correction_is_exact_and_non_semantic() -> None: review_correction = authority["review_correction"] acceptance_correction = authority["acceptance_correction"] writer_closure_correction = authority["writer_closure_correction"] + multi_publication_correction = authority["multi_publication_correction"] cohort = authority["selected_successor_cohort"] assert isinstance(correction, dict) @@ -139,8 +140,12 @@ def test_import_order_identity_correction_is_exact_and_non_semantic() -> None: assert isinstance(review_correction, dict) assert isinstance(acceptance_correction, dict) assert isinstance(writer_closure_correction, dict) - assert cohort["preflight_base_sha"] == writer_closure_correction["base_sha"] - assert cohort["patch_sha256"] == writer_closure_correction["selected_patch_sha256"] + assert isinstance(multi_publication_correction, dict) + assert cohort["preflight_base_sha"] == multi_publication_correction["base_sha"] + assert ( + cohort["patch_sha256"] + == multi_publication_correction["selected_patch_sha256"] + ) assert review_correction["superseded_patch_sha256"] == correction["selected_patch_sha256"] assert ( acceptance_correction["superseded_selected_patch_sha256"] @@ -150,6 +155,10 @@ def test_import_order_identity_correction_is_exact_and_non_semantic() -> None: writer_closure_correction["superseded_selected_patch_sha256"] == acceptance_correction["selected_patch_sha256"] ) + assert ( + multi_publication_correction["superseded_selected_patch_sha256"] + == writer_closure_correction["selected_patch_sha256"] + ) assert set(writer_closure_correction["added_successor_paths"]) == { "src/codex_usage_tracker/agent_kernel/publication/writer.py", "tests/agent_kernel/publication/test_writer.py", @@ -159,6 +168,20 @@ def test_import_order_identity_correction_is_exact_and_non_semantic() -> None: "src/codex_usage_tracker/agent_kernel/publication/writer.py", "tests/agent_kernel/publication/test_writer.py", } + assert set(multi_publication_correction["changed_successor_paths"]) == { + "src/codex_usage_tracker/agent_kernel/publication/preparation.py", + "src/codex_usage_tracker/agent_kernel/publication/writer.py", + "tests/agent_kernel/publication/test_preparation.py", + "tests/agent_kernel/publication/test_writer.py", + } + assert multi_publication_correction["relationship_order"] == [ + "event_at_us_is_null", + "event_at_us", + "source_rank", + "source_order", + "event_kind_order", + "transition_rank", + ] assert set(acceptance_correction["changed_successor_paths"]) == { "src/codex_usage_tracker/agent_kernel/domain/plan_derivations_structural.py", "src/codex_usage_tracker/agent_kernel/publication/preparation.py", @@ -212,7 +235,7 @@ def test_successor_cohort_and_consumer_ownership_are_bounded() -> None: == "forbidden" ) assert cohort["focused_validation"] == { - "result": "174 passed focused semantic and writer preflight", + "result": "261 passed focused semantic, publication, compiler, replay, and writer preflight", "case_count": 80, "independent_rows_equal_production_rows": True, "independent_grades_equal_frozen_grades": True, @@ -225,6 +248,8 @@ def test_successor_cohort_and_consumer_ownership_are_bounded() -> None: "late relationship cycle, reverse-order chain, ambiguous new parent, and missing-parent rejection", "production and independent required tool start/terminal null timestamp rejection", "writer-owned existing non-root closure, reverse late chain, reparented descendants, unaffected-row preservation, and write-set parity", + "two-publication native-parent closure plus unknown-parent dangling rejection", + "four-publication newer reparent, stale replay, exact duplicate, equal-order conflict, descendant recomputation, and unaffected-component preservation", ], }