From a19e981edcb5d86ec38bde8f15e84f5d6bc2f6a3 Mon Sep 17 00:00:00 2001 From: Divyam Talwar Date: Tue, 29 Sep 2026 01:28:59 +0530 Subject: [PATCH 1/8] test(release): add standalone qualification and acceptance evidence --- docs/engineering/acceptance-edge-notes.md | 109 + docs/engineering/acceptance-map.json | 3452 +++++++++++++++++ docs/engineering/acceptance-supplement.json | 2343 +++++++++++ .../evidence-kind-normalization.json | 453 +++ docs/engineering/qualification-review.md | 27 + docs/release-qualification.md | 453 +++ scripts/qualify_jitmind.py | 1436 +++++++ tests/test_acceptance_edges.py | 538 +++ tests/test_qualification.py | 628 +++ tests/test_qualification_contracts.py | 32 + tests/test_qualification_regressions.py | 493 +++ tests/test_standalone_install.py | 216 ++ 12 files changed, 10180 insertions(+) create mode 100644 docs/engineering/acceptance-edge-notes.md create mode 100644 docs/engineering/acceptance-map.json create mode 100644 docs/engineering/acceptance-supplement.json create mode 100644 docs/engineering/evidence-kind-normalization.json create mode 100644 docs/engineering/qualification-review.md create mode 100644 docs/release-qualification.md create mode 100644 scripts/qualify_jitmind.py create mode 100644 tests/test_acceptance_edges.py create mode 100644 tests/test_qualification.py create mode 100644 tests/test_qualification_contracts.py create mode 100644 tests/test_qualification_regressions.py create mode 100644 tests/test_standalone_install.py diff --git a/docs/engineering/acceptance-edge-notes.md b/docs/engineering/acceptance-edge-notes.md new file mode 100644 index 0000000..4b8f313 --- /dev/null +++ b/docs/engineering/acceptance-edge-notes.md @@ -0,0 +1,109 @@ +# J10 snapshot acceptance evidence — historical + +J08 final integration note: the outcomes below describe the original J10 snapshot. +The copied fixture now configures J06's explicit `DurableBindingAuthority`; current +node/fixture/module hashes in the supplement describe final staged owner sources. +The supplement's `inputs` and `all_copied_dependencies` still preserve historical +J10 provenance, not the final composite roster. J08's final full run collected +861 tests: 860 passed, one unchanged gate-schema test failed, zero skipped. +All 26 supplement nodes and all 93 mapped pytest nodes passed every phase. +See [qualification-review.md](qualification-review.md) for current blockers and ownership. +No source specification status has been converted into an execution result. + +This is internal integration evidence for the supervisor's J08 qualification +assembly, not a product feature, separate PR, or final qualification result. +All statuses in `acceptance-supplement.json` intentionally remain `not_run`. +The outcomes below describe the attested J10 snapshot only. + +Only three files are J10 contributions: `tests/test_acceptance_edges.py`, +`docs/engineering/acceptance-supplement.json`, and this note. Product modules and +existing tests were read-only. No copies were refreshed, dependencies installed, +services/providers contacted, commits created, or peer files edited. + +| Stage | Evidence | Final exact-node count | +| --- | --- | ---: | +| J02 / J-01 | New ENOSPC at actual legacy publication, five stores, positive recovery | 5 | +| J02 / J-02 | New native SQLITE_FULL, complete rollback, same-key positive recovery | 1 | +| J04 / J-02 | Reused real process exits before/after commit | 5 | +| J16 / J-06 | Reused actual parser → binding → move/disappearance → open-work fallback | 2 | +| J22 / J-07 | Reused end/start tool cuts and complete-range positive for three terminals | 3 | +| J25 / J-02 | Three reused corrupt sources, three reused import failures, two new process exits | 8 | +| J29 / J-04 | New full parser/binding/lesson/preflight/projection chain, two delivery schedules | 2 | +| J31 / J-04 | Same two compound nodes, primary forget with delayed projections and open task | 2 | + +The table has 28 stage-node associations but **26 unique pytest nodes: 10 new, +16 reused**. Every reused definition was inspected and executed. Exact collected +parameter IDs, including escaped newlines in the existing J16 parameters, are +stored in `collection.exact_node_ids`. No static mapping is counted as a run. + +Final verification: **26 passed, 3 expected optional-provider warnings, 3.56 s**. +Runtime: Python 3.12.12, SQLite 3.51.2, Node v25.2.1; the real adapter uses its +provisioned tree-sitter 0.21.1 / tree-sitter-python 0.21.0 dependencies. +The final own-test run separately passed **10/10**; the reused-node run passed +**16/16**. Ruff check and format check passed. Python compilation and Python 3.10 +syntax parsing passed. JSON/source validation checked all eight stages, every +mapped source/module digest, and all 45 unchanged snapshot dependencies. +`git diff --check` passed. Neither mypy nor pyright is installed; no static type +check is claimed and no installation was attempted. + +Final execution command from J10 (the variables expand to the prescribed paths): + +```sh +ROOT=/path/to/orchestration-root +PYTHONPATH="$PWD" \ +JITMIND_TEST_GRAFT_ADAPTER="$ROOT/worktrees/J04/adapters/graft" \ +"$ROOT/venv/bin/python" - <<'PY' +import json, os, subprocess, sys +from pathlib import Path +spec = json.loads(Path('docs/engineering/acceptance-supplement.json').read_text()) +result = subprocess.run( + [sys.executable, '-m', 'pytest', '-q', *spec['collection']['exact_node_ids']], + env=os.environ, timeout=120, +) +raise SystemExit(result.returncode) +PY +``` + +Collection used the same isolated Python with `-m pytest --collect-only -q` and +the exact selectors in `collection.selectors`: **26 collected**. Lint commands +were `"$ROOT/venv/bin/python" -m ruff check tests/test_acceptance_edges.py` and +`"$ROOT/venv/bin/python" -m ruff format --check tests/test_acceptance_edges.py`. +New spawned children have 20-second joins followed by bounded terminate/kill +and reap; the parser uses its actual bounded process wrapper. Only sanitized +ENOSPC is injected; SQLite capacity and process termination are real. + +The supplement's `all_copied_dependencies` is the complete inventory of **45 +pre-existing copied files**, with owner, initial/current SHA-256, and explicit +non-contribution markers. Every local digest still matches +`ROOT/reports/J10-dependency-snapshot.json`. The J04 adapter is read directly +from its owner and is not copied. Its source/lockfile digests are also recorded. +Tests use `JITMIND_TEST_GRAFT_ADAPTER`, falling back to repository +`adapters/graft`; no test depends on a home path or review-probe script. +Inventory counts: J02 8, J03 7, J04 8, J05 6, J06 7, J07 7, and J09 2. + +At source review, nine owner files had advanced beyond this local snapshot: +J02 `storage/{migration,sqlite}.py` and `test_durable_remediation.py`; +J05 `code_memory/{anchors,binding_storage}.py` and `test_code_anchors.py`; +J06 `code_memory/{lesson_models,preflight}.py` and `test_open_work_bindings.py`. +Their observed owner digests are recorded without copying in-progress changes. +Final assembly must retest its actual versions. In particular, newer J06 work +introduces a binding-authority adapter; its final configuration/schema compatibility +is outside this snapshot run and must be composed explicitly, not bypassed. + +The compound fixture first proves that the memory-only sentinel appears in the +authoritative fact and delivered lesson. It never appears in repository source. +One schedule starts with an existing primary projection; the other keeps the +original add pending until after the delete event is delivered. Both verify +metadata replay, lesson version ordering, source freshness/generation, primary +forget before deletion projection, empty current derived memory outputs, +content-free binding/work/delivery histories, and an obligation still open at +revision 1. **Raw authorized code remains readable after memory forget.** J04 +indexes source bytes, not fact bodies; deleting a memory does not delete the +user's files. Retained primary administrative history and backups can still +contain bodies; no physical erasure or all-history purge is claimed. + +No product defect blocked these 26 snapshot cases. Remaining limits are final +owner-version assembly, cross-platform/power-loss coverage, and the per-node +limits recorded in the supplement. The frozen temporal oracle was read but this +supplement adds no temporal acceptance claims. Reusing 16 exact existing nodes +avoids copying tests or introducing product abstractions. diff --git a/docs/engineering/acceptance-map.json b/docs/engineering/acceptance-map.json new file mode 100644 index 0000000..c53f463 --- /dev/null +++ b/docs/engineering/acceptance-map.json @@ -0,0 +1,3452 @@ +{ + "schema": "jitmind.acceptance-map/v1", + "target": "JITMIND", + "source_handoff_sha256": "f1b3107ff03f21fb8ccc8c8b90301e4953480e5639bd10a059ec278ecb8cdd51", + "notice": "Derived scenario map, not a copy of full handoff fixtures or execution results. Original case fixtures reviewed by supervisor. All scenarios require actual mapped test evidence. Later-stage repeats are required.", + "cases": [ + { + "case_id": "J01", + "ticket": "J-01", + "scenario": "Cleanup races with append", + "required_assertion": "A committed append survives cleanup; no stale-snapshot overwrite", + "required_in_tickets": [ + "J-01" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-01", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_legacy_persistence.py::test_cleanup_append_schedule[cleanup]", + "kind": "real_storage", + "source": { + "path": "tests/test_legacy_persistence.py", + "sha256": "1516040fc50767e8ca317a7da29e57e1386ac9187657825d3108a136ce079a48" + }, + "fixtures": [ + { + "path": "tests/test_legacy_persistence.py", + "sha256": "1516040fc50767e8ca317a7da29e57e1386ac9187657825d3108a136ce079a48" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_legacy_persistence.py::test_cleanup_append_schedule[append]", + "kind": "real_storage", + "source": { + "path": "tests/test_legacy_persistence.py", + "sha256": "1516040fc50767e8ca317a7da29e57e1386ac9187657825d3108a136ce079a48" + }, + "fixtures": [ + { + "path": "tests/test_legacy_persistence.py", + "sha256": "1516040fc50767e8ca317a7da29e57e1386ac9187657825d3108a136ce079a48" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J02", + "ticket": "J-01", + "scenario": "Disk-full write failure", + "required_assertion": "Durability failure reaches caller; no committed acknowledgement", + "required_in_tickets": [ + "J-01", + "J-02" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-01", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_legacy_persistence.py::test_advanced_save_failure_reaches_caller", + "kind": "injected_storage_fault", + "source": { + "path": "tests/test_legacy_persistence.py", + "sha256": "1516040fc50767e8ca317a7da29e57e1386ac9187657825d3108a136ce079a48" + }, + "fixtures": [ + { + "path": "tests/test_legacy_persistence.py", + "sha256": "1516040fc50767e8ca317a7da29e57e1386ac9187657825d3108a136ce079a48" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[advanced]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Five real legacy store classes in temporary directories; successful initial append, ENOSPC from os.replace after temporary bytes are fsynced, then successful append after fault removal.", + "modules_composed": [ + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/memory.py", + "sha256": "68e5803e6523b41f09fb710656ddfb9c0f2a61bb9ba9335a8fa684173e59a7e9" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + }, + { + "path": "jitmind/schemas/ttl_memory.py", + "sha256": "ff48ac01b5a5a1bacd41d671f48e7cee07a703dcf5b3017eb8b8ca14405e29ca" + }, + { + "path": "jitmind/schemas/ttl_page.py", + "sha256": "2889b4ec309cda92c8eeda1ec624f8a074ae00d791e9d5e7fd11a6e16d9816ca" + }, + { + "path": "jitmind/utils/atomic_io.py", + "sha256": "aa58bbae5ca9f686ad020f7ebe74a27c082400964aebad3614fe46cd4466202d" + }, + { + "path": "jitmind/utils/file_lock.py", + "sha256": "4498fbe42d1a9b8f7224f17d684a8a35fb15dbb815b49de83d1246be5ed6e398" + } + ], + "assertions": [ + "Typed PersistenceError reaches public add caller with ENOSPC cause and outcome_uncertain=False.", + "Previous authoritative bytes unchanged; same-instance and fresh reader contain only prior content; temporary file removed.", + "Positive writes before and after fault prove usable fixture." + ], + "evidence_limits": [ + "Injects only errno.ENOSPC at the actual pre-replacement boundary; does not fill disk or assert post-replacement failure semantics.", + "Covers the five public store add surfaces, not every MemoryAgent/provider path or every filesystem syscall." + ] + }, + { + "node_id": "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[memory]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Five real legacy store classes in temporary directories; successful initial append, ENOSPC from os.replace after temporary bytes are fsynced, then successful append after fault removal.", + "modules_composed": [ + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/memory.py", + "sha256": "68e5803e6523b41f09fb710656ddfb9c0f2a61bb9ba9335a8fa684173e59a7e9" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + }, + { + "path": "jitmind/schemas/ttl_memory.py", + "sha256": "ff48ac01b5a5a1bacd41d671f48e7cee07a703dcf5b3017eb8b8ca14405e29ca" + }, + { + "path": "jitmind/schemas/ttl_page.py", + "sha256": "2889b4ec309cda92c8eeda1ec624f8a074ae00d791e9d5e7fd11a6e16d9816ca" + }, + { + "path": "jitmind/utils/atomic_io.py", + "sha256": "aa58bbae5ca9f686ad020f7ebe74a27c082400964aebad3614fe46cd4466202d" + }, + { + "path": "jitmind/utils/file_lock.py", + "sha256": "4498fbe42d1a9b8f7224f17d684a8a35fb15dbb815b49de83d1246be5ed6e398" + } + ], + "assertions": [ + "Typed PersistenceError reaches public add caller with ENOSPC cause and outcome_uncertain=False.", + "Previous authoritative bytes unchanged; same-instance and fresh reader contain only prior content; temporary file removed.", + "Positive writes before and after fault prove usable fixture." + ], + "evidence_limits": [ + "Injects only errno.ENOSPC at the actual pre-replacement boundary; does not fill disk or assert post-replacement failure semantics.", + "Covers the five public store add surfaces, not every MemoryAgent/provider path or every filesystem syscall." + ] + }, + { + "node_id": "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[ttl_memory]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Five real legacy store classes in temporary directories; successful initial append, ENOSPC from os.replace after temporary bytes are fsynced, then successful append after fault removal.", + "modules_composed": [ + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/memory.py", + "sha256": "68e5803e6523b41f09fb710656ddfb9c0f2a61bb9ba9335a8fa684173e59a7e9" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + }, + { + "path": "jitmind/schemas/ttl_memory.py", + "sha256": "ff48ac01b5a5a1bacd41d671f48e7cee07a703dcf5b3017eb8b8ca14405e29ca" + }, + { + "path": "jitmind/schemas/ttl_page.py", + "sha256": "2889b4ec309cda92c8eeda1ec624f8a074ae00d791e9d5e7fd11a6e16d9816ca" + }, + { + "path": "jitmind/utils/atomic_io.py", + "sha256": "aa58bbae5ca9f686ad020f7ebe74a27c082400964aebad3614fe46cd4466202d" + }, + { + "path": "jitmind/utils/file_lock.py", + "sha256": "4498fbe42d1a9b8f7224f17d684a8a35fb15dbb815b49de83d1246be5ed6e398" + } + ], + "assertions": [ + "Typed PersistenceError reaches public add caller with ENOSPC cause and outcome_uncertain=False.", + "Previous authoritative bytes unchanged; same-instance and fresh reader contain only prior content; temporary file removed.", + "Positive writes before and after fault prove usable fixture." + ], + "evidence_limits": [ + "Injects only errno.ENOSPC at the actual pre-replacement boundary; does not fill disk or assert post-replacement failure semantics.", + "Covers the five public store add surfaces, not every MemoryAgent/provider path or every filesystem syscall." + ] + }, + { + "node_id": "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[pages]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Five real legacy store classes in temporary directories; successful initial append, ENOSPC from os.replace after temporary bytes are fsynced, then successful append after fault removal.", + "modules_composed": [ + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/memory.py", + "sha256": "68e5803e6523b41f09fb710656ddfb9c0f2a61bb9ba9335a8fa684173e59a7e9" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + }, + { + "path": "jitmind/schemas/ttl_memory.py", + "sha256": "ff48ac01b5a5a1bacd41d671f48e7cee07a703dcf5b3017eb8b8ca14405e29ca" + }, + { + "path": "jitmind/schemas/ttl_page.py", + "sha256": "2889b4ec309cda92c8eeda1ec624f8a074ae00d791e9d5e7fd11a6e16d9816ca" + }, + { + "path": "jitmind/utils/atomic_io.py", + "sha256": "aa58bbae5ca9f686ad020f7ebe74a27c082400964aebad3614fe46cd4466202d" + }, + { + "path": "jitmind/utils/file_lock.py", + "sha256": "4498fbe42d1a9b8f7224f17d684a8a35fb15dbb815b49de83d1246be5ed6e398" + } + ], + "assertions": [ + "Typed PersistenceError reaches public add caller with ENOSPC cause and outcome_uncertain=False.", + "Previous authoritative bytes unchanged; same-instance and fresh reader contain only prior content; temporary file removed.", + "Positive writes before and after fault prove usable fixture." + ], + "evidence_limits": [ + "Injects only errno.ENOSPC at the actual pre-replacement boundary; does not fill disk or assert post-replacement failure semantics.", + "Covers the five public store add surfaces, not every MemoryAgent/provider path or every filesystem syscall." + ] + }, + { + "node_id": "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[ttl_pages]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Five real legacy store classes in temporary directories; successful initial append, ENOSPC from os.replace after temporary bytes are fsynced, then successful append after fault removal.", + "modules_composed": [ + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/memory.py", + "sha256": "68e5803e6523b41f09fb710656ddfb9c0f2a61bb9ba9335a8fa684173e59a7e9" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + }, + { + "path": "jitmind/schemas/ttl_memory.py", + "sha256": "ff48ac01b5a5a1bacd41d671f48e7cee07a703dcf5b3017eb8b8ca14405e29ca" + }, + { + "path": "jitmind/schemas/ttl_page.py", + "sha256": "2889b4ec309cda92c8eeda1ec624f8a074ae00d791e9d5e7fd11a6e16d9816ca" + }, + { + "path": "jitmind/utils/atomic_io.py", + "sha256": "aa58bbae5ca9f686ad020f7ebe74a27c082400964aebad3614fe46cd4466202d" + }, + { + "path": "jitmind/utils/file_lock.py", + "sha256": "4498fbe42d1a9b8f7224f17d684a8a35fb15dbb815b49de83d1246be5ed6e398" + } + ], + "assertions": [ + "Typed PersistenceError reaches public add caller with ENOSPC cause and outcome_uncertain=False.", + "Previous authoritative bytes unchanged; same-instance and fresh reader contain only prior content; temporary file removed.", + "Positive writes before and after fault prove usable fixture." + ], + "evidence_limits": [ + "Injects only errno.ENOSPC at the actual pre-replacement boundary; does not fill disk or assert post-replacement failure semantics.", + "Covers the five public store add surfaces, not every MemoryAgent/provider path or every filesystem syscall." + ] + }, + { + "node_id": "tests/test_atomic_io_regressions.py::test_atomic_failure_stages_clean_temp_and_descriptors[mkdir]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + }, + "fixtures": [ + { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + } + ], + "fixture_description": "J01 atomic durability/corruption invariants, using J07-owned v2 checkpoint path adaptation. Generic fault coverage supplements, never replaces, the five explicit J10 ENOSPC cases." + }, + { + "node_id": "tests/test_atomic_io_regressions.py::test_atomic_failure_stages_clean_temp_and_descriptors[mkstemp]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + }, + "fixtures": [ + { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + } + ], + "fixture_description": "J01 atomic durability/corruption invariants, using J07-owned v2 checkpoint path adaptation. Generic fault coverage supplements, never replaces, the five explicit J10 ENOSPC cases." + }, + { + "node_id": "tests/test_atomic_io_regressions.py::test_atomic_failure_stages_clean_temp_and_descriptors[fdopen]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + }, + "fixtures": [ + { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + } + ], + "fixture_description": "J01 atomic durability/corruption invariants, using J07-owned v2 checkpoint path adaptation. Generic fault coverage supplements, never replaces, the five explicit J10 ENOSPC cases." + }, + { + "node_id": "tests/test_atomic_io_regressions.py::test_atomic_failure_stages_clean_temp_and_descriptors[write]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + }, + "fixtures": [ + { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + } + ], + "fixture_description": "J01 atomic durability/corruption invariants, using J07-owned v2 checkpoint path adaptation. Generic fault coverage supplements, never replaces, the five explicit J10 ENOSPC cases." + }, + { + "node_id": "tests/test_atomic_io_regressions.py::test_atomic_failure_stages_clean_temp_and_descriptors[flush]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + }, + "fixtures": [ + { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + } + ], + "fixture_description": "J01 atomic durability/corruption invariants, using J07-owned v2 checkpoint path adaptation. Generic fault coverage supplements, never replaces, the five explicit J10 ENOSPC cases." + }, + { + "node_id": "tests/test_atomic_io_regressions.py::test_atomic_failure_stages_clean_temp_and_descriptors[fsync]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + }, + "fixtures": [ + { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + } + ], + "fixture_description": "J01 atomic durability/corruption invariants, using J07-owned v2 checkpoint path adaptation. Generic fault coverage supplements, never replaces, the five explicit J10 ENOSPC cases." + }, + { + "node_id": "tests/test_atomic_io_regressions.py::test_atomic_failure_stages_clean_temp_and_descriptors[replace]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + }, + "fixtures": [ + { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + } + ], + "fixture_description": "J01 atomic durability/corruption invariants, using J07-owned v2 checkpoint path adaptation. Generic fault coverage supplements, never replaces, the five explicit J10 ENOSPC cases." + }, + { + "node_id": "tests/test_atomic_io_regressions.py::test_atomic_failure_stages_clean_temp_and_descriptors[directory_open]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + }, + "fixtures": [ + { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + } + ], + "fixture_description": "J01 atomic durability/corruption invariants, using J07-owned v2 checkpoint path adaptation. Generic fault coverage supplements, never replaces, the five explicit J10 ENOSPC cases." + }, + { + "node_id": "tests/test_atomic_io_regressions.py::test_atomic_failure_stages_clean_temp_and_descriptors[directory_fsync]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + }, + "fixtures": [ + { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + } + ], + "fixture_description": "J01 atomic durability/corruption invariants, using J07-owned v2 checkpoint path adaptation. Generic fault coverage supplements, never replaces, the five explicit J10 ENOSPC cases." + }, + { + "node_id": "tests/test_atomic_io_regressions.py::test_serialization_failure_is_precommit", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + }, + "fixtures": [ + { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + } + ], + "fixture_description": "J01 atomic durability/corruption invariants, using J07-owned v2 checkpoint path adaptation. Generic fault coverage supplements, never replaces, the five explicit J10 ENOSPC cases." + }, + { + "node_id": "tests/test_atomic_io_regressions.py::test_other_legacy_stores_errors_and_corruption[False-profile]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + }, + "fixtures": [ + { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + } + ], + "fixture_description": "J01 atomic durability/corruption invariants, using J07-owned v2 checkpoint path adaptation. Generic fault coverage supplements, never replaces, the five explicit J10 ENOSPC cases." + }, + { + "node_id": "tests/test_atomic_io_regressions.py::test_other_legacy_stores_errors_and_corruption[False-checkpoint]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + }, + "fixtures": [ + { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + } + ], + "fixture_description": "J01 atomic durability/corruption invariants, using J07-owned v2 checkpoint path adaptation. Generic fault coverage supplements, never replaces, the five explicit J10 ENOSPC cases." + }, + { + "node_id": "tests/test_atomic_io_regressions.py::test_other_legacy_stores_errors_and_corruption[True-profile]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + }, + "fixtures": [ + { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + } + ], + "fixture_description": "J01 atomic durability/corruption invariants, using J07-owned v2 checkpoint path adaptation. Generic fault coverage supplements, never replaces, the five explicit J10 ENOSPC cases." + }, + { + "node_id": "tests/test_atomic_io_regressions.py::test_other_legacy_stores_errors_and_corruption[True-checkpoint]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + }, + "fixtures": [ + { + "path": "tests/test_atomic_io_regressions.py", + "sha256": "2f6e21692241b179ddc59e7c7318abf4eb7bd28ab72351d8bac769f0cd178cc4" + } + ], + "fixture_description": "J01 atomic durability/corruption invariants, using J07-owned v2 checkpoint path adaptation. Generic fault coverage supplements, never replaces, the five explicit J10 ENOSPC cases." + } + ], + "additional_mapping_required": false + }, + { + "stage_id": "J-02", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_acceptance_edges.py::test_real_sqlite_full_rolls_back_every_effect_then_accepts_same_request", + "kind": "real_storage", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Real temporary SQLite DB; each ingest connection capped to current page_count; 100000-character allowed input triggers native SQLITE_FULL, then cap removed for same-key successful commit.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + } + ], + "assertions": [ + "Observes native sqlite_errorcode == SQLITE_FULL before product error translation; public StorageFailure, no acknowledgement.", + "Fresh reader sees zero revision/facts/pages/operations/outbox; no receipt; raw tables including namespace and projection remain empty; integrity_check=ok.", + "After removing cap, same request commits fact/page/receipt/event; replay is idempotent and event delivery returns the fact." + ], + "evidence_limits": [ + "Connection wrapper configures a real PRAGMA, not a mocked SQLite exception; host disk is not exhausted.", + "Empty temporary database only; no production filesystem or WAL qualification." + ] + } + ], + "additional_mapping_required": false + } + ] + }, + { + "case_id": "J03", + "ticket": "J-01", + "scenario": "Live-holder exclusion and process-death release", + "required_assertion": "Old owner cannot remove successor ownership", + "required_in_tickets": [ + "J-01" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-01", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_file_lock_regressions.py::test_aged_live_owner_kill_successor_and_third_owner", + "kind": "real_storage", + "source": { + "path": "tests/test_file_lock_regressions.py", + "sha256": "23302924a1771800e98c377a166297031a4a9d58d6da1abecd80cb912235359f" + }, + "fixtures": [ + { + "path": "tests/test_file_lock_regressions.py", + "sha256": "23302924a1771800e98c377a166297031a4a9d58d6da1abecd80cb912235359f" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J04", + "ticket": "J-02", + "scenario": "Memory/page interrupted write", + "required_assertion": "Recovery yields a consistent memory/provenance pair", + "required_in_tickets": [ + "J-02" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-02", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_durable_storage.py::test_fault_rolls_back_entire_pair[before_transaction]", + "kind": "injected_storage_fault", + "source": { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + }, + "fixtures": [ + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_durable_storage.py::test_fault_rolls_back_entire_pair[after_page_insert]", + "kind": "injected_storage_fault", + "source": { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + }, + "fixtures": [ + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_durable_storage.py::test_fault_rolls_back_entire_pair[after_fact_insert]", + "kind": "injected_storage_fault", + "source": { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + }, + "fixtures": [ + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_durable_storage.py::test_fault_rolls_back_entire_pair[after_outbox_receipt]", + "kind": "injected_storage_fault", + "source": { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + }, + "fixtures": [ + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_durable_storage.py::test_fault_rolls_back_entire_pair[before_commit]", + "kind": "injected_storage_fault", + "source": { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + }, + "fixtures": [ + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[before_transaction-False]", + "kind": "real_storage", + "status": "not_run", + "source": { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + }, + "fixtures": [ + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Existing J02 spawned child calls os._exit(37) at before_transaction, after_page_insert, after_fact_insert, after_outbox_receipt, or after_commit; fresh SQLite process view and retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + } + ], + "assertions": [ + "Child exits at requested boundary; reopened page/fact/receipt counts are all zero before commit or all one after commit.", + "Retry yields revision 1 and one page; child has bounded join, terminate and kill teardown." + ], + "evidence_limits": [ + "Process exit is real; kill point selected by trusted fault hook. Does not emulate machine power loss.", + "Existing node asserts pair counts and idempotent recovery; no claim of a separately asserted byte-for-byte provenance comparison." + ] + }, + { + "node_id": "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[after_page_insert-False]", + "kind": "real_storage", + "status": "not_run", + "source": { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + }, + "fixtures": [ + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Existing J02 spawned child calls os._exit(37) at before_transaction, after_page_insert, after_fact_insert, after_outbox_receipt, or after_commit; fresh SQLite process view and retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + } + ], + "assertions": [ + "Child exits at requested boundary; reopened page/fact/receipt counts are all zero before commit or all one after commit.", + "Retry yields revision 1 and one page; child has bounded join, terminate and kill teardown." + ], + "evidence_limits": [ + "Process exit is real; kill point selected by trusted fault hook. Does not emulate machine power loss.", + "Existing node asserts pair counts and idempotent recovery; no claim of a separately asserted byte-for-byte provenance comparison." + ] + }, + { + "node_id": "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[after_fact_insert-False]", + "kind": "real_storage", + "status": "not_run", + "source": { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + }, + "fixtures": [ + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Existing J02 spawned child calls os._exit(37) at before_transaction, after_page_insert, after_fact_insert, after_outbox_receipt, or after_commit; fresh SQLite process view and retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + } + ], + "assertions": [ + "Child exits at requested boundary; reopened page/fact/receipt counts are all zero before commit or all one after commit.", + "Retry yields revision 1 and one page; child has bounded join, terminate and kill teardown." + ], + "evidence_limits": [ + "Process exit is real; kill point selected by trusted fault hook. Does not emulate machine power loss.", + "Existing node asserts pair counts and idempotent recovery; no claim of a separately asserted byte-for-byte provenance comparison." + ] + }, + { + "node_id": "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[after_outbox_receipt-False]", + "kind": "real_storage", + "status": "not_run", + "source": { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + }, + "fixtures": [ + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Existing J02 spawned child calls os._exit(37) at before_transaction, after_page_insert, after_fact_insert, after_outbox_receipt, or after_commit; fresh SQLite process view and retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + } + ], + "assertions": [ + "Child exits at requested boundary; reopened page/fact/receipt counts are all zero before commit or all one after commit.", + "Retry yields revision 1 and one page; child has bounded join, terminate and kill teardown." + ], + "evidence_limits": [ + "Process exit is real; kill point selected by trusted fault hook. Does not emulate machine power loss.", + "Existing node asserts pair counts and idempotent recovery; no claim of a separately asserted byte-for-byte provenance comparison." + ] + }, + { + "node_id": "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[after_commit-True]", + "kind": "real_storage", + "status": "not_run", + "source": { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + }, + "fixtures": [ + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Existing J02 spawned child calls os._exit(37) at before_transaction, after_page_insert, after_fact_insert, after_outbox_receipt, or after_commit; fresh SQLite process view and retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + } + ], + "assertions": [ + "Child exits at requested boundary; reopened page/fact/receipt counts are all zero before commit or all one after commit.", + "Retry yields revision 1 and one page; child has bounded join, terminate and kill teardown." + ], + "evidence_limits": [ + "Process exit is real; kill point selected by trusted fault hook. Does not emulate machine power loss.", + "Existing node asserts pair counts and idempotent recovery; no claim of a separately asserted byte-for-byte provenance comparison." + ] + } + ], + "additional_mapping_required": false + } + ] + }, + { + "case_id": "J05", + "ticket": "J-02", + "scenario": "Duplicate ingest event", + "required_assertion": "One logical operation is committed for the idempotency key", + "required_in_tickets": [ + "J-02" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-02", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_durable_storage.py::test_multiprocess_duplicate_keys_and_namespace_isolation", + "kind": "real_storage", + "source": { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + }, + "fixtures": [ + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_durable_storage.py::test_public_facade_lost_ack_restarts_without_provider_or_side_effects", + "kind": "real_storage", + "source": { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + }, + "fixtures": [ + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J06", + "ticket": "J-04", + "scenario": "Same-path source edit", + "required_assertion": "Hash-based freshness detects changed content", + "required_in_tickets": [ + "J-04" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-04", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_code_context.py::test_same_size_edit_new_removed_and_old_generation", + "kind": "real_parser", + "source": { + "path": "tests/test_code_context.py", + "sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09" + }, + "fixtures": [ + { + "path": "tests/test_code_context.py", + "sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J07", + "ticket": "J-04", + "scenario": "New source file", + "required_assertion": "Coverage records the newly unindexed file", + "required_in_tickets": [ + "J-04" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-04", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_code_context.py::test_same_size_edit_new_removed_and_old_generation", + "kind": "real_parser", + "source": { + "path": "tests/test_code_context.py", + "sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09" + }, + "fixtures": [ + { + "path": "tests/test_code_context.py", + "sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J08", + "ticket": "J-04", + "scenario": "Removed source file", + "required_assertion": "Removal is distinguished from unreadable/unavailable state", + "required_in_tickets": [ + "J-04" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-04", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_code_context.py::test_same_size_edit_new_removed_and_old_generation", + "kind": "real_parser", + "source": { + "path": "tests/test_code_context.py", + "sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09" + }, + "fixtures": [ + { + "path": "tests/test_code_context.py", + "sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_code_context.py::test_unsupported_encoding_parse_and_unreadable_unknown", + "kind": "real_parser", + "source": { + "path": "tests/test_code_context.py", + "sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09" + }, + "fixtures": [ + { + "path": "tests/test_code_context.py", + "sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J09", + "ticket": "J-03", + "scenario": "Workspace path scope", + "required_assertion": "Results remain in the requested authorized repository/path scope", + "required_in_tickets": [ + "J-03", + "J-04" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-03", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_scoped_research.py::test_repository_ids_same_basename_and_branch_snapshots_stay_distinct", + "kind": "public_api", + "source": { + "path": "tests/test_scoped_research.py", + "sha256": "428d4c17df53220a76f4e38c1be91f50d025418063613eac58dc59ec5bd17108" + }, + "fixtures": [ + { + "path": "tests/test_scoped_research.py", + "sha256": "428d4c17df53220a76f4e38c1be91f50d025418063613eac58dc59ec5bd17108" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + }, + { + "stage_id": "J-04", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_code_context.py::test_real_parser_cycle_scope_depth_workspace", + "kind": "real_parser", + "source": { + "path": "tests/test_code_context.py", + "sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09" + }, + "fixtures": [ + { + "path": "tests/test_code_context.py", + "sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J10", + "ticket": "J-04", + "scenario": "Workspace traversal depth", + "required_assertion": "Single-repo and workspace depth contracts agree", + "required_in_tickets": [ + "J-04" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-04", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_code_context.py::test_real_parser_cycle_scope_depth_workspace", + "kind": "real_parser", + "source": { + "path": "tests/test_code_context.py", + "sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09" + }, + "fixtures": [ + { + "path": "tests/test_code_context.py", + "sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J11", + "ticket": "J-05", + "scenario": "Pure symbol rename", + "required_assertion": "An evidenced new binding preserves historical memory", + "required_in_tickets": [ + "J-05" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-05", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_code_anchors.py::test_j11_samefile_rename_persists_fact_and_revision", + "kind": "real_parser", + "source": { + "path": "tests/test_code_anchors.py", + "sha256": "8255edab92b341ef41dd5556a68f3f2be8e52b0e940e7e9e98891f2f5cced3cb" + }, + "fixtures": [ + { + "path": "tests/test_code_anchors.py", + "sha256": "8255edab92b341ef41dd5556a68f3f2be8e52b0e940e7e9e98891f2f5cced3cb" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J12", + "ticket": "J-05", + "scenario": "Pure file/symbol move", + "required_assertion": "Correct symbol binding follows the move with provenance", + "required_in_tickets": [ + "J-05" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-05", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_code_anchors.py::test_j12_move_and_rename_move[False]", + "kind": "real_parser", + "source": { + "path": "tests/test_code_anchors.py", + "sha256": "8255edab92b341ef41dd5556a68f3f2be8e52b0e940e7e9e98891f2f5cced3cb" + }, + "fixtures": [ + { + "path": "tests/test_code_anchors.py", + "sha256": "8255edab92b341ef41dd5556a68f3f2be8e52b0e940e7e9e98891f2f5cced3cb" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_code_anchors.py::test_j12_move_and_rename_move[True]", + "kind": "real_parser", + "source": { + "path": "tests/test_code_anchors.py", + "sha256": "8255edab92b341ef41dd5556a68f3f2be8e52b0e940e7e9e98891f2f5cced3cb" + }, + "fixtures": [ + { + "path": "tests/test_code_anchors.py", + "sha256": "8255edab92b341ef41dd5556a68f3f2be8e52b0e940e7e9e98891f2f5cced3cb" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J13", + "ticket": "J-05", + "scenario": "Ambiguous similar symbols", + "required_assertion": "No arbitrary reassignment; state remains unknown", + "required_in_tickets": [ + "J-05" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-05", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_code_anchors.py::test_j13_all_identical_getters_are_ambiguous_and_evidence_bounded", + "kind": "real_parser", + "source": { + "path": "tests/test_code_anchors.py", + "sha256": "8255edab92b341ef41dd5556a68f3f2be8e52b0e940e7e9e98891f2f5cced3cb" + }, + "fixtures": [ + { + "path": "tests/test_code_anchors.py", + "sha256": "8255edab92b341ef41dd5556a68f3f2be8e52b0e940e7e9e98891f2f5cced3cb" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J14", + "ticket": "J-05", + "scenario": "Index behind worktree", + "required_assertion": "Stale graph absence does not prove fact deletion", + "required_in_tickets": [ + "J-05" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-05", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_code_anchors.py::test_j14_stale_snapshot_and_shifted_lines_never_read_current_disk", + "kind": "real_parser", + "source": { + "path": "tests/test_code_anchors.py", + "sha256": "8255edab92b341ef41dd5556a68f3f2be8e52b0e940e7e9e98891f2f5cced3cb" + }, + "fixtures": [ + { + "path": "tests/test_code_anchors.py", + "sha256": "8255edab92b341ef41dd5556a68f3f2be8e52b0e940e7e9e98891f2f5cced3cb" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J15", + "ticket": "J-05", + "scenario": "Unavailable worktree", + "required_assertion": "No mass expiry from inability to inspect the repository", + "required_in_tickets": [ + "J-05" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-05", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_code_anchors.py::test_j15_missing_checkout_preserves_facts_and_history", + "kind": "real_parser", + "source": { + "path": "tests/test_code_anchors.py", + "sha256": "8255edab92b341ef41dd5556a68f3f2be8e52b0e940e7e9e98891f2f5cced3cb" + }, + "fixtures": [ + { + "path": "tests/test_code_anchors.py", + "sha256": "8255edab92b341ef41dd5556a68f3f2be8e52b0e940e7e9e98891f2f5cced3cb" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J16", + "ticket": "J-06", + "scenario": "Unfinished work loses anchor", + "required_assertion": "Obligation remains open and can fall back to broader scope", + "required_in_tickets": [ + "J-06" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-06", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_open_work_bindings.py::test_j16_j31_real_binding_move_disappearance_forget_keep_obligation[# code removed\\n-orphaned_confirmed]", + "kind": "real_parser", + "status": "not_run", + "source": { + "path": "tests/test_open_work_bindings.py", + "sha256": "645628f66ceddab3ebc92c5260f3289aa4c7bea19a165c135d337417e9857f59" + }, + "fixtures": [ + { + "path": "tests/test_open_work_bindings.py", + "sha256": "645628f66ceddab3ebc92c5260f3289aa4c7bea19a165c135d337417e9857f59" + } + ], + "fixture_description": "Reviewed existing J06 test: temporary Git checkout parsed by actual J04 Node/tree-sitter, J02 fact, J05 logical binding, J06 obligation; file move then confirmed removal or malformed-source uncertainty.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/scope.py", + "sha256": "2762e46016b2f4e1a6ea6d95208954724f1cfef8e4e59812a19fc06e97bdf34a" + }, + { + "path": "jitmind/code_context/__init__.py", + "sha256": "0bdda619ccabbb7f4894b106572885cf15b5c86232bfd6f333f6ca1b8b75f211" + }, + { + "path": "jitmind/code_context/models.py", + "sha256": "84686d3cdb1f34e6111652956e65b90b01fd19487308a268022a66b14ea44878" + }, + { + "path": "jitmind/code_context/process.py", + "sha256": "ef9baf49a5bbe761fbffa1f60ef172b8f53c587eaffc13c4e179f2700462f77a" + }, + { + "path": "jitmind/code_context/retriever.py", + "sha256": "822dc84804992b8bd9fe7de62e535843585091350f8ff5a2311a05eaf51150f4" + }, + { + "path": "jitmind/code_context/service.py", + "sha256": "16daa9b16b9a55f130ca61204c96d40e8abb279709dbd4c36b81e4c99afbe873" + }, + { + "path": "jitmind/code_context/snapshot.py", + "sha256": "45a35d8a3455cde10816ff3e2feef3a7a21174bbec41326635d94394fec27272" + }, + { + "path": "jitmind/code_memory/anchors.py", + "sha256": "98d9715ad0faba844638859e5f49d8ccb58cd9a7e67c56c7376b81b08c24e31a" + }, + { + "path": "jitmind/code_memory/binding_models.py", + "sha256": "39c9e9676f58314e4e3d9073efd19f0072023440cdb6fc61f9d802fc9a9f203c" + }, + { + "path": "jitmind/code_memory/binding_storage.py", + "sha256": "5684d3bf4269703f87f4232f0d3fd32482d90be704170f57e1cc6670ab539c1f" + }, + { + "path": "jitmind/code_memory/revalidation.py", + "sha256": "ada66aa4f8d553d8930eb37aff00662544d7216bdfae941d643485ca8cdd92d5" + }, + { + "path": "jitmind/code_memory/open_work.py", + "sha256": "330b670fa75dfc33bd0013a4af3293fed415c29ef4f1df8df2f3295642e3a23c" + }, + { + "path": "jitmind/code_memory/work_storage.py", + "sha256": "f0a2775db9046f8b01007c946a586e9a4bd1ab3763fff5fef87df0d5555b8362" + }, + { + "path": "jitmind/code_memory/lesson_models.py", + "sha256": "447721bf5d7c7b972a4d3b1bda171c674a107d3aba50c90fa0033403f4c5b787" + }, + { + "path": "jitmind/code_memory/preflight.py", + "sha256": "7119d160107db1f0828fa31affc3aba18bcd716163df562a8c77c45cfebc6258" + } + ], + "assertions": [ + "Binding starts at source.py, follows real move to moved.py, then becomes orphaned_confirmed or unknown.", + "OpenWorkService.binding_locations falls back to exact authorized repo; obligation stays open at revision 1 through primary forget.", + "Real lesson projection/preflight and binding history run in same chain." + ], + "evidence_limits": [ + "Only the two exact collected parameters are reused; current tests and modules are the attested J10 snapshot.", + "Broader repository scope is a location fallback, not task completion or proof of code deletion in malformed input." + ] + }, + { + "node_id": "tests/test_open_work_bindings.py::test_j16_j31_real_binding_move_disappearance_forget_keep_obligation[invalid syntax ???\\n-unknown]", + "kind": "real_parser", + "status": "not_run", + "source": { + "path": "tests/test_open_work_bindings.py", + "sha256": "645628f66ceddab3ebc92c5260f3289aa4c7bea19a165c135d337417e9857f59" + }, + "fixtures": [ + { + "path": "tests/test_open_work_bindings.py", + "sha256": "645628f66ceddab3ebc92c5260f3289aa4c7bea19a165c135d337417e9857f59" + } + ], + "fixture_description": "Reviewed existing J06 test: temporary Git checkout parsed by actual J04 Node/tree-sitter, J02 fact, J05 logical binding, J06 obligation; file move then confirmed removal or malformed-source uncertainty.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/scope.py", + "sha256": "2762e46016b2f4e1a6ea6d95208954724f1cfef8e4e59812a19fc06e97bdf34a" + }, + { + "path": "jitmind/code_context/__init__.py", + "sha256": "0bdda619ccabbb7f4894b106572885cf15b5c86232bfd6f333f6ca1b8b75f211" + }, + { + "path": "jitmind/code_context/models.py", + "sha256": "84686d3cdb1f34e6111652956e65b90b01fd19487308a268022a66b14ea44878" + }, + { + "path": "jitmind/code_context/process.py", + "sha256": "ef9baf49a5bbe761fbffa1f60ef172b8f53c587eaffc13c4e179f2700462f77a" + }, + { + "path": "jitmind/code_context/retriever.py", + "sha256": "822dc84804992b8bd9fe7de62e535843585091350f8ff5a2311a05eaf51150f4" + }, + { + "path": "jitmind/code_context/service.py", + "sha256": "16daa9b16b9a55f130ca61204c96d40e8abb279709dbd4c36b81e4c99afbe873" + }, + { + "path": "jitmind/code_context/snapshot.py", + "sha256": "45a35d8a3455cde10816ff3e2feef3a7a21174bbec41326635d94394fec27272" + }, + { + "path": "jitmind/code_memory/anchors.py", + "sha256": "98d9715ad0faba844638859e5f49d8ccb58cd9a7e67c56c7376b81b08c24e31a" + }, + { + "path": "jitmind/code_memory/binding_models.py", + "sha256": "39c9e9676f58314e4e3d9073efd19f0072023440cdb6fc61f9d802fc9a9f203c" + }, + { + "path": "jitmind/code_memory/binding_storage.py", + "sha256": "5684d3bf4269703f87f4232f0d3fd32482d90be704170f57e1cc6670ab539c1f" + }, + { + "path": "jitmind/code_memory/revalidation.py", + "sha256": "ada66aa4f8d553d8930eb37aff00662544d7216bdfae941d643485ca8cdd92d5" + }, + { + "path": "jitmind/code_memory/open_work.py", + "sha256": "330b670fa75dfc33bd0013a4af3293fed415c29ef4f1df8df2f3295642e3a23c" + }, + { + "path": "jitmind/code_memory/work_storage.py", + "sha256": "f0a2775db9046f8b01007c946a586e9a4bd1ab3763fff5fef87df0d5555b8362" + }, + { + "path": "jitmind/code_memory/lesson_models.py", + "sha256": "447721bf5d7c7b972a4d3b1bda171c674a107d3aba50c90fa0033403f4c5b787" + }, + { + "path": "jitmind/code_memory/preflight.py", + "sha256": "7119d160107db1f0828fa31affc3aba18bcd716163df562a8c77c45cfebc6258" + } + ], + "assertions": [ + "Binding starts at source.py, follows real move to moved.py, then becomes orphaned_confirmed or unknown.", + "OpenWorkService.binding_locations falls back to exact authorized repo; obligation stays open at revision 1 through primary forget.", + "Real lesson projection/preflight and binding history run in same chain." + ], + "evidence_limits": [ + "Only the two exact collected parameters are reused; current tests and modules are the attested J10 snapshot.", + "Broader repository scope is a location fallback, not task completion or proof of code deletion in malformed input." + ] + } + ], + "additional_mapping_required": false + } + ] + }, + { + "case_id": "J17", + "ticket": "J-06", + "scenario": "Explicit task resolution", + "required_assertion": "Resolver and supporting evidence are recorded exactly once", + "required_in_tickets": [ + "J-06" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-06", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_open_work.py::test_durable_cas_replay_owner_history_and_explicit_reopen", + "kind": "real_storage", + "source": { + "path": "tests/test_open_work.py", + "sha256": "b0b192f5bd1ecfe39811346eb4ce912a85a15d00c446e31e8f2a01493e957597" + }, + "fixtures": [ + { + "path": "tests/test_open_work.py", + "sha256": "b0b192f5bd1ecfe39811346eb4ce912a85a15d00c446e31e8f2a01493e957597" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_open_work.py::test_competing_resolution_accepts_one", + "kind": "real_storage", + "source": { + "path": "tests/test_open_work.py", + "sha256": "b0b192f5bd1ecfe39811346eb4ce912a85a15d00c446e31e8f2a01493e957597" + }, + "fixtures": [ + { + "path": "tests/test_open_work.py", + "sha256": "b0b192f5bd1ecfe39811346eb4ce912a85a15d00c446e31e8f2a01493e957597" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J18", + "ticket": "J-06", + "scenario": "Preflight repeated edit", + "required_assertion": "Bounded once-per-symbol/session behavior avoids prompt flooding", + "required_in_tickets": [ + "J-06" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-06", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_preflight.py::test_version_dedup_replay_two_lessons_and_wrapper_budget", + "kind": "public_api", + "source": { + "path": "tests/test_preflight.py", + "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + }, + "fixtures": [ + { + "path": "tests/test_preflight.py", + "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J19", + "ticket": "J-06", + "scenario": "Poisoned imported law label", + "required_assertion": "Imported content cannot promote itself to trusted policy", + "required_in_tickets": [ + "J-06" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-06", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_preflight.py::test_imported_law_untrusted_authored_positive_and_spoof_denied", + "kind": "public_api", + "source": { + "path": "tests/test_preflight.py", + "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + }, + "fixtures": [ + { + "path": "tests/test_preflight.py", + "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J20", + "ticket": "J-06", + "scenario": "Preflight storage contention", + "required_assertion": "Bounded latency and explicit degraded behavior", + "required_in_tickets": [ + "J-06" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-06", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_preflight.py::test_independent_process_lock_bounded_deferred_and_release[work-IMMEDIATE]", + "kind": "real_storage", + "source": { + "path": "tests/test_preflight.py", + "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + }, + "fixtures": [ + { + "path": "tests/test_preflight.py", + "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_preflight.py::test_independent_process_lock_bounded_deferred_and_release[work-EXCLUSIVE]", + "kind": "real_storage", + "source": { + "path": "tests/test_preflight.py", + "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + }, + "fixtures": [ + { + "path": "tests/test_preflight.py", + "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_preflight.py::test_independent_process_lock_bounded_deferred_and_release[facts-IMMEDIATE]", + "kind": "real_storage", + "source": { + "path": "tests/test_preflight.py", + "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + }, + "fixtures": [ + { + "path": "tests/test_preflight.py", + "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_preflight.py::test_independent_process_lock_bounded_deferred_and_release[facts-EXCLUSIVE]", + "kind": "real_storage", + "source": { + "path": "tests/test_preflight.py", + "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + }, + "fixtures": [ + { + "path": "tests/test_preflight.py", + "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J21", + "ticket": "J-07", + "scenario": "Checkpoint has event gap", + "required_assertion": "Incomplete event range cannot be published as closed", + "required_in_tickets": [ + "J-07" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-07", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_checkpoint_ledger.py::test_missing_event_and_identity_conflicts", + "kind": "real_storage", + "source": { + "path": "tests/test_checkpoint_ledger.py", + "sha256": "a9ff3ffe41f0cba68e0e7b86ee425c69e9ee912c169fa2323dc510c5a40313b8" + }, + "fixtures": [ + { + "path": "tests/test_checkpoint_ledger.py", + "sha256": "a9ff3ffe41f0cba68e0e7b86ee425c69e9ee912c169fa2323dc510c5a40313b8" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J22", + "ticket": "J-07", + "scenario": "Checkpoint cuts tool interaction", + "required_assertion": "Unsafe boundary is rejected or postponed", + "required_in_tickets": [ + "J-07" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-07", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_checkpoint_ledger.py::test_overlapping_calls_and_midrange_closed_call", + "kind": "real_storage", + "source": { + "path": "tests/test_checkpoint_ledger.py", + "sha256": "a9ff3ffe41f0cba68e0e7b86ee425c69e9ee912c169fa2323dc510c5a40313b8" + }, + "fixtures": [ + { + "path": "tests/test_checkpoint_ledger.py", + "sha256": "a9ff3ffe41f0cba68e0e7b86ee425c69e9ee912c169fa2323dc510c5a40313b8" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_checkpoint_ledger.py::test_tool_boundaries_and_explicit_terminals[tool_result]", + "kind": "real_storage", + "status": "not_run", + "source": { + "path": "tests/test_checkpoint_ledger.py", + "sha256": "a9ff3ffe41f0cba68e0e7b86ee425c69e9ee912c169fa2323dc510c5a40313b8" + }, + "fixtures": [ + { + "path": "tests/test_checkpoint_ledger.py", + "sha256": "a9ff3ffe41f0cba68e0e7b86ee425c69e9ee912c169fa2323dc510c5a40313b8" + } + ], + "fixture_description": "Existing real SQLiteCheckpointLedger stream: tool_start at 0, message at 1, terminal at 2; all three terminal kinds have exact collected parameters.", + "modules_composed": [ + { + "path": "jitmind/scope.py", + "sha256": "2762e46016b2f4e1a6ea6d95208954724f1cfef8e4e59812a19fc06e97bdf34a" + }, + { + "path": "jitmind/checkpoints/__init__.py", + "sha256": "4d54e3f91114b474c337fbd460653e46210c2c668fcb557c231560e8477c0017" + }, + { + "path": "jitmind/checkpoints/ledger.py", + "sha256": "ba500b7dff478277252df4647e4c9ddd48656c1f58667357cf38a2d5639f88e4" + } + ], + "assertions": [ + "Rejects range 0..1 before and after late terminal (end cut), and 1..2 / 2..2 / 1..1 (start cut or wholly inside interaction).", + "Complete 0..2 publishes revision 1; subsequent 3..3 allowed; repeated/unknown terminals rejected." + ], + "evidence_limits": [ + "Both boundary directions are directly asserted by the existing node. No provider transcript or remote checkpoint store." + ] + }, + { + "node_id": "tests/test_checkpoint_ledger.py::test_tool_boundaries_and_explicit_terminals[tool_cancel]", + "kind": "real_storage", + "status": "not_run", + "source": { + "path": "tests/test_checkpoint_ledger.py", + "sha256": "a9ff3ffe41f0cba68e0e7b86ee425c69e9ee912c169fa2323dc510c5a40313b8" + }, + "fixtures": [ + { + "path": "tests/test_checkpoint_ledger.py", + "sha256": "a9ff3ffe41f0cba68e0e7b86ee425c69e9ee912c169fa2323dc510c5a40313b8" + } + ], + "fixture_description": "Existing real SQLiteCheckpointLedger stream: tool_start at 0, message at 1, terminal at 2; all three terminal kinds have exact collected parameters.", + "modules_composed": [ + { + "path": "jitmind/scope.py", + "sha256": "2762e46016b2f4e1a6ea6d95208954724f1cfef8e4e59812a19fc06e97bdf34a" + }, + { + "path": "jitmind/checkpoints/__init__.py", + "sha256": "4d54e3f91114b474c337fbd460653e46210c2c668fcb557c231560e8477c0017" + }, + { + "path": "jitmind/checkpoints/ledger.py", + "sha256": "ba500b7dff478277252df4647e4c9ddd48656c1f58667357cf38a2d5639f88e4" + } + ], + "assertions": [ + "Rejects range 0..1 before and after late terminal (end cut), and 1..2 / 2..2 / 1..1 (start cut or wholly inside interaction).", + "Complete 0..2 publishes revision 1; subsequent 3..3 allowed; repeated/unknown terminals rejected." + ], + "evidence_limits": [ + "Both boundary directions are directly asserted by the existing node. No provider transcript or remote checkpoint store." + ] + }, + { + "node_id": "tests/test_checkpoint_ledger.py::test_tool_boundaries_and_explicit_terminals[tool_timeout]", + "kind": "real_storage", + "status": "not_run", + "source": { + "path": "tests/test_checkpoint_ledger.py", + "sha256": "a9ff3ffe41f0cba68e0e7b86ee425c69e9ee912c169fa2323dc510c5a40313b8" + }, + "fixtures": [ + { + "path": "tests/test_checkpoint_ledger.py", + "sha256": "a9ff3ffe41f0cba68e0e7b86ee425c69e9ee912c169fa2323dc510c5a40313b8" + } + ], + "fixture_description": "Existing real SQLiteCheckpointLedger stream: tool_start at 0, message at 1, terminal at 2; all three terminal kinds have exact collected parameters.", + "modules_composed": [ + { + "path": "jitmind/scope.py", + "sha256": "2762e46016b2f4e1a6ea6d95208954724f1cfef8e4e59812a19fc06e97bdf34a" + }, + { + "path": "jitmind/checkpoints/__init__.py", + "sha256": "4d54e3f91114b474c337fbd460653e46210c2c668fcb557c231560e8477c0017" + }, + { + "path": "jitmind/checkpoints/ledger.py", + "sha256": "ba500b7dff478277252df4647e4c9ddd48656c1f58667357cf38a2d5639f88e4" + } + ], + "assertions": [ + "Rejects range 0..1 before and after late terminal (end cut), and 1..2 / 2..2 / 1..1 (start cut or wholly inside interaction).", + "Complete 0..2 publishes revision 1; subsequent 3..3 allowed; repeated/unknown terminals rejected." + ], + "evidence_limits": [ + "Both boundary directions are directly asserted by the existing node. No provider transcript or remote checkpoint store." + ] + } + ], + "additional_mapping_required": false + } + ] + }, + { + "case_id": "J23", + "ticket": "J-03", + "scenario": "Cross-scope retrieval/cache", + "required_assertion": "Authorization filters candidates and caches before exposure", + "required_in_tickets": [ + "J-03", + "J-04" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-03", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_scoped_research.py::test_real_stores_are_isolated_before_build_rerank_prompt_and_logs", + "kind": "public_api", + "source": { + "path": "tests/test_scoped_research.py", + "sha256": "428d4c17df53220a76f4e38c1be91f50d025418063613eac58dc59ec5bd17108" + }, + "fixtures": [ + { + "path": "tests/test_scoped_research.py", + "sha256": "428d4c17df53220a76f4e38c1be91f50d025418063613eac58dc59ec5bd17108" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_scoped_research.py::test_cache_rechecks_snapshot_and_regrant_and_canonical_metadata", + "kind": "public_api", + "source": { + "path": "tests/test_scoped_research.py", + "sha256": "428d4c17df53220a76f4e38c1be91f50d025418063613eac58dc59ec5bd17108" + }, + "fixtures": [ + { + "path": "tests/test_scoped_research.py", + "sha256": "428d4c17df53220a76f4e38c1be91f50d025418063613eac58dc59ec5bd17108" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + }, + { + "stage_id": "J-04", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_code_context.py::test_denied_before_read_and_revoked_before_return", + "kind": "real_parser", + "source": { + "path": "tests/test_code_context.py", + "sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09" + }, + "fixtures": [ + { + "path": "tests/test_code_context.py", + "sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J24", + "ticket": "J-03", + "scenario": "Temporal boundary and timezone", + "required_assertion": "Valid/transaction-time answers respect normalized boundary semantics", + "required_in_tickets": [ + "J-03" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-03", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_scoped_temporal.py::test_seven_query_reviewed_retry_limit_oracle", + "kind": "temporal_oracle", + "source": { + "path": "tests/test_scoped_temporal.py", + "sha256": "e335712d09b7ecdc5e466b63008fb717dab4b9b772623e6b51df840ec71eb66e" + }, + "fixtures": [ + { + "path": "tests/test_scoped_temporal.py", + "sha256": "e335712d09b7ecdc5e466b63008fb717dab4b9b772623e6b51df840ec71eb66e" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_scoped_temporal.py::test_utc_offsets_and_exact_half_open_boundaries", + "kind": "temporal_oracle", + "source": { + "path": "tests/test_scoped_temporal.py", + "sha256": "e335712d09b7ecdc5e466b63008fb717dab4b9b772623e6b51df840ec71eb66e" + }, + "fixtures": [ + { + "path": "tests/test_scoped_temporal.py", + "sha256": "e335712d09b7ecdc5e466b63008fb717dab4b9b772623e6b51df840ec71eb66e" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_scoped_temporal.py::test_declared_single_valued_overlap_fails_and_multiple_values_opt_in", + "kind": "temporal_oracle", + "source": { + "path": "tests/test_scoped_temporal.py", + "sha256": "e335712d09b7ecdc5e466b63008fb717dab4b9b772623e6b51df840ec71eb66e" + }, + "fixtures": [ + { + "path": "tests/test_scoped_temporal.py", + "sha256": "e335712d09b7ecdc5e466b63008fb717dab4b9b772623e6b51df840ec71eb66e" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_scoped_temporal.py::test_legacy_naive_query_input_compatibility_is_unchanged", + "kind": "temporal_oracle", + "source": { + "path": "tests/test_scoped_temporal.py", + "sha256": "e335712d09b7ecdc5e466b63008fb717dab4b9b772623e6b51df840ec71eb66e" + }, + "fixtures": [ + { + "path": "tests/test_scoped_temporal.py", + "sha256": "e335712d09b7ecdc5e466b63008fb717dab4b9b772623e6b51df840ec71eb66e" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J25", + "ticket": "J-02", + "scenario": "Corrupt store and interrupted staging", + "required_assertion": "Corruption is reported without silently manufacturing an empty successful migration; interrupted staged import does not replace authoritative source", + "required_in_tickets": [ + "J-02" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-02", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_durable_migration.py::test_staging_requires_quiescence_and_detects_changed_source", + "kind": "migration", + "source": { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + }, + "fixtures": [ + { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + }, + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_durable_migration.py::test_invalid_migration_refuses_without_changes[truncated]", + "kind": "migration", + "status": "not_run", + "source": { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + }, + "fixtures": [ + { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + } + ], + "fixture_description": "Existing truncated/duplicate-key/NaN legacy-source rejection and three exception rollback nodes; new real child exit(73) after import pages or before import commit; source JSON byte snapshots and clean retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/storage/migration.py", + "sha256": "26cf90e0911fe6bfae875ef31c50f0b8cbf94b05c2d5a694cd5408622533a15a" + }, + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + } + ], + "assertions": [ + "Corrupt source raises exact MigrationError without creating a candidate or changing original JSON.", + "Existing three injected exception nodes leave source and candidate empty and permit positive retry.", + "Real child exits roll back namespaces/pages/facts/operations/outbox/aliases/imports; original source bytes unchanged.", + "Restaging and retry preserve fact ID, page provenance and alias; duplicate import keeps revision 1." + ], + "evidence_limits": [ + "Corrupt cases and exception nodes are reused unchanged; real process-exit supplement owns its own small fixture.", + "No concurrent legacy writer or machine-power-loss simulation; staging is explicitly quiesced." + ] + }, + { + "node_id": "tests/test_durable_migration.py::test_invalid_migration_refuses_without_changes[duplicate_json_key]", + "kind": "migration", + "status": "not_run", + "source": { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + }, + "fixtures": [ + { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + } + ], + "fixture_description": "Existing truncated/duplicate-key/NaN legacy-source rejection and three exception rollback nodes; new real child exit(73) after import pages or before import commit; source JSON byte snapshots and clean retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/storage/migration.py", + "sha256": "26cf90e0911fe6bfae875ef31c50f0b8cbf94b05c2d5a694cd5408622533a15a" + }, + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + } + ], + "assertions": [ + "Corrupt source raises exact MigrationError without creating a candidate or changing original JSON.", + "Existing three injected exception nodes leave source and candidate empty and permit positive retry.", + "Real child exits roll back namespaces/pages/facts/operations/outbox/aliases/imports; original source bytes unchanged.", + "Restaging and retry preserve fact ID, page provenance and alias; duplicate import keeps revision 1." + ], + "evidence_limits": [ + "Corrupt cases and exception nodes are reused unchanged; real process-exit supplement owns its own small fixture.", + "No concurrent legacy writer or machine-power-loss simulation; staging is explicitly quiesced." + ] + }, + { + "node_id": "tests/test_durable_migration.py::test_invalid_migration_refuses_without_changes[nan]", + "kind": "migration", + "status": "not_run", + "source": { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + }, + "fixtures": [ + { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + } + ], + "fixture_description": "Existing truncated/duplicate-key/NaN legacy-source rejection and three exception rollback nodes; new real child exit(73) after import pages or before import commit; source JSON byte snapshots and clean retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/storage/migration.py", + "sha256": "26cf90e0911fe6bfae875ef31c50f0b8cbf94b05c2d5a694cd5408622533a15a" + }, + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + } + ], + "assertions": [ + "Corrupt source raises exact MigrationError without creating a candidate or changing original JSON.", + "Existing three injected exception nodes leave source and candidate empty and permit positive retry.", + "Real child exits roll back namespaces/pages/facts/operations/outbox/aliases/imports; original source bytes unchanged.", + "Restaging and retry preserve fact ID, page provenance and alias; duplicate import keeps revision 1." + ], + "evidence_limits": [ + "Corrupt cases and exception nodes are reused unchanged; real process-exit supplement owns its own small fixture.", + "No concurrent legacy writer or machine-power-loss simulation; staging is explicitly quiesced." + ] + }, + { + "node_id": "tests/test_durable_migration.py::test_staged_failure_leaves_legacy_and_candidate_unchanged[before_import]", + "kind": "migration", + "status": "not_run", + "source": { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + }, + "fixtures": [ + { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + } + ], + "fixture_description": "Existing truncated/duplicate-key/NaN legacy-source rejection and three exception rollback nodes; new real child exit(73) after import pages or before import commit; source JSON byte snapshots and clean retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/storage/migration.py", + "sha256": "26cf90e0911fe6bfae875ef31c50f0b8cbf94b05c2d5a694cd5408622533a15a" + }, + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + } + ], + "assertions": [ + "Corrupt source raises exact MigrationError without creating a candidate or changing original JSON.", + "Existing three injected exception nodes leave source and candidate empty and permit positive retry.", + "Real child exits roll back namespaces/pages/facts/operations/outbox/aliases/imports; original source bytes unchanged.", + "Restaging and retry preserve fact ID, page provenance and alias; duplicate import keeps revision 1." + ], + "evidence_limits": [ + "Corrupt cases and exception nodes are reused unchanged; real process-exit supplement owns its own small fixture.", + "No concurrent legacy writer or machine-power-loss simulation; staging is explicitly quiesced." + ] + }, + { + "node_id": "tests/test_durable_migration.py::test_staged_failure_leaves_legacy_and_candidate_unchanged[after_import_pages]", + "kind": "migration", + "status": "not_run", + "source": { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + }, + "fixtures": [ + { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + } + ], + "fixture_description": "Existing truncated/duplicate-key/NaN legacy-source rejection and three exception rollback nodes; new real child exit(73) after import pages or before import commit; source JSON byte snapshots and clean retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/storage/migration.py", + "sha256": "26cf90e0911fe6bfae875ef31c50f0b8cbf94b05c2d5a694cd5408622533a15a" + }, + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + } + ], + "assertions": [ + "Corrupt source raises exact MigrationError without creating a candidate or changing original JSON.", + "Existing three injected exception nodes leave source and candidate empty and permit positive retry.", + "Real child exits roll back namespaces/pages/facts/operations/outbox/aliases/imports; original source bytes unchanged.", + "Restaging and retry preserve fact ID, page provenance and alias; duplicate import keeps revision 1." + ], + "evidence_limits": [ + "Corrupt cases and exception nodes are reused unchanged; real process-exit supplement owns its own small fixture.", + "No concurrent legacy writer or machine-power-loss simulation; staging is explicitly quiesced." + ] + }, + { + "node_id": "tests/test_durable_migration.py::test_staged_failure_leaves_legacy_and_candidate_unchanged[before_import_commit]", + "kind": "migration", + "status": "not_run", + "source": { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + }, + "fixtures": [ + { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + } + ], + "fixture_description": "Existing truncated/duplicate-key/NaN legacy-source rejection and three exception rollback nodes; new real child exit(73) after import pages or before import commit; source JSON byte snapshots and clean retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/storage/migration.py", + "sha256": "26cf90e0911fe6bfae875ef31c50f0b8cbf94b05c2d5a694cd5408622533a15a" + }, + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + } + ], + "assertions": [ + "Corrupt source raises exact MigrationError without creating a candidate or changing original JSON.", + "Existing three injected exception nodes leave source and candidate empty and permit positive retry.", + "Real child exits roll back namespaces/pages/facts/operations/outbox/aliases/imports; original source bytes unchanged.", + "Restaging and retry preserve fact ID, page provenance and alias; duplicate import keeps revision 1." + ], + "evidence_limits": [ + "Corrupt cases and exception nodes are reused unchanged; real process-exit supplement owns its own small fixture.", + "No concurrent legacy writer or machine-power-loss simulation; staging is explicitly quiesced." + ] + }, + { + "node_id": "tests/test_acceptance_edges.py::test_real_migration_exit_preserves_source_and_allows_retry[after_import_pages]", + "kind": "migration", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Existing truncated/duplicate-key/NaN legacy-source rejection and three exception rollback nodes; new real child exit(73) after import pages or before import commit; source JSON byte snapshots and clean retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/storage/migration.py", + "sha256": "26cf90e0911fe6bfae875ef31c50f0b8cbf94b05c2d5a694cd5408622533a15a" + }, + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + } + ], + "assertions": [ + "Corrupt source raises exact MigrationError without creating a candidate or changing original JSON.", + "Existing three injected exception nodes leave source and candidate empty and permit positive retry.", + "Real child exits roll back namespaces/pages/facts/operations/outbox/aliases/imports; original source bytes unchanged.", + "Restaging and retry preserve fact ID, page provenance and alias; duplicate import keeps revision 1." + ], + "evidence_limits": [ + "Corrupt cases and exception nodes are reused unchanged; real process-exit supplement owns its own small fixture.", + "No concurrent legacy writer or machine-power-loss simulation; staging is explicitly quiesced." + ] + }, + { + "node_id": "tests/test_acceptance_edges.py::test_real_migration_exit_preserves_source_and_allows_retry[before_import_commit]", + "kind": "migration", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Existing truncated/duplicate-key/NaN legacy-source rejection and three exception rollback nodes; new real child exit(73) after import pages or before import commit; source JSON byte snapshots and clean retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/storage/migration.py", + "sha256": "26cf90e0911fe6bfae875ef31c50f0b8cbf94b05c2d5a694cd5408622533a15a" + }, + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + } + ], + "assertions": [ + "Corrupt source raises exact MigrationError without creating a candidate or changing original JSON.", + "Existing three injected exception nodes leave source and candidate empty and permit positive retry.", + "Real child exits roll back namespaces/pages/facts/operations/outbox/aliases/imports; original source bytes unchanged.", + "Restaging and retry preserve fact ID, page provenance and alias; duplicate import keeps revision 1." + ], + "evidence_limits": [ + "Corrupt cases and exception nodes are reused unchanged; real process-exit supplement owns its own small fixture.", + "No concurrent legacy writer or machine-power-loss simulation; staging is explicitly quiesced." + ] + } + ], + "additional_mapping_required": false + } + ] + }, + { + "case_id": "J26", + "ticket": "J-02", + "scenario": "Legacy migration and post-cutover rollback", + "required_assertion": "IDs, provenance, histories and queries preserved by explicit mapping; unknown custom stores not silently transactional", + "required_in_tickets": [ + "J-02" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-02", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_durable_migration.py::test_migration_preserves_ids_metadata_temporal_history_aliases", + "kind": "migration", + "source": { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + }, + "fixtures": [ + { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + }, + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_durable_migration.py::test_backup_reopen_restore_preserves_candidate_era_writes", + "kind": "migration", + "source": { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + }, + "fixtures": [ + { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + }, + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J27", + "ticket": "J-04", + "scenario": "Traversal and context acquisition limits", + "required_assertion": "Work stops within declared bounds and preserves source identities and explicit coverage", + "required_in_tickets": [ + "J-04" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-04", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_code_context.py::test_context_budget_and_retention", + "kind": "real_parser", + "source": { + "path": "tests/test_code_context.py", + "sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09" + }, + "fixtures": [ + { + "path": "tests/test_code_context.py", + "sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_code_context.py::test_coverage_limits_and_namespace_preflight", + "kind": "real_parser", + "source": { + "path": "tests/test_code_context.py", + "sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09" + }, + "fixtures": [ + { + "path": "tests/test_code_context.py", + "sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J28", + "ticket": "J-03", + "scenario": "Canonical path and scope validation", + "required_assertion": "Reject escapes without colliding distinct repositories/identities in caches or databases", + "required_in_tickets": [ + "J-03", + "J-04" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-03", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_scoped_research.py::test_real_store_roots_with_same_basename_are_distinct_and_alias_is_rejected", + "kind": "public_api", + "source": { + "path": "tests/test_scoped_research.py", + "sha256": "428d4c17df53220a76f4e38c1be91f50d025418063613eac58dc59ec5bd17108" + }, + "fixtures": [ + { + "path": "tests/test_scoped_research.py", + "sha256": "428d4c17df53220a76f4e38c1be91f50d025418063613eac58dc59ec5bd17108" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + }, + { + "stage_id": "J-04", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_code_context.py::test_symlink_sentinel_never_opened_and_basename_identity", + "kind": "real_parser", + "source": { + "path": "tests/test_code_context.py", + "sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09" + }, + "fixtures": [ + { + "path": "tests/test_code_context.py", + "sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J29", + "ticket": "J-02", + "scenario": "Projection outbox redelivery", + "required_assertion": "Primary durability intact, replay idempotent, lag visible; no stale graph evidence declared current", + "required_in_tickets": [ + "J-02", + "J-04", + "J-05" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-02", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_durable_storage.py::test_projection_duplicate_out_of_order_and_forget_filter", + "kind": "projection", + "source": { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + }, + "fixtures": [ + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_durable_storage.py::test_projection_failure_does_not_rollback_authority", + "kind": "projection", + "source": { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + }, + "fixtures": [ + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_durable_storage.py::test_process_crash_after_projection_is_idempotent", + "kind": "projection", + "source": { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + }, + "fixtures": [ + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + }, + { + "stage_id": "J-04", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_acceptance_edges.py::test_real_parser_binding_projection_redelivery_and_primary_forget[projected]", + "kind": "projection", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Temporary unversioned checkout, actual J04 parser, J02 add/NOOP/delete, J05 binding and file move, J06 projected lesson/preflight/open task. Two schedules: primary projection already populated or original add event pending until after delete.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/scope.py", + "sha256": "2762e46016b2f4e1a6ea6d95208954724f1cfef8e4e59812a19fc06e97bdf34a" + }, + { + "path": "jitmind/code_context/__init__.py", + "sha256": "0bdda619ccabbb7f4894b106572885cf15b5c86232bfd6f333f6ca1b8b75f211" + }, + { + "path": "jitmind/code_context/models.py", + "sha256": "84686d3cdb1f34e6111652956e65b90b01fd19487308a268022a66b14ea44878" + }, + { + "path": "jitmind/code_context/process.py", + "sha256": "ef9baf49a5bbe761fbffa1f60ef172b8f53c587eaffc13c4e179f2700462f77a" + }, + { + "path": "jitmind/code_context/retriever.py", + "sha256": "822dc84804992b8bd9fe7de62e535843585091350f8ff5a2311a05eaf51150f4" + }, + { + "path": "jitmind/code_context/service.py", + "sha256": "16daa9b16b9a55f130ca61204c96d40e8abb279709dbd4c36b81e4c99afbe873" + }, + { + "path": "jitmind/code_context/snapshot.py", + "sha256": "45a35d8a3455cde10816ff3e2feef3a7a21174bbec41326635d94394fec27272" + }, + { + "path": "jitmind/code_memory/anchors.py", + "sha256": "98d9715ad0faba844638859e5f49d8ccb58cd9a7e67c56c7376b81b08c24e31a" + }, + { + "path": "jitmind/code_memory/binding_models.py", + "sha256": "39c9e9676f58314e4e3d9073efd19f0072023440cdb6fc61f9d802fc9a9f203c" + }, + { + "path": "jitmind/code_memory/binding_storage.py", + "sha256": "5684d3bf4269703f87f4232f0d3fd32482d90be704170f57e1cc6670ab539c1f" + }, + { + "path": "jitmind/code_memory/revalidation.py", + "sha256": "ada66aa4f8d553d8930eb37aff00662544d7216bdfae941d643485ca8cdd92d5" + }, + { + "path": "jitmind/code_memory/open_work.py", + "sha256": "330b670fa75dfc33bd0013a4af3293fed415c29ef4f1df8df2f3295642e3a23c" + }, + { + "path": "jitmind/code_memory/work_storage.py", + "sha256": "f0a2775db9046f8b01007c946a586e9a4bd1ab3763fff5fef87df0d5555b8362" + }, + { + "path": "jitmind/code_memory/lesson_models.py", + "sha256": "447721bf5d7c7b972a4d3b1bda171c674a107d3aba50c90fa0033403f4c5b787" + }, + { + "path": "jitmind/code_memory/preflight.py", + "sha256": "7119d160107db1f0828fa31affc3aba18bcd716163df562a8c77c45cfebc6258" + } + ], + "assertions": [ + "Fact durable and lesson delivered while primary outbox lag remains visible; NOOP delivered twice ahead of original add leaves watermark 0.", + "Real source move makes prior code freshness nonfresh and binding unknown; new build/revalidation produces higher generation and moved verified binding.", + "Lesson version 2 replay is idempotent; version 1 rejected; fact metadata redelivery rejected.", + "Deletion metadata and event followed by old add cannot resurrect fact/binding/lesson; pending add schedule explicitly delivers delete before still-pending add.", + "Primary watermark reaches delete revision, pending count zero, current code generation remains correct." + ], + "evidence_limits": [ + "J04 raw code index consumes captured source, not fact bodies. MEMORY_ONLY_SENTINEL_83f91c is deliberately absent from source.", + "Raw authorized source remains readable after memory forget; forgetting memory never promises deletion of user source files.", + "J02 primary administrative/include_inactive history and backups may retain bodies. Assertions concern ordinary derived retrieval, receipt reconstruction, and content-free binding/work/delivery histories; no physical erasure claim.", + "Source generation, binding observation and outbox revision are separate; no atomic transaction across checkout and three databases is claimed.", + "Uses supplied J10 snapshot. Owner modules may advance; final supervisor must assemble and retest, configuring newer authority adapters if required. No automatic listener or raw-code outbox consumer is invented." + ] + }, + { + "node_id": "tests/test_acceptance_edges.py::test_real_parser_binding_projection_redelivery_and_primary_forget[add_pending]", + "kind": "projection", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Temporary unversioned checkout, actual J04 parser, J02 add/NOOP/delete, J05 binding and file move, J06 projected lesson/preflight/open task. Two schedules: primary projection already populated or original add event pending until after delete.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/scope.py", + "sha256": "2762e46016b2f4e1a6ea6d95208954724f1cfef8e4e59812a19fc06e97bdf34a" + }, + { + "path": "jitmind/code_context/__init__.py", + "sha256": "0bdda619ccabbb7f4894b106572885cf15b5c86232bfd6f333f6ca1b8b75f211" + }, + { + "path": "jitmind/code_context/models.py", + "sha256": "84686d3cdb1f34e6111652956e65b90b01fd19487308a268022a66b14ea44878" + }, + { + "path": "jitmind/code_context/process.py", + "sha256": "ef9baf49a5bbe761fbffa1f60ef172b8f53c587eaffc13c4e179f2700462f77a" + }, + { + "path": "jitmind/code_context/retriever.py", + "sha256": "822dc84804992b8bd9fe7de62e535843585091350f8ff5a2311a05eaf51150f4" + }, + { + "path": "jitmind/code_context/service.py", + "sha256": "16daa9b16b9a55f130ca61204c96d40e8abb279709dbd4c36b81e4c99afbe873" + }, + { + "path": "jitmind/code_context/snapshot.py", + "sha256": "45a35d8a3455cde10816ff3e2feef3a7a21174bbec41326635d94394fec27272" + }, + { + "path": "jitmind/code_memory/anchors.py", + "sha256": "98d9715ad0faba844638859e5f49d8ccb58cd9a7e67c56c7376b81b08c24e31a" + }, + { + "path": "jitmind/code_memory/binding_models.py", + "sha256": "39c9e9676f58314e4e3d9073efd19f0072023440cdb6fc61f9d802fc9a9f203c" + }, + { + "path": "jitmind/code_memory/binding_storage.py", + "sha256": "5684d3bf4269703f87f4232f0d3fd32482d90be704170f57e1cc6670ab539c1f" + }, + { + "path": "jitmind/code_memory/revalidation.py", + "sha256": "ada66aa4f8d553d8930eb37aff00662544d7216bdfae941d643485ca8cdd92d5" + }, + { + "path": "jitmind/code_memory/open_work.py", + "sha256": "330b670fa75dfc33bd0013a4af3293fed415c29ef4f1df8df2f3295642e3a23c" + }, + { + "path": "jitmind/code_memory/work_storage.py", + "sha256": "f0a2775db9046f8b01007c946a586e9a4bd1ab3763fff5fef87df0d5555b8362" + }, + { + "path": "jitmind/code_memory/lesson_models.py", + "sha256": "447721bf5d7c7b972a4d3b1bda171c674a107d3aba50c90fa0033403f4c5b787" + }, + { + "path": "jitmind/code_memory/preflight.py", + "sha256": "7119d160107db1f0828fa31affc3aba18bcd716163df562a8c77c45cfebc6258" + } + ], + "assertions": [ + "Fact durable and lesson delivered while primary outbox lag remains visible; NOOP delivered twice ahead of original add leaves watermark 0.", + "Real source move makes prior code freshness nonfresh and binding unknown; new build/revalidation produces higher generation and moved verified binding.", + "Lesson version 2 replay is idempotent; version 1 rejected; fact metadata redelivery rejected.", + "Deletion metadata and event followed by old add cannot resurrect fact/binding/lesson; pending add schedule explicitly delivers delete before still-pending add.", + "Primary watermark reaches delete revision, pending count zero, current code generation remains correct." + ], + "evidence_limits": [ + "J04 raw code index consumes captured source, not fact bodies. MEMORY_ONLY_SENTINEL_83f91c is deliberately absent from source.", + "Raw authorized source remains readable after memory forget; forgetting memory never promises deletion of user source files.", + "J02 primary administrative/include_inactive history and backups may retain bodies. Assertions concern ordinary derived retrieval, receipt reconstruction, and content-free binding/work/delivery histories; no physical erasure claim.", + "Source generation, binding observation and outbox revision are separate; no atomic transaction across checkout and three databases is claimed.", + "Uses supplied J10 snapshot. Owner modules may advance; final supervisor must assemble and retest, configuring newer authority adapters if required. No automatic listener or raw-code outbox consumer is invented." + ] + } + ], + "additional_mapping_required": false + }, + { + "stage_id": "J-05", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_code_anchors.py::test_real_j02_projection_redelivery_and_terminal_tombstone", + "kind": "projection", + "source": { + "path": "tests/test_code_anchors.py", + "sha256": "8255edab92b341ef41dd5556a68f3f2be8e52b0e940e7e9e98891f2f5cced3cb" + }, + "fixtures": [ + { + "path": "tests/test_code_anchors.py", + "sha256": "8255edab92b341ef41dd5556a68f3f2be8e52b0e940e7e9e98891f2f5cced3cb" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J30", + "ticket": "J-07", + "scenario": "Checkpoint identity collision", + "required_assertion": "Distinct identities cannot overwrite/delete each other; verify payload identity; ambiguous legacy mapping flagged", + "required_in_tickets": [ + "J-07" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-07", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_checkpoint_manager.py::test_legacy_identity_collision_and_migration", + "kind": "real_storage", + "source": { + "path": "tests/test_checkpoint_manager.py", + "sha256": "a85fd91122e6dbde9ddf7b7e5422af622d828192540ef3241d87ef51923f9b65" + }, + "fixtures": [ + { + "path": "tests/test_checkpoint_manager.py", + "sha256": "a85fd91122e6dbde9ddf7b7e5422af622d828192540ef3241d87ef51923f9b65" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_checkpoint_manager.py::test_requested_identity_verified_even_in_v2_path", + "kind": "real_storage", + "source": { + "path": "tests/test_checkpoint_manager.py", + "sha256": "a85fd91122e6dbde9ddf7b7e5422af622d828192540ef3241d87ef51923f9b65" + }, + "fixtures": [ + { + "path": "tests/test_checkpoint_manager.py", + "sha256": "a85fd91122e6dbde9ddf7b7e5422af622d828192540ef3241d87ef51923f9b65" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J31", + "ticket": "J-06", + "scenario": "Forget and derived retention", + "required_assertion": "Current retrieval excludes forgotten content; obligation remains; retained metadata does not leak body", + "required_in_tickets": [ + "J-02", + "J-04", + "J-05", + "J-06" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-02", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_durable_storage.py::test_projection_duplicate_out_of_order_and_forget_filter", + "kind": "projection", + "source": { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + }, + "fixtures": [ + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + }, + { + "stage_id": "J-04", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_acceptance_edges.py::test_real_parser_binding_projection_redelivery_and_primary_forget[projected]", + "kind": "projection", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Same two actual composed parser chains as J29; memory-only sentinel first positively delivered from bound lesson and memory, then primary forget with deletion projection delayed.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/scope.py", + "sha256": "2762e46016b2f4e1a6ea6d95208954724f1cfef8e4e59812a19fc06e97bdf34a" + }, + { + "path": "jitmind/code_context/__init__.py", + "sha256": "0bdda619ccabbb7f4894b106572885cf15b5c86232bfd6f333f6ca1b8b75f211" + }, + { + "path": "jitmind/code_context/models.py", + "sha256": "84686d3cdb1f34e6111652956e65b90b01fd19487308a268022a66b14ea44878" + }, + { + "path": "jitmind/code_context/process.py", + "sha256": "ef9baf49a5bbe761fbffa1f60ef172b8f53c587eaffc13c4e179f2700462f77a" + }, + { + "path": "jitmind/code_context/retriever.py", + "sha256": "822dc84804992b8bd9fe7de62e535843585091350f8ff5a2311a05eaf51150f4" + }, + { + "path": "jitmind/code_context/service.py", + "sha256": "16daa9b16b9a55f130ca61204c96d40e8abb279709dbd4c36b81e4c99afbe873" + }, + { + "path": "jitmind/code_context/snapshot.py", + "sha256": "45a35d8a3455cde10816ff3e2feef3a7a21174bbec41326635d94394fec27272" + }, + { + "path": "jitmind/code_memory/anchors.py", + "sha256": "98d9715ad0faba844638859e5f49d8ccb58cd9a7e67c56c7376b81b08c24e31a" + }, + { + "path": "jitmind/code_memory/binding_models.py", + "sha256": "39c9e9676f58314e4e3d9073efd19f0072023440cdb6fc61f9d802fc9a9f203c" + }, + { + "path": "jitmind/code_memory/binding_storage.py", + "sha256": "5684d3bf4269703f87f4232f0d3fd32482d90be704170f57e1cc6670ab539c1f" + }, + { + "path": "jitmind/code_memory/revalidation.py", + "sha256": "ada66aa4f8d553d8930eb37aff00662544d7216bdfae941d643485ca8cdd92d5" + }, + { + "path": "jitmind/code_memory/open_work.py", + "sha256": "330b670fa75dfc33bd0013a4af3293fed415c29ef4f1df8df2f3295642e3a23c" + }, + { + "path": "jitmind/code_memory/work_storage.py", + "sha256": "f0a2775db9046f8b01007c946a586e9a4bd1ab3763fff5fef87df0d5555b8362" + }, + { + "path": "jitmind/code_memory/lesson_models.py", + "sha256": "447721bf5d7c7b972a4d3b1bda171c674a107d3aba50c90fa0033403f4c5b787" + }, + { + "path": "jitmind/code_memory/preflight.py", + "sha256": "7119d160107db1f0828fa31affc3aba18bcd716163df562a8c77c45cfebc6258" + } + ], + "assertions": [ + "After primary forget, ordinary fact/page/adapters/projected entries/receipt reconstruction exclude sentinel before any delete projection.", + "Both saved preflight receipts return empty payload; candidates empty; bound projection refused; deletion metadata then old events cannot revive content.", + "Purged lesson table empty; binding history, work history/receipts, delivery receipts and tombstones contain no sentinel.", + "Task remains open revision 1 with repo fallback. Raw authorized source remains exact and readable with original SHA-256, current generation and no memory sentinel." + ], + "evidence_limits": [ + "J04 raw code index consumes captured source, not fact bodies. MEMORY_ONLY_SENTINEL_83f91c is deliberately absent from source.", + "Raw authorized source remains readable after memory forget; forgetting memory never promises deletion of user source files.", + "J02 primary administrative/include_inactive history and backups may retain bodies. Assertions concern ordinary derived retrieval, receipt reconstruction, and content-free binding/work/delivery histories; no physical erasure claim.", + "Source generation, binding observation and outbox revision are separate; no atomic transaction across checkout and three databases is claimed.", + "Uses supplied J10 snapshot. Owner modules may advance; final supervisor must assemble and retest, configuring newer authority adapters if required. No automatic listener or raw-code outbox consumer is invented." + ] + }, + { + "node_id": "tests/test_acceptance_edges.py::test_real_parser_binding_projection_redelivery_and_primary_forget[add_pending]", + "kind": "projection", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Same two actual composed parser chains as J29; memory-only sentinel first positively delivered from bound lesson and memory, then primary forget with deletion projection delayed.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/scope.py", + "sha256": "2762e46016b2f4e1a6ea6d95208954724f1cfef8e4e59812a19fc06e97bdf34a" + }, + { + "path": "jitmind/code_context/__init__.py", + "sha256": "0bdda619ccabbb7f4894b106572885cf15b5c86232bfd6f333f6ca1b8b75f211" + }, + { + "path": "jitmind/code_context/models.py", + "sha256": "84686d3cdb1f34e6111652956e65b90b01fd19487308a268022a66b14ea44878" + }, + { + "path": "jitmind/code_context/process.py", + "sha256": "ef9baf49a5bbe761fbffa1f60ef172b8f53c587eaffc13c4e179f2700462f77a" + }, + { + "path": "jitmind/code_context/retriever.py", + "sha256": "822dc84804992b8bd9fe7de62e535843585091350f8ff5a2311a05eaf51150f4" + }, + { + "path": "jitmind/code_context/service.py", + "sha256": "16daa9b16b9a55f130ca61204c96d40e8abb279709dbd4c36b81e4c99afbe873" + }, + { + "path": "jitmind/code_context/snapshot.py", + "sha256": "45a35d8a3455cde10816ff3e2feef3a7a21174bbec41326635d94394fec27272" + }, + { + "path": "jitmind/code_memory/anchors.py", + "sha256": "98d9715ad0faba844638859e5f49d8ccb58cd9a7e67c56c7376b81b08c24e31a" + }, + { + "path": "jitmind/code_memory/binding_models.py", + "sha256": "39c9e9676f58314e4e3d9073efd19f0072023440cdb6fc61f9d802fc9a9f203c" + }, + { + "path": "jitmind/code_memory/binding_storage.py", + "sha256": "5684d3bf4269703f87f4232f0d3fd32482d90be704170f57e1cc6670ab539c1f" + }, + { + "path": "jitmind/code_memory/revalidation.py", + "sha256": "ada66aa4f8d553d8930eb37aff00662544d7216bdfae941d643485ca8cdd92d5" + }, + { + "path": "jitmind/code_memory/open_work.py", + "sha256": "330b670fa75dfc33bd0013a4af3293fed415c29ef4f1df8df2f3295642e3a23c" + }, + { + "path": "jitmind/code_memory/work_storage.py", + "sha256": "f0a2775db9046f8b01007c946a586e9a4bd1ab3763fff5fef87df0d5555b8362" + }, + { + "path": "jitmind/code_memory/lesson_models.py", + "sha256": "447721bf5d7c7b972a4d3b1bda171c674a107d3aba50c90fa0033403f4c5b787" + }, + { + "path": "jitmind/code_memory/preflight.py", + "sha256": "7119d160107db1f0828fa31affc3aba18bcd716163df562a8c77c45cfebc6258" + } + ], + "assertions": [ + "After primary forget, ordinary fact/page/adapters/projected entries/receipt reconstruction exclude sentinel before any delete projection.", + "Both saved preflight receipts return empty payload; candidates empty; bound projection refused; deletion metadata then old events cannot revive content.", + "Purged lesson table empty; binding history, work history/receipts, delivery receipts and tombstones contain no sentinel.", + "Task remains open revision 1 with repo fallback. Raw authorized source remains exact and readable with original SHA-256, current generation and no memory sentinel." + ], + "evidence_limits": [ + "J04 raw code index consumes captured source, not fact bodies. MEMORY_ONLY_SENTINEL_83f91c is deliberately absent from source.", + "Raw authorized source remains readable after memory forget; forgetting memory never promises deletion of user source files.", + "J02 primary administrative/include_inactive history and backups may retain bodies. Assertions concern ordinary derived retrieval, receipt reconstruction, and content-free binding/work/delivery histories; no physical erasure claim.", + "Source generation, binding observation and outbox revision are separate; no atomic transaction across checkout and three databases is claimed.", + "Uses supplied J10 snapshot. Owner modules may advance; final supervisor must assemble and retest, configuring newer authority adapters if required. No automatic listener or raw-code outbox consumer is invented." + ] + } + ], + "additional_mapping_required": false + }, + { + "stage_id": "J-05", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_code_anchors.py::test_deleted_authority_with_no_projection_cannot_return_verified", + "kind": "real_parser", + "source": { + "path": "tests/test_code_anchors.py", + "sha256": "8255edab92b341ef41dd5556a68f3f2be8e52b0e940e7e9e98891f2f5cced3cb" + }, + "fixtures": [ + { + "path": "tests/test_code_anchors.py", + "sha256": "8255edab92b341ef41dd5556a68f3f2be8e52b0e940e7e9e98891f2f5cced3cb" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + }, + { + "stage_id": "J-06", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_preflight.py::test_primary_forget_hides_delayed_projection_replay_and_keeps_work", + "kind": "public_api", + "source": { + "path": "tests/test_preflight.py", + "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + }, + "fixtures": [ + { + "path": "tests/test_preflight.py", + "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + }, + { + "case_id": "J32", + "ticket": "J-08", + "scenario": "Standalone install qualification", + "required_assertion": "Core works independently; absent optional adapter gives capability error not failed import or remote fallback", + "required_in_tickets": [ + "J-08" + ], + "status": "not_run", + "stages": [ + { + "stage_id": "J-08", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_standalone_install.py::installed_smoke", + "kind": "installed_package", + "source": { + "path": "tests/test_standalone_install.py", + "sha256": "1617be508bd800a323058a8f5975bd54ca3ba6bccd9ca6a7df631586f0b75004" + }, + "fixtures": [ + { + "path": "tests/test_standalone_install.py", + "sha256": "1617be508bd800a323058a8f5975bd54ca3ba6bccd9ca6a7df631586f0b75004" + } + ], + "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + } + ] + } + ] + } + ], + "derived_map_sha256": "752b9ed4b8b2571865a0369699bf0ea069f09f3b638f257c79ac498d97b8f5ba", + "mapping_notice": "Final owner-source mapping retains 32 cases and 41 required stages, original handoff/oracle digests, and every prior node. J10 supplies the eight previously incomplete stages. All statuses remain not_run; staged execution is separate from qualification. J10 evidence kinds are preserved exactly and currently block the unchanged runner schema; see final-map-review.md.", + "temporal_oracle": { + "source_sha256": "3a2bb77dab2790f10ad091d048987ab41064699b5bc4c05820d4b4aa83fe231e", + "year": 2026, + "timezone": "UTC", + "interval": "half-open", + "answers": [ + [ + "Jan20", + "Jan20", + 3 + ], + [ + "Jan20", + "Feb15", + 3 + ], + [ + "Jan20", + "Mar1", + 4 + ], + [ + "Jan10", + "Mar2", + 3 + ], + [ + "Jan15", + "Mar2", + 4 + ], + [ + "Feb1", + "Mar2", + 5 + ], + [ + "Feb10", + "Jan20", + 3 + ] + ], + "latest_Jan20": 4, + "conflicts": "error; never insertion order", + "legacy_naive_api": "unchanged" + } +} diff --git a/docs/engineering/acceptance-supplement.json b/docs/engineering/acceptance-supplement.json new file mode 100644 index 0000000..6c1cc44 --- /dev/null +++ b/docs/engineering/acceptance-supplement.json @@ -0,0 +1,2343 @@ +{ + "schema": "jitmind.acceptance-supplement/v1", + "target": "JITMIND", + "status": "not_run", + "notice": "J10 exact-node supplement adapted in J08 to final owner APIs. All statuses remain not_run. Inputs and all_copied_dependencies retain historical J10 provenance; executable node source, fixture and composed-module hashes attest the final staged owner files. See acceptance-edge-notes.md and final-map-review.md.", + "inputs": [ + { + "path": "handoff/acceptance-map.json", + "sha256": "752b9ed4b8b2571865a0369699bf0ea069f09f3b638f257c79ac498d97b8f5ba" + }, + { + "path": "handoff/temporal-oracle.md", + "sha256": "3a2bb77dab2790f10ad091d048987ab41064699b5bc4c05820d4b4aa83fe231e" + }, + { + "path": "worktrees/J08/docs/engineering/acceptance-map.json", + "sha256": "099be53bdf862e4c4ecafc850f218d3db59f7a2a8b1237cc901993ba932fae9a" + }, + { + "path": "reports/J10-dependency-snapshot.json", + "sha256": "ad6e3927b1926f2bafc08c108e92cad54d98447096695b05fdba1aaf74d8cd58" + } + ], + "cases": [ + { + "case_id": "J02", + "status": "not_run", + "stages": [ + { + "stage_id": "J-01", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[advanced]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Five real legacy store classes in temporary directories; successful initial append, ENOSPC from os.replace after temporary bytes are fsynced, then successful append after fault removal.", + "modules_composed": [ + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/memory.py", + "sha256": "68e5803e6523b41f09fb710656ddfb9c0f2a61bb9ba9335a8fa684173e59a7e9" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + }, + { + "path": "jitmind/schemas/ttl_memory.py", + "sha256": "ff48ac01b5a5a1bacd41d671f48e7cee07a703dcf5b3017eb8b8ca14405e29ca" + }, + { + "path": "jitmind/schemas/ttl_page.py", + "sha256": "2889b4ec309cda92c8eeda1ec624f8a074ae00d791e9d5e7fd11a6e16d9816ca" + }, + { + "path": "jitmind/utils/atomic_io.py", + "sha256": "aa58bbae5ca9f686ad020f7ebe74a27c082400964aebad3614fe46cd4466202d" + }, + { + "path": "jitmind/utils/file_lock.py", + "sha256": "4498fbe42d1a9b8f7224f17d684a8a35fb15dbb815b49de83d1246be5ed6e398" + } + ], + "assertions": [ + "Typed PersistenceError reaches public add caller with ENOSPC cause and outcome_uncertain=False.", + "Previous authoritative bytes unchanged; same-instance and fresh reader contain only prior content; temporary file removed.", + "Positive writes before and after fault prove usable fixture." + ], + "evidence_limits": [ + "Injects only errno.ENOSPC at the actual pre-replacement boundary; does not fill disk or assert post-replacement failure semantics.", + "Covers the five public store add surfaces, not every MemoryAgent/provider path or every filesystem syscall." + ] + }, + { + "node_id": "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[memory]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Five real legacy store classes in temporary directories; successful initial append, ENOSPC from os.replace after temporary bytes are fsynced, then successful append after fault removal.", + "modules_composed": [ + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/memory.py", + "sha256": "68e5803e6523b41f09fb710656ddfb9c0f2a61bb9ba9335a8fa684173e59a7e9" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + }, + { + "path": "jitmind/schemas/ttl_memory.py", + "sha256": "ff48ac01b5a5a1bacd41d671f48e7cee07a703dcf5b3017eb8b8ca14405e29ca" + }, + { + "path": "jitmind/schemas/ttl_page.py", + "sha256": "2889b4ec309cda92c8eeda1ec624f8a074ae00d791e9d5e7fd11a6e16d9816ca" + }, + { + "path": "jitmind/utils/atomic_io.py", + "sha256": "aa58bbae5ca9f686ad020f7ebe74a27c082400964aebad3614fe46cd4466202d" + }, + { + "path": "jitmind/utils/file_lock.py", + "sha256": "4498fbe42d1a9b8f7224f17d684a8a35fb15dbb815b49de83d1246be5ed6e398" + } + ], + "assertions": [ + "Typed PersistenceError reaches public add caller with ENOSPC cause and outcome_uncertain=False.", + "Previous authoritative bytes unchanged; same-instance and fresh reader contain only prior content; temporary file removed.", + "Positive writes before and after fault prove usable fixture." + ], + "evidence_limits": [ + "Injects only errno.ENOSPC at the actual pre-replacement boundary; does not fill disk or assert post-replacement failure semantics.", + "Covers the five public store add surfaces, not every MemoryAgent/provider path or every filesystem syscall." + ] + }, + { + "node_id": "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[ttl_memory]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Five real legacy store classes in temporary directories; successful initial append, ENOSPC from os.replace after temporary bytes are fsynced, then successful append after fault removal.", + "modules_composed": [ + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/memory.py", + "sha256": "68e5803e6523b41f09fb710656ddfb9c0f2a61bb9ba9335a8fa684173e59a7e9" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + }, + { + "path": "jitmind/schemas/ttl_memory.py", + "sha256": "ff48ac01b5a5a1bacd41d671f48e7cee07a703dcf5b3017eb8b8ca14405e29ca" + }, + { + "path": "jitmind/schemas/ttl_page.py", + "sha256": "2889b4ec309cda92c8eeda1ec624f8a074ae00d791e9d5e7fd11a6e16d9816ca" + }, + { + "path": "jitmind/utils/atomic_io.py", + "sha256": "aa58bbae5ca9f686ad020f7ebe74a27c082400964aebad3614fe46cd4466202d" + }, + { + "path": "jitmind/utils/file_lock.py", + "sha256": "4498fbe42d1a9b8f7224f17d684a8a35fb15dbb815b49de83d1246be5ed6e398" + } + ], + "assertions": [ + "Typed PersistenceError reaches public add caller with ENOSPC cause and outcome_uncertain=False.", + "Previous authoritative bytes unchanged; same-instance and fresh reader contain only prior content; temporary file removed.", + "Positive writes before and after fault prove usable fixture." + ], + "evidence_limits": [ + "Injects only errno.ENOSPC at the actual pre-replacement boundary; does not fill disk or assert post-replacement failure semantics.", + "Covers the five public store add surfaces, not every MemoryAgent/provider path or every filesystem syscall." + ] + }, + { + "node_id": "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[pages]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Five real legacy store classes in temporary directories; successful initial append, ENOSPC from os.replace after temporary bytes are fsynced, then successful append after fault removal.", + "modules_composed": [ + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/memory.py", + "sha256": "68e5803e6523b41f09fb710656ddfb9c0f2a61bb9ba9335a8fa684173e59a7e9" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + }, + { + "path": "jitmind/schemas/ttl_memory.py", + "sha256": "ff48ac01b5a5a1bacd41d671f48e7cee07a703dcf5b3017eb8b8ca14405e29ca" + }, + { + "path": "jitmind/schemas/ttl_page.py", + "sha256": "2889b4ec309cda92c8eeda1ec624f8a074ae00d791e9d5e7fd11a6e16d9816ca" + }, + { + "path": "jitmind/utils/atomic_io.py", + "sha256": "aa58bbae5ca9f686ad020f7ebe74a27c082400964aebad3614fe46cd4466202d" + }, + { + "path": "jitmind/utils/file_lock.py", + "sha256": "4498fbe42d1a9b8f7224f17d684a8a35fb15dbb815b49de83d1246be5ed6e398" + } + ], + "assertions": [ + "Typed PersistenceError reaches public add caller with ENOSPC cause and outcome_uncertain=False.", + "Previous authoritative bytes unchanged; same-instance and fresh reader contain only prior content; temporary file removed.", + "Positive writes before and after fault prove usable fixture." + ], + "evidence_limits": [ + "Injects only errno.ENOSPC at the actual pre-replacement boundary; does not fill disk or assert post-replacement failure semantics.", + "Covers the five public store add surfaces, not every MemoryAgent/provider path or every filesystem syscall." + ] + }, + { + "node_id": "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[ttl_pages]", + "kind": "injected_storage_fault", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Five real legacy store classes in temporary directories; successful initial append, ENOSPC from os.replace after temporary bytes are fsynced, then successful append after fault removal.", + "modules_composed": [ + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/memory.py", + "sha256": "68e5803e6523b41f09fb710656ddfb9c0f2a61bb9ba9335a8fa684173e59a7e9" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + }, + { + "path": "jitmind/schemas/ttl_memory.py", + "sha256": "ff48ac01b5a5a1bacd41d671f48e7cee07a703dcf5b3017eb8b8ca14405e29ca" + }, + { + "path": "jitmind/schemas/ttl_page.py", + "sha256": "2889b4ec309cda92c8eeda1ec624f8a074ae00d791e9d5e7fd11a6e16d9816ca" + }, + { + "path": "jitmind/utils/atomic_io.py", + "sha256": "aa58bbae5ca9f686ad020f7ebe74a27c082400964aebad3614fe46cd4466202d" + }, + { + "path": "jitmind/utils/file_lock.py", + "sha256": "4498fbe42d1a9b8f7224f17d684a8a35fb15dbb815b49de83d1246be5ed6e398" + } + ], + "assertions": [ + "Typed PersistenceError reaches public add caller with ENOSPC cause and outcome_uncertain=False.", + "Previous authoritative bytes unchanged; same-instance and fresh reader contain only prior content; temporary file removed.", + "Positive writes before and after fault prove usable fixture." + ], + "evidence_limits": [ + "Injects only errno.ENOSPC at the actual pre-replacement boundary; does not fill disk or assert post-replacement failure semantics.", + "Covers the five public store add surfaces, not every MemoryAgent/provider path or every filesystem syscall." + ] + } + ] + }, + { + "stage_id": "J-02", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_acceptance_edges.py::test_real_sqlite_full_rolls_back_every_effect_then_accepts_same_request", + "kind": "real_storage", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Real temporary SQLite DB; each ingest connection capped to current page_count; 100000-character allowed input triggers native SQLITE_FULL, then cap removed for same-key successful commit.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + } + ], + "assertions": [ + "Observes native sqlite_errorcode == SQLITE_FULL before product error translation; public StorageFailure, no acknowledgement.", + "Fresh reader sees zero revision/facts/pages/operations/outbox; no receipt; raw tables including namespace and projection remain empty; integrity_check=ok.", + "After removing cap, same request commits fact/page/receipt/event; replay is idempotent and event delivery returns the fact." + ], + "evidence_limits": [ + "Connection wrapper configures a real PRAGMA, not a mocked SQLite exception; host disk is not exhausted.", + "Empty temporary database only; no production filesystem or WAL qualification." + ] + } + ] + } + ], + "scenario": "Disk-full write failure", + "required_assertion": "Durability failure reaches caller; no committed acknowledgement" + }, + { + "case_id": "J04", + "status": "not_run", + "stages": [ + { + "stage_id": "J-02", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[before_transaction-False]", + "kind": "real_storage", + "status": "not_run", + "source": { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + }, + "fixtures": [ + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Existing J02 spawned child calls os._exit(37) at before_transaction, after_page_insert, after_fact_insert, after_outbox_receipt, or after_commit; fresh SQLite process view and retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + } + ], + "assertions": [ + "Child exits at requested boundary; reopened page/fact/receipt counts are all zero before commit or all one after commit.", + "Retry yields revision 1 and one page; child has bounded join, terminate and kill teardown." + ], + "evidence_limits": [ + "Process exit is real; kill point selected by trusted fault hook. Does not emulate machine power loss.", + "Existing node asserts pair counts and idempotent recovery; no claim of a separately asserted byte-for-byte provenance comparison." + ] + }, + { + "node_id": "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[after_page_insert-False]", + "kind": "real_storage", + "status": "not_run", + "source": { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + }, + "fixtures": [ + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Existing J02 spawned child calls os._exit(37) at before_transaction, after_page_insert, after_fact_insert, after_outbox_receipt, or after_commit; fresh SQLite process view and retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + } + ], + "assertions": [ + "Child exits at requested boundary; reopened page/fact/receipt counts are all zero before commit or all one after commit.", + "Retry yields revision 1 and one page; child has bounded join, terminate and kill teardown." + ], + "evidence_limits": [ + "Process exit is real; kill point selected by trusted fault hook. Does not emulate machine power loss.", + "Existing node asserts pair counts and idempotent recovery; no claim of a separately asserted byte-for-byte provenance comparison." + ] + }, + { + "node_id": "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[after_fact_insert-False]", + "kind": "real_storage", + "status": "not_run", + "source": { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + }, + "fixtures": [ + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Existing J02 spawned child calls os._exit(37) at before_transaction, after_page_insert, after_fact_insert, after_outbox_receipt, or after_commit; fresh SQLite process view and retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + } + ], + "assertions": [ + "Child exits at requested boundary; reopened page/fact/receipt counts are all zero before commit or all one after commit.", + "Retry yields revision 1 and one page; child has bounded join, terminate and kill teardown." + ], + "evidence_limits": [ + "Process exit is real; kill point selected by trusted fault hook. Does not emulate machine power loss.", + "Existing node asserts pair counts and idempotent recovery; no claim of a separately asserted byte-for-byte provenance comparison." + ] + }, + { + "node_id": "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[after_outbox_receipt-False]", + "kind": "real_storage", + "status": "not_run", + "source": { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + }, + "fixtures": [ + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Existing J02 spawned child calls os._exit(37) at before_transaction, after_page_insert, after_fact_insert, after_outbox_receipt, or after_commit; fresh SQLite process view and retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + } + ], + "assertions": [ + "Child exits at requested boundary; reopened page/fact/receipt counts are all zero before commit or all one after commit.", + "Retry yields revision 1 and one page; child has bounded join, terminate and kill teardown." + ], + "evidence_limits": [ + "Process exit is real; kill point selected by trusted fault hook. Does not emulate machine power loss.", + "Existing node asserts pair counts and idempotent recovery; no claim of a separately asserted byte-for-byte provenance comparison." + ] + }, + { + "node_id": "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[after_commit-True]", + "kind": "real_storage", + "status": "not_run", + "source": { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + }, + "fixtures": [ + { + "path": "tests/test_durable_storage.py", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00" + } + ], + "fixture_description": "Existing J02 spawned child calls os._exit(37) at before_transaction, after_page_insert, after_fact_insert, after_outbox_receipt, or after_commit; fresh SQLite process view and retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + } + ], + "assertions": [ + "Child exits at requested boundary; reopened page/fact/receipt counts are all zero before commit or all one after commit.", + "Retry yields revision 1 and one page; child has bounded join, terminate and kill teardown." + ], + "evidence_limits": [ + "Process exit is real; kill point selected by trusted fault hook. Does not emulate machine power loss.", + "Existing node asserts pair counts and idempotent recovery; no claim of a separately asserted byte-for-byte provenance comparison." + ] + } + ] + } + ], + "scenario": "Memory/page interrupted write", + "required_assertion": "Recovery yields a consistent memory/provenance pair" + }, + { + "case_id": "J16", + "status": "not_run", + "stages": [ + { + "stage_id": "J-06", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_open_work_bindings.py::test_j16_j31_real_binding_move_disappearance_forget_keep_obligation[# code removed\\n-orphaned_confirmed]", + "kind": "real_parser", + "status": "not_run", + "source": { + "path": "tests/test_open_work_bindings.py", + "sha256": "645628f66ceddab3ebc92c5260f3289aa4c7bea19a165c135d337417e9857f59" + }, + "fixtures": [ + { + "path": "tests/test_open_work_bindings.py", + "sha256": "645628f66ceddab3ebc92c5260f3289aa4c7bea19a165c135d337417e9857f59" + } + ], + "fixture_description": "Reviewed existing J06 test: temporary Git checkout parsed by actual J04 Node/tree-sitter, J02 fact, J05 logical binding, J06 obligation; file move then confirmed removal or malformed-source uncertainty.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/scope.py", + "sha256": "2762e46016b2f4e1a6ea6d95208954724f1cfef8e4e59812a19fc06e97bdf34a" + }, + { + "path": "jitmind/code_context/__init__.py", + "sha256": "0bdda619ccabbb7f4894b106572885cf15b5c86232bfd6f333f6ca1b8b75f211" + }, + { + "path": "jitmind/code_context/models.py", + "sha256": "84686d3cdb1f34e6111652956e65b90b01fd19487308a268022a66b14ea44878" + }, + { + "path": "jitmind/code_context/process.py", + "sha256": "ef9baf49a5bbe761fbffa1f60ef172b8f53c587eaffc13c4e179f2700462f77a" + }, + { + "path": "jitmind/code_context/retriever.py", + "sha256": "822dc84804992b8bd9fe7de62e535843585091350f8ff5a2311a05eaf51150f4" + }, + { + "path": "jitmind/code_context/service.py", + "sha256": "16daa9b16b9a55f130ca61204c96d40e8abb279709dbd4c36b81e4c99afbe873" + }, + { + "path": "jitmind/code_context/snapshot.py", + "sha256": "45a35d8a3455cde10816ff3e2feef3a7a21174bbec41326635d94394fec27272" + }, + { + "path": "jitmind/code_memory/anchors.py", + "sha256": "98d9715ad0faba844638859e5f49d8ccb58cd9a7e67c56c7376b81b08c24e31a" + }, + { + "path": "jitmind/code_memory/binding_models.py", + "sha256": "39c9e9676f58314e4e3d9073efd19f0072023440cdb6fc61f9d802fc9a9f203c" + }, + { + "path": "jitmind/code_memory/binding_storage.py", + "sha256": "5684d3bf4269703f87f4232f0d3fd32482d90be704170f57e1cc6670ab539c1f" + }, + { + "path": "jitmind/code_memory/revalidation.py", + "sha256": "ada66aa4f8d553d8930eb37aff00662544d7216bdfae941d643485ca8cdd92d5" + }, + { + "path": "jitmind/code_memory/open_work.py", + "sha256": "330b670fa75dfc33bd0013a4af3293fed415c29ef4f1df8df2f3295642e3a23c" + }, + { + "path": "jitmind/code_memory/work_storage.py", + "sha256": "f0a2775db9046f8b01007c946a586e9a4bd1ab3763fff5fef87df0d5555b8362" + }, + { + "path": "jitmind/code_memory/lesson_models.py", + "sha256": "447721bf5d7c7b972a4d3b1bda171c674a107d3aba50c90fa0033403f4c5b787" + }, + { + "path": "jitmind/code_memory/preflight.py", + "sha256": "7119d160107db1f0828fa31affc3aba18bcd716163df562a8c77c45cfebc6258" + } + ], + "assertions": [ + "Binding starts at source.py, follows real move to moved.py, then becomes orphaned_confirmed or unknown.", + "OpenWorkService.binding_locations falls back to exact authorized repo; obligation stays open at revision 1 through primary forget.", + "Real lesson projection/preflight and binding history run in same chain." + ], + "evidence_limits": [ + "Only the two exact collected parameters are reused; current tests and modules are the attested J10 snapshot.", + "Broader repository scope is a location fallback, not task completion or proof of code deletion in malformed input." + ] + }, + { + "node_id": "tests/test_open_work_bindings.py::test_j16_j31_real_binding_move_disappearance_forget_keep_obligation[invalid syntax ???\\n-unknown]", + "kind": "real_parser", + "status": "not_run", + "source": { + "path": "tests/test_open_work_bindings.py", + "sha256": "645628f66ceddab3ebc92c5260f3289aa4c7bea19a165c135d337417e9857f59" + }, + "fixtures": [ + { + "path": "tests/test_open_work_bindings.py", + "sha256": "645628f66ceddab3ebc92c5260f3289aa4c7bea19a165c135d337417e9857f59" + } + ], + "fixture_description": "Reviewed existing J06 test: temporary Git checkout parsed by actual J04 Node/tree-sitter, J02 fact, J05 logical binding, J06 obligation; file move then confirmed removal or malformed-source uncertainty.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/scope.py", + "sha256": "2762e46016b2f4e1a6ea6d95208954724f1cfef8e4e59812a19fc06e97bdf34a" + }, + { + "path": "jitmind/code_context/__init__.py", + "sha256": "0bdda619ccabbb7f4894b106572885cf15b5c86232bfd6f333f6ca1b8b75f211" + }, + { + "path": "jitmind/code_context/models.py", + "sha256": "84686d3cdb1f34e6111652956e65b90b01fd19487308a268022a66b14ea44878" + }, + { + "path": "jitmind/code_context/process.py", + "sha256": "ef9baf49a5bbe761fbffa1f60ef172b8f53c587eaffc13c4e179f2700462f77a" + }, + { + "path": "jitmind/code_context/retriever.py", + "sha256": "822dc84804992b8bd9fe7de62e535843585091350f8ff5a2311a05eaf51150f4" + }, + { + "path": "jitmind/code_context/service.py", + "sha256": "16daa9b16b9a55f130ca61204c96d40e8abb279709dbd4c36b81e4c99afbe873" + }, + { + "path": "jitmind/code_context/snapshot.py", + "sha256": "45a35d8a3455cde10816ff3e2feef3a7a21174bbec41326635d94394fec27272" + }, + { + "path": "jitmind/code_memory/anchors.py", + "sha256": "98d9715ad0faba844638859e5f49d8ccb58cd9a7e67c56c7376b81b08c24e31a" + }, + { + "path": "jitmind/code_memory/binding_models.py", + "sha256": "39c9e9676f58314e4e3d9073efd19f0072023440cdb6fc61f9d802fc9a9f203c" + }, + { + "path": "jitmind/code_memory/binding_storage.py", + "sha256": "5684d3bf4269703f87f4232f0d3fd32482d90be704170f57e1cc6670ab539c1f" + }, + { + "path": "jitmind/code_memory/revalidation.py", + "sha256": "ada66aa4f8d553d8930eb37aff00662544d7216bdfae941d643485ca8cdd92d5" + }, + { + "path": "jitmind/code_memory/open_work.py", + "sha256": "330b670fa75dfc33bd0013a4af3293fed415c29ef4f1df8df2f3295642e3a23c" + }, + { + "path": "jitmind/code_memory/work_storage.py", + "sha256": "f0a2775db9046f8b01007c946a586e9a4bd1ab3763fff5fef87df0d5555b8362" + }, + { + "path": "jitmind/code_memory/lesson_models.py", + "sha256": "447721bf5d7c7b972a4d3b1bda171c674a107d3aba50c90fa0033403f4c5b787" + }, + { + "path": "jitmind/code_memory/preflight.py", + "sha256": "7119d160107db1f0828fa31affc3aba18bcd716163df562a8c77c45cfebc6258" + } + ], + "assertions": [ + "Binding starts at source.py, follows real move to moved.py, then becomes orphaned_confirmed or unknown.", + "OpenWorkService.binding_locations falls back to exact authorized repo; obligation stays open at revision 1 through primary forget.", + "Real lesson projection/preflight and binding history run in same chain." + ], + "evidence_limits": [ + "Only the two exact collected parameters are reused; current tests and modules are the attested J10 snapshot.", + "Broader repository scope is a location fallback, not task completion or proof of code deletion in malformed input." + ] + } + ] + } + ], + "scenario": "Unfinished work loses anchor", + "required_assertion": "Obligation remains open and can fall back to broader scope" + }, + { + "case_id": "J22", + "status": "not_run", + "stages": [ + { + "stage_id": "J-07", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_checkpoint_ledger.py::test_tool_boundaries_and_explicit_terminals[tool_result]", + "kind": "real_storage", + "status": "not_run", + "source": { + "path": "tests/test_checkpoint_ledger.py", + "sha256": "a9ff3ffe41f0cba68e0e7b86ee425c69e9ee912c169fa2323dc510c5a40313b8" + }, + "fixtures": [ + { + "path": "tests/test_checkpoint_ledger.py", + "sha256": "a9ff3ffe41f0cba68e0e7b86ee425c69e9ee912c169fa2323dc510c5a40313b8" + } + ], + "fixture_description": "Existing real SQLiteCheckpointLedger stream: tool_start at 0, message at 1, terminal at 2; all three terminal kinds have exact collected parameters.", + "modules_composed": [ + { + "path": "jitmind/scope.py", + "sha256": "2762e46016b2f4e1a6ea6d95208954724f1cfef8e4e59812a19fc06e97bdf34a" + }, + { + "path": "jitmind/checkpoints/__init__.py", + "sha256": "4d54e3f91114b474c337fbd460653e46210c2c668fcb557c231560e8477c0017" + }, + { + "path": "jitmind/checkpoints/ledger.py", + "sha256": "ba500b7dff478277252df4647e4c9ddd48656c1f58667357cf38a2d5639f88e4" + } + ], + "assertions": [ + "Rejects range 0..1 before and after late terminal (end cut), and 1..2 / 2..2 / 1..1 (start cut or wholly inside interaction).", + "Complete 0..2 publishes revision 1; subsequent 3..3 allowed; repeated/unknown terminals rejected." + ], + "evidence_limits": [ + "Both boundary directions are directly asserted by the existing node. No provider transcript or remote checkpoint store." + ] + }, + { + "node_id": "tests/test_checkpoint_ledger.py::test_tool_boundaries_and_explicit_terminals[tool_cancel]", + "kind": "real_storage", + "status": "not_run", + "source": { + "path": "tests/test_checkpoint_ledger.py", + "sha256": "a9ff3ffe41f0cba68e0e7b86ee425c69e9ee912c169fa2323dc510c5a40313b8" + }, + "fixtures": [ + { + "path": "tests/test_checkpoint_ledger.py", + "sha256": "a9ff3ffe41f0cba68e0e7b86ee425c69e9ee912c169fa2323dc510c5a40313b8" + } + ], + "fixture_description": "Existing real SQLiteCheckpointLedger stream: tool_start at 0, message at 1, terminal at 2; all three terminal kinds have exact collected parameters.", + "modules_composed": [ + { + "path": "jitmind/scope.py", + "sha256": "2762e46016b2f4e1a6ea6d95208954724f1cfef8e4e59812a19fc06e97bdf34a" + }, + { + "path": "jitmind/checkpoints/__init__.py", + "sha256": "4d54e3f91114b474c337fbd460653e46210c2c668fcb557c231560e8477c0017" + }, + { + "path": "jitmind/checkpoints/ledger.py", + "sha256": "ba500b7dff478277252df4647e4c9ddd48656c1f58667357cf38a2d5639f88e4" + } + ], + "assertions": [ + "Rejects range 0..1 before and after late terminal (end cut), and 1..2 / 2..2 / 1..1 (start cut or wholly inside interaction).", + "Complete 0..2 publishes revision 1; subsequent 3..3 allowed; repeated/unknown terminals rejected." + ], + "evidence_limits": [ + "Both boundary directions are directly asserted by the existing node. No provider transcript or remote checkpoint store." + ] + }, + { + "node_id": "tests/test_checkpoint_ledger.py::test_tool_boundaries_and_explicit_terminals[tool_timeout]", + "kind": "real_storage", + "status": "not_run", + "source": { + "path": "tests/test_checkpoint_ledger.py", + "sha256": "a9ff3ffe41f0cba68e0e7b86ee425c69e9ee912c169fa2323dc510c5a40313b8" + }, + "fixtures": [ + { + "path": "tests/test_checkpoint_ledger.py", + "sha256": "a9ff3ffe41f0cba68e0e7b86ee425c69e9ee912c169fa2323dc510c5a40313b8" + } + ], + "fixture_description": "Existing real SQLiteCheckpointLedger stream: tool_start at 0, message at 1, terminal at 2; all three terminal kinds have exact collected parameters.", + "modules_composed": [ + { + "path": "jitmind/scope.py", + "sha256": "2762e46016b2f4e1a6ea6d95208954724f1cfef8e4e59812a19fc06e97bdf34a" + }, + { + "path": "jitmind/checkpoints/__init__.py", + "sha256": "4d54e3f91114b474c337fbd460653e46210c2c668fcb557c231560e8477c0017" + }, + { + "path": "jitmind/checkpoints/ledger.py", + "sha256": "ba500b7dff478277252df4647e4c9ddd48656c1f58667357cf38a2d5639f88e4" + } + ], + "assertions": [ + "Rejects range 0..1 before and after late terminal (end cut), and 1..2 / 2..2 / 1..1 (start cut or wholly inside interaction).", + "Complete 0..2 publishes revision 1; subsequent 3..3 allowed; repeated/unknown terminals rejected." + ], + "evidence_limits": [ + "Both boundary directions are directly asserted by the existing node. No provider transcript or remote checkpoint store." + ] + } + ] + } + ], + "scenario": "Checkpoint cuts tool interaction", + "required_assertion": "Unsafe boundary is rejected or postponed" + }, + { + "case_id": "J25", + "status": "not_run", + "stages": [ + { + "stage_id": "J-02", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_durable_migration.py::test_invalid_migration_refuses_without_changes[truncated]", + "kind": "migration", + "status": "not_run", + "source": { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + }, + "fixtures": [ + { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + } + ], + "fixture_description": "Existing truncated/duplicate-key/NaN legacy-source rejection and three exception rollback nodes; new real child exit(73) after import pages or before import commit; source JSON byte snapshots and clean retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/storage/migration.py", + "sha256": "26cf90e0911fe6bfae875ef31c50f0b8cbf94b05c2d5a694cd5408622533a15a" + }, + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + } + ], + "assertions": [ + "Corrupt source raises exact MigrationError without creating a candidate or changing original JSON.", + "Existing three injected exception nodes leave source and candidate empty and permit positive retry.", + "Real child exits roll back namespaces/pages/facts/operations/outbox/aliases/imports; original source bytes unchanged.", + "Restaging and retry preserve fact ID, page provenance and alias; duplicate import keeps revision 1." + ], + "evidence_limits": [ + "Corrupt cases and exception nodes are reused unchanged; real process-exit supplement owns its own small fixture.", + "No concurrent legacy writer or machine-power-loss simulation; staging is explicitly quiesced." + ] + }, + { + "node_id": "tests/test_durable_migration.py::test_invalid_migration_refuses_without_changes[duplicate_json_key]", + "kind": "migration", + "status": "not_run", + "source": { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + }, + "fixtures": [ + { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + } + ], + "fixture_description": "Existing truncated/duplicate-key/NaN legacy-source rejection and three exception rollback nodes; new real child exit(73) after import pages or before import commit; source JSON byte snapshots and clean retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/storage/migration.py", + "sha256": "26cf90e0911fe6bfae875ef31c50f0b8cbf94b05c2d5a694cd5408622533a15a" + }, + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + } + ], + "assertions": [ + "Corrupt source raises exact MigrationError without creating a candidate or changing original JSON.", + "Existing three injected exception nodes leave source and candidate empty and permit positive retry.", + "Real child exits roll back namespaces/pages/facts/operations/outbox/aliases/imports; original source bytes unchanged.", + "Restaging and retry preserve fact ID, page provenance and alias; duplicate import keeps revision 1." + ], + "evidence_limits": [ + "Corrupt cases and exception nodes are reused unchanged; real process-exit supplement owns its own small fixture.", + "No concurrent legacy writer or machine-power-loss simulation; staging is explicitly quiesced." + ] + }, + { + "node_id": "tests/test_durable_migration.py::test_invalid_migration_refuses_without_changes[nan]", + "kind": "migration", + "status": "not_run", + "source": { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + }, + "fixtures": [ + { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + } + ], + "fixture_description": "Existing truncated/duplicate-key/NaN legacy-source rejection and three exception rollback nodes; new real child exit(73) after import pages or before import commit; source JSON byte snapshots and clean retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/storage/migration.py", + "sha256": "26cf90e0911fe6bfae875ef31c50f0b8cbf94b05c2d5a694cd5408622533a15a" + }, + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + } + ], + "assertions": [ + "Corrupt source raises exact MigrationError without creating a candidate or changing original JSON.", + "Existing three injected exception nodes leave source and candidate empty and permit positive retry.", + "Real child exits roll back namespaces/pages/facts/operations/outbox/aliases/imports; original source bytes unchanged.", + "Restaging and retry preserve fact ID, page provenance and alias; duplicate import keeps revision 1." + ], + "evidence_limits": [ + "Corrupt cases and exception nodes are reused unchanged; real process-exit supplement owns its own small fixture.", + "No concurrent legacy writer or machine-power-loss simulation; staging is explicitly quiesced." + ] + }, + { + "node_id": "tests/test_durable_migration.py::test_staged_failure_leaves_legacy_and_candidate_unchanged[before_import]", + "kind": "migration", + "status": "not_run", + "source": { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + }, + "fixtures": [ + { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + } + ], + "fixture_description": "Existing truncated/duplicate-key/NaN legacy-source rejection and three exception rollback nodes; new real child exit(73) after import pages or before import commit; source JSON byte snapshots and clean retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/storage/migration.py", + "sha256": "26cf90e0911fe6bfae875ef31c50f0b8cbf94b05c2d5a694cd5408622533a15a" + }, + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + } + ], + "assertions": [ + "Corrupt source raises exact MigrationError without creating a candidate or changing original JSON.", + "Existing three injected exception nodes leave source and candidate empty and permit positive retry.", + "Real child exits roll back namespaces/pages/facts/operations/outbox/aliases/imports; original source bytes unchanged.", + "Restaging and retry preserve fact ID, page provenance and alias; duplicate import keeps revision 1." + ], + "evidence_limits": [ + "Corrupt cases and exception nodes are reused unchanged; real process-exit supplement owns its own small fixture.", + "No concurrent legacy writer or machine-power-loss simulation; staging is explicitly quiesced." + ] + }, + { + "node_id": "tests/test_durable_migration.py::test_staged_failure_leaves_legacy_and_candidate_unchanged[after_import_pages]", + "kind": "migration", + "status": "not_run", + "source": { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + }, + "fixtures": [ + { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + } + ], + "fixture_description": "Existing truncated/duplicate-key/NaN legacy-source rejection and three exception rollback nodes; new real child exit(73) after import pages or before import commit; source JSON byte snapshots and clean retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/storage/migration.py", + "sha256": "26cf90e0911fe6bfae875ef31c50f0b8cbf94b05c2d5a694cd5408622533a15a" + }, + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + } + ], + "assertions": [ + "Corrupt source raises exact MigrationError without creating a candidate or changing original JSON.", + "Existing three injected exception nodes leave source and candidate empty and permit positive retry.", + "Real child exits roll back namespaces/pages/facts/operations/outbox/aliases/imports; original source bytes unchanged.", + "Restaging and retry preserve fact ID, page provenance and alias; duplicate import keeps revision 1." + ], + "evidence_limits": [ + "Corrupt cases and exception nodes are reused unchanged; real process-exit supplement owns its own small fixture.", + "No concurrent legacy writer or machine-power-loss simulation; staging is explicitly quiesced." + ] + }, + { + "node_id": "tests/test_durable_migration.py::test_staged_failure_leaves_legacy_and_candidate_unchanged[before_import_commit]", + "kind": "migration", + "status": "not_run", + "source": { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + }, + "fixtures": [ + { + "path": "tests/test_durable_migration.py", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60" + } + ], + "fixture_description": "Existing truncated/duplicate-key/NaN legacy-source rejection and three exception rollback nodes; new real child exit(73) after import pages or before import commit; source JSON byte snapshots and clean retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/storage/migration.py", + "sha256": "26cf90e0911fe6bfae875ef31c50f0b8cbf94b05c2d5a694cd5408622533a15a" + }, + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + } + ], + "assertions": [ + "Corrupt source raises exact MigrationError without creating a candidate or changing original JSON.", + "Existing three injected exception nodes leave source and candidate empty and permit positive retry.", + "Real child exits roll back namespaces/pages/facts/operations/outbox/aliases/imports; original source bytes unchanged.", + "Restaging and retry preserve fact ID, page provenance and alias; duplicate import keeps revision 1." + ], + "evidence_limits": [ + "Corrupt cases and exception nodes are reused unchanged; real process-exit supplement owns its own small fixture.", + "No concurrent legacy writer or machine-power-loss simulation; staging is explicitly quiesced." + ] + }, + { + "node_id": "tests/test_acceptance_edges.py::test_real_migration_exit_preserves_source_and_allows_retry[after_import_pages]", + "kind": "migration", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Existing truncated/duplicate-key/NaN legacy-source rejection and three exception rollback nodes; new real child exit(73) after import pages or before import commit; source JSON byte snapshots and clean retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/storage/migration.py", + "sha256": "26cf90e0911fe6bfae875ef31c50f0b8cbf94b05c2d5a694cd5408622533a15a" + }, + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + } + ], + "assertions": [ + "Corrupt source raises exact MigrationError without creating a candidate or changing original JSON.", + "Existing three injected exception nodes leave source and candidate empty and permit positive retry.", + "Real child exits roll back namespaces/pages/facts/operations/outbox/aliases/imports; original source bytes unchanged.", + "Restaging and retry preserve fact ID, page provenance and alias; duplicate import keeps revision 1." + ], + "evidence_limits": [ + "Corrupt cases and exception nodes are reused unchanged; real process-exit supplement owns its own small fixture.", + "No concurrent legacy writer or machine-power-loss simulation; staging is explicitly quiesced." + ] + }, + { + "node_id": "tests/test_acceptance_edges.py::test_real_migration_exit_preserves_source_and_allows_retry[before_import_commit]", + "kind": "migration", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Existing truncated/duplicate-key/NaN legacy-source rejection and three exception rollback nodes; new real child exit(73) after import pages or before import commit; source JSON byte snapshots and clean retry.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/storage/migration.py", + "sha256": "26cf90e0911fe6bfae875ef31c50f0b8cbf94b05c2d5a694cd5408622533a15a" + }, + { + "path": "jitmind/schemas/advanced_memory.py", + "sha256": "b56e5807477630000e1dc7c2166080343a1e5eceecdb643cf9d6240c98512633" + }, + { + "path": "jitmind/schemas/page.py", + "sha256": "4f47392d633fd71f3a7f4b758ce16d5c65e2d1aa82809d410214196632b00d0e" + } + ], + "assertions": [ + "Corrupt source raises exact MigrationError without creating a candidate or changing original JSON.", + "Existing three injected exception nodes leave source and candidate empty and permit positive retry.", + "Real child exits roll back namespaces/pages/facts/operations/outbox/aliases/imports; original source bytes unchanged.", + "Restaging and retry preserve fact ID, page provenance and alias; duplicate import keeps revision 1." + ], + "evidence_limits": [ + "Corrupt cases and exception nodes are reused unchanged; real process-exit supplement owns its own small fixture.", + "No concurrent legacy writer or machine-power-loss simulation; staging is explicitly quiesced." + ] + } + ] + } + ], + "scenario": "Corrupt store and interrupted staging", + "required_assertion": "Corruption is reported without silently manufacturing an empty successful migration; interrupted staged import does not replace authoritative source" + }, + { + "case_id": "J29", + "status": "not_run", + "stages": [ + { + "stage_id": "J-04", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_acceptance_edges.py::test_real_parser_binding_projection_redelivery_and_primary_forget[projected]", + "kind": "projection", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Temporary unversioned checkout, actual J04 parser, J02 add/NOOP/delete, J05 binding and file move, J06 projected lesson/preflight/open task. Two schedules: primary projection already populated or original add event pending until after delete.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/scope.py", + "sha256": "2762e46016b2f4e1a6ea6d95208954724f1cfef8e4e59812a19fc06e97bdf34a" + }, + { + "path": "jitmind/code_context/__init__.py", + "sha256": "0bdda619ccabbb7f4894b106572885cf15b5c86232bfd6f333f6ca1b8b75f211" + }, + { + "path": "jitmind/code_context/models.py", + "sha256": "84686d3cdb1f34e6111652956e65b90b01fd19487308a268022a66b14ea44878" + }, + { + "path": "jitmind/code_context/process.py", + "sha256": "ef9baf49a5bbe761fbffa1f60ef172b8f53c587eaffc13c4e179f2700462f77a" + }, + { + "path": "jitmind/code_context/retriever.py", + "sha256": "822dc84804992b8bd9fe7de62e535843585091350f8ff5a2311a05eaf51150f4" + }, + { + "path": "jitmind/code_context/service.py", + "sha256": "16daa9b16b9a55f130ca61204c96d40e8abb279709dbd4c36b81e4c99afbe873" + }, + { + "path": "jitmind/code_context/snapshot.py", + "sha256": "45a35d8a3455cde10816ff3e2feef3a7a21174bbec41326635d94394fec27272" + }, + { + "path": "jitmind/code_memory/anchors.py", + "sha256": "98d9715ad0faba844638859e5f49d8ccb58cd9a7e67c56c7376b81b08c24e31a" + }, + { + "path": "jitmind/code_memory/binding_models.py", + "sha256": "39c9e9676f58314e4e3d9073efd19f0072023440cdb6fc61f9d802fc9a9f203c" + }, + { + "path": "jitmind/code_memory/binding_storage.py", + "sha256": "5684d3bf4269703f87f4232f0d3fd32482d90be704170f57e1cc6670ab539c1f" + }, + { + "path": "jitmind/code_memory/revalidation.py", + "sha256": "ada66aa4f8d553d8930eb37aff00662544d7216bdfae941d643485ca8cdd92d5" + }, + { + "path": "jitmind/code_memory/open_work.py", + "sha256": "330b670fa75dfc33bd0013a4af3293fed415c29ef4f1df8df2f3295642e3a23c" + }, + { + "path": "jitmind/code_memory/work_storage.py", + "sha256": "f0a2775db9046f8b01007c946a586e9a4bd1ab3763fff5fef87df0d5555b8362" + }, + { + "path": "jitmind/code_memory/lesson_models.py", + "sha256": "447721bf5d7c7b972a4d3b1bda171c674a107d3aba50c90fa0033403f4c5b787" + }, + { + "path": "jitmind/code_memory/preflight.py", + "sha256": "7119d160107db1f0828fa31affc3aba18bcd716163df562a8c77c45cfebc6258" + } + ], + "assertions": [ + "Fact durable and lesson delivered while primary outbox lag remains visible; NOOP delivered twice ahead of original add leaves watermark 0.", + "Real source move makes prior code freshness nonfresh and binding unknown; new build/revalidation produces higher generation and moved verified binding.", + "Lesson version 2 replay is idempotent; version 1 rejected; fact metadata redelivery rejected.", + "Deletion metadata and event followed by old add cannot resurrect fact/binding/lesson; pending add schedule explicitly delivers delete before still-pending add.", + "Primary watermark reaches delete revision, pending count zero, current code generation remains correct." + ], + "evidence_limits": [ + "J04 raw code index consumes captured source, not fact bodies. MEMORY_ONLY_SENTINEL_83f91c is deliberately absent from source.", + "Raw authorized source remains readable after memory forget; forgetting memory never promises deletion of user source files.", + "J02 primary administrative/include_inactive history and backups may retain bodies. Assertions concern ordinary derived retrieval, receipt reconstruction, and content-free binding/work/delivery histories; no physical erasure claim.", + "Source generation, binding observation and outbox revision are separate; no atomic transaction across checkout and three databases is claimed.", + "Uses supplied J10 snapshot. Owner modules may advance; final supervisor must assemble and retest, configuring newer authority adapters if required. No automatic listener or raw-code outbox consumer is invented." + ] + }, + { + "node_id": "tests/test_acceptance_edges.py::test_real_parser_binding_projection_redelivery_and_primary_forget[add_pending]", + "kind": "projection", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Temporary unversioned checkout, actual J04 parser, J02 add/NOOP/delete, J05 binding and file move, J06 projected lesson/preflight/open task. Two schedules: primary projection already populated or original add event pending until after delete.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/scope.py", + "sha256": "2762e46016b2f4e1a6ea6d95208954724f1cfef8e4e59812a19fc06e97bdf34a" + }, + { + "path": "jitmind/code_context/__init__.py", + "sha256": "0bdda619ccabbb7f4894b106572885cf15b5c86232bfd6f333f6ca1b8b75f211" + }, + { + "path": "jitmind/code_context/models.py", + "sha256": "84686d3cdb1f34e6111652956e65b90b01fd19487308a268022a66b14ea44878" + }, + { + "path": "jitmind/code_context/process.py", + "sha256": "ef9baf49a5bbe761fbffa1f60ef172b8f53c587eaffc13c4e179f2700462f77a" + }, + { + "path": "jitmind/code_context/retriever.py", + "sha256": "822dc84804992b8bd9fe7de62e535843585091350f8ff5a2311a05eaf51150f4" + }, + { + "path": "jitmind/code_context/service.py", + "sha256": "16daa9b16b9a55f130ca61204c96d40e8abb279709dbd4c36b81e4c99afbe873" + }, + { + "path": "jitmind/code_context/snapshot.py", + "sha256": "45a35d8a3455cde10816ff3e2feef3a7a21174bbec41326635d94394fec27272" + }, + { + "path": "jitmind/code_memory/anchors.py", + "sha256": "98d9715ad0faba844638859e5f49d8ccb58cd9a7e67c56c7376b81b08c24e31a" + }, + { + "path": "jitmind/code_memory/binding_models.py", + "sha256": "39c9e9676f58314e4e3d9073efd19f0072023440cdb6fc61f9d802fc9a9f203c" + }, + { + "path": "jitmind/code_memory/binding_storage.py", + "sha256": "5684d3bf4269703f87f4232f0d3fd32482d90be704170f57e1cc6670ab539c1f" + }, + { + "path": "jitmind/code_memory/revalidation.py", + "sha256": "ada66aa4f8d553d8930eb37aff00662544d7216bdfae941d643485ca8cdd92d5" + }, + { + "path": "jitmind/code_memory/open_work.py", + "sha256": "330b670fa75dfc33bd0013a4af3293fed415c29ef4f1df8df2f3295642e3a23c" + }, + { + "path": "jitmind/code_memory/work_storage.py", + "sha256": "f0a2775db9046f8b01007c946a586e9a4bd1ab3763fff5fef87df0d5555b8362" + }, + { + "path": "jitmind/code_memory/lesson_models.py", + "sha256": "447721bf5d7c7b972a4d3b1bda171c674a107d3aba50c90fa0033403f4c5b787" + }, + { + "path": "jitmind/code_memory/preflight.py", + "sha256": "7119d160107db1f0828fa31affc3aba18bcd716163df562a8c77c45cfebc6258" + } + ], + "assertions": [ + "Fact durable and lesson delivered while primary outbox lag remains visible; NOOP delivered twice ahead of original add leaves watermark 0.", + "Real source move makes prior code freshness nonfresh and binding unknown; new build/revalidation produces higher generation and moved verified binding.", + "Lesson version 2 replay is idempotent; version 1 rejected; fact metadata redelivery rejected.", + "Deletion metadata and event followed by old add cannot resurrect fact/binding/lesson; pending add schedule explicitly delivers delete before still-pending add.", + "Primary watermark reaches delete revision, pending count zero, current code generation remains correct." + ], + "evidence_limits": [ + "J04 raw code index consumes captured source, not fact bodies. MEMORY_ONLY_SENTINEL_83f91c is deliberately absent from source.", + "Raw authorized source remains readable after memory forget; forgetting memory never promises deletion of user source files.", + "J02 primary administrative/include_inactive history and backups may retain bodies. Assertions concern ordinary derived retrieval, receipt reconstruction, and content-free binding/work/delivery histories; no physical erasure claim.", + "Source generation, binding observation and outbox revision are separate; no atomic transaction across checkout and three databases is claimed.", + "Uses supplied J10 snapshot. Owner modules may advance; final supervisor must assemble and retest, configuring newer authority adapters if required. No automatic listener or raw-code outbox consumer is invented." + ] + } + ] + } + ], + "scenario": "Projection outbox redelivery", + "required_assertion": "Primary durability intact, replay idempotent, lag visible; no stale graph evidence declared current" + }, + { + "case_id": "J31", + "status": "not_run", + "stages": [ + { + "stage_id": "J-04", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_acceptance_edges.py::test_real_parser_binding_projection_redelivery_and_primary_forget[projected]", + "kind": "projection", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Same two actual composed parser chains as J29; memory-only sentinel first positively delivered from bound lesson and memory, then primary forget with deletion projection delayed.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/scope.py", + "sha256": "2762e46016b2f4e1a6ea6d95208954724f1cfef8e4e59812a19fc06e97bdf34a" + }, + { + "path": "jitmind/code_context/__init__.py", + "sha256": "0bdda619ccabbb7f4894b106572885cf15b5c86232bfd6f333f6ca1b8b75f211" + }, + { + "path": "jitmind/code_context/models.py", + "sha256": "84686d3cdb1f34e6111652956e65b90b01fd19487308a268022a66b14ea44878" + }, + { + "path": "jitmind/code_context/process.py", + "sha256": "ef9baf49a5bbe761fbffa1f60ef172b8f53c587eaffc13c4e179f2700462f77a" + }, + { + "path": "jitmind/code_context/retriever.py", + "sha256": "822dc84804992b8bd9fe7de62e535843585091350f8ff5a2311a05eaf51150f4" + }, + { + "path": "jitmind/code_context/service.py", + "sha256": "16daa9b16b9a55f130ca61204c96d40e8abb279709dbd4c36b81e4c99afbe873" + }, + { + "path": "jitmind/code_context/snapshot.py", + "sha256": "45a35d8a3455cde10816ff3e2feef3a7a21174bbec41326635d94394fec27272" + }, + { + "path": "jitmind/code_memory/anchors.py", + "sha256": "98d9715ad0faba844638859e5f49d8ccb58cd9a7e67c56c7376b81b08c24e31a" + }, + { + "path": "jitmind/code_memory/binding_models.py", + "sha256": "39c9e9676f58314e4e3d9073efd19f0072023440cdb6fc61f9d802fc9a9f203c" + }, + { + "path": "jitmind/code_memory/binding_storage.py", + "sha256": "5684d3bf4269703f87f4232f0d3fd32482d90be704170f57e1cc6670ab539c1f" + }, + { + "path": "jitmind/code_memory/revalidation.py", + "sha256": "ada66aa4f8d553d8930eb37aff00662544d7216bdfae941d643485ca8cdd92d5" + }, + { + "path": "jitmind/code_memory/open_work.py", + "sha256": "330b670fa75dfc33bd0013a4af3293fed415c29ef4f1df8df2f3295642e3a23c" + }, + { + "path": "jitmind/code_memory/work_storage.py", + "sha256": "f0a2775db9046f8b01007c946a586e9a4bd1ab3763fff5fef87df0d5555b8362" + }, + { + "path": "jitmind/code_memory/lesson_models.py", + "sha256": "447721bf5d7c7b972a4d3b1bda171c674a107d3aba50c90fa0033403f4c5b787" + }, + { + "path": "jitmind/code_memory/preflight.py", + "sha256": "7119d160107db1f0828fa31affc3aba18bcd716163df562a8c77c45cfebc6258" + } + ], + "assertions": [ + "After primary forget, ordinary fact/page/adapters/projected entries/receipt reconstruction exclude sentinel before any delete projection.", + "Both saved preflight receipts return empty payload; candidates empty; bound projection refused; deletion metadata then old events cannot revive content.", + "Purged lesson table empty; binding history, work history/receipts, delivery receipts and tombstones contain no sentinel.", + "Task remains open revision 1 with repo fallback. Raw authorized source remains exact and readable with original SHA-256, current generation and no memory sentinel." + ], + "evidence_limits": [ + "J04 raw code index consumes captured source, not fact bodies. MEMORY_ONLY_SENTINEL_83f91c is deliberately absent from source.", + "Raw authorized source remains readable after memory forget; forgetting memory never promises deletion of user source files.", + "J02 primary administrative/include_inactive history and backups may retain bodies. Assertions concern ordinary derived retrieval, receipt reconstruction, and content-free binding/work/delivery histories; no physical erasure claim.", + "Source generation, binding observation and outbox revision are separate; no atomic transaction across checkout and three databases is claimed.", + "Uses supplied J10 snapshot. Owner modules may advance; final supervisor must assemble and retest, configuring newer authority adapters if required. No automatic listener or raw-code outbox consumer is invented." + ] + }, + { + "node_id": "tests/test_acceptance_edges.py::test_real_parser_binding_projection_redelivery_and_primary_forget[add_pending]", + "kind": "projection", + "status": "not_run", + "source": { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + }, + "fixtures": [ + { + "path": "tests/test_acceptance_edges.py", + "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + } + ], + "fixture_description": "Same two actual composed parser chains as J29; memory-only sentinel first positively delivered from bound lesson and memory, then primary forget with deletion projection delayed.", + "modules_composed": [ + { + "path": "jitmind/storage/__init__.py", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e" + }, + { + "path": "jitmind/storage/models.py", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354" + }, + { + "path": "jitmind/storage/sqlite.py", + "sha256": "0fa4ca4acf0975184a8e3d40a9780e2671136e07a9ff5a9cc71030e792ee013c" + }, + { + "path": "jitmind/scope.py", + "sha256": "2762e46016b2f4e1a6ea6d95208954724f1cfef8e4e59812a19fc06e97bdf34a" + }, + { + "path": "jitmind/code_context/__init__.py", + "sha256": "0bdda619ccabbb7f4894b106572885cf15b5c86232bfd6f333f6ca1b8b75f211" + }, + { + "path": "jitmind/code_context/models.py", + "sha256": "84686d3cdb1f34e6111652956e65b90b01fd19487308a268022a66b14ea44878" + }, + { + "path": "jitmind/code_context/process.py", + "sha256": "ef9baf49a5bbe761fbffa1f60ef172b8f53c587eaffc13c4e179f2700462f77a" + }, + { + "path": "jitmind/code_context/retriever.py", + "sha256": "822dc84804992b8bd9fe7de62e535843585091350f8ff5a2311a05eaf51150f4" + }, + { + "path": "jitmind/code_context/service.py", + "sha256": "16daa9b16b9a55f130ca61204c96d40e8abb279709dbd4c36b81e4c99afbe873" + }, + { + "path": "jitmind/code_context/snapshot.py", + "sha256": "45a35d8a3455cde10816ff3e2feef3a7a21174bbec41326635d94394fec27272" + }, + { + "path": "jitmind/code_memory/anchors.py", + "sha256": "98d9715ad0faba844638859e5f49d8ccb58cd9a7e67c56c7376b81b08c24e31a" + }, + { + "path": "jitmind/code_memory/binding_models.py", + "sha256": "39c9e9676f58314e4e3d9073efd19f0072023440cdb6fc61f9d802fc9a9f203c" + }, + { + "path": "jitmind/code_memory/binding_storage.py", + "sha256": "5684d3bf4269703f87f4232f0d3fd32482d90be704170f57e1cc6670ab539c1f" + }, + { + "path": "jitmind/code_memory/revalidation.py", + "sha256": "ada66aa4f8d553d8930eb37aff00662544d7216bdfae941d643485ca8cdd92d5" + }, + { + "path": "jitmind/code_memory/open_work.py", + "sha256": "330b670fa75dfc33bd0013a4af3293fed415c29ef4f1df8df2f3295642e3a23c" + }, + { + "path": "jitmind/code_memory/work_storage.py", + "sha256": "f0a2775db9046f8b01007c946a586e9a4bd1ab3763fff5fef87df0d5555b8362" + }, + { + "path": "jitmind/code_memory/lesson_models.py", + "sha256": "447721bf5d7c7b972a4d3b1bda171c674a107d3aba50c90fa0033403f4c5b787" + }, + { + "path": "jitmind/code_memory/preflight.py", + "sha256": "7119d160107db1f0828fa31affc3aba18bcd716163df562a8c77c45cfebc6258" + } + ], + "assertions": [ + "After primary forget, ordinary fact/page/adapters/projected entries/receipt reconstruction exclude sentinel before any delete projection.", + "Both saved preflight receipts return empty payload; candidates empty; bound projection refused; deletion metadata then old events cannot revive content.", + "Purged lesson table empty; binding history, work history/receipts, delivery receipts and tombstones contain no sentinel.", + "Task remains open revision 1 with repo fallback. Raw authorized source remains exact and readable with original SHA-256, current generation and no memory sentinel." + ], + "evidence_limits": [ + "J04 raw code index consumes captured source, not fact bodies. MEMORY_ONLY_SENTINEL_83f91c is deliberately absent from source.", + "Raw authorized source remains readable after memory forget; forgetting memory never promises deletion of user source files.", + "J02 primary administrative/include_inactive history and backups may retain bodies. Assertions concern ordinary derived retrieval, receipt reconstruction, and content-free binding/work/delivery histories; no physical erasure claim.", + "Source generation, binding observation and outbox revision are separate; no atomic transaction across checkout and three databases is claimed.", + "Uses supplied J10 snapshot. Owner modules may advance; final supervisor must assemble and retest, configuring newer authority adapters if required. No automatic listener or raw-code outbox consumer is invented." + ] + } + ] + } + ], + "scenario": "Forget and derived retention", + "required_assertion": "Current retrieval excludes forgotten content; obligation remains; retained metadata does not leak body" + } + ], + "collection": { + "status": "not_run", + "selectors": [ + "tests/test_acceptance_edges.py", + "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair", + "tests/test_durable_migration.py::test_invalid_migration_refuses_without_changes[truncated]", + "tests/test_durable_migration.py::test_invalid_migration_refuses_without_changes[duplicate_json_key]", + "tests/test_durable_migration.py::test_invalid_migration_refuses_without_changes[nan]", + "tests/test_durable_migration.py::test_staged_failure_leaves_legacy_and_candidate_unchanged", + "tests/test_checkpoint_ledger.py::test_tool_boundaries_and_explicit_terminals", + "tests/test_open_work_bindings.py::test_j16_j31_real_binding_move_disappearance_forget_keep_obligation" + ], + "exact_node_ids": [ + "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[advanced]", + "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[memory]", + "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[ttl_memory]", + "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[pages]", + "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[ttl_pages]", + "tests/test_acceptance_edges.py::test_real_sqlite_full_rolls_back_every_effect_then_accepts_same_request", + "tests/test_acceptance_edges.py::test_real_migration_exit_preserves_source_and_allows_retry[after_import_pages]", + "tests/test_acceptance_edges.py::test_real_migration_exit_preserves_source_and_allows_retry[before_import_commit]", + "tests/test_acceptance_edges.py::test_real_parser_binding_projection_redelivery_and_primary_forget[projected]", + "tests/test_acceptance_edges.py::test_real_parser_binding_projection_redelivery_and_primary_forget[add_pending]", + "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[before_transaction-False]", + "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[after_page_insert-False]", + "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[after_fact_insert-False]", + "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[after_outbox_receipt-False]", + "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[after_commit-True]", + "tests/test_durable_migration.py::test_invalid_migration_refuses_without_changes[truncated]", + "tests/test_durable_migration.py::test_invalid_migration_refuses_without_changes[duplicate_json_key]", + "tests/test_durable_migration.py::test_invalid_migration_refuses_without_changes[nan]", + "tests/test_durable_migration.py::test_staged_failure_leaves_legacy_and_candidate_unchanged[before_import]", + "tests/test_durable_migration.py::test_staged_failure_leaves_legacy_and_candidate_unchanged[after_import_pages]", + "tests/test_durable_migration.py::test_staged_failure_leaves_legacy_and_candidate_unchanged[before_import_commit]", + "tests/test_checkpoint_ledger.py::test_tool_boundaries_and_explicit_terminals[tool_result]", + "tests/test_checkpoint_ledger.py::test_tool_boundaries_and_explicit_terminals[tool_cancel]", + "tests/test_checkpoint_ledger.py::test_tool_boundaries_and_explicit_terminals[tool_timeout]", + "tests/test_open_work_bindings.py::test_j16_j31_real_binding_move_disappearance_forget_keep_obligation[# code removed\\n-orphaned_confirmed]", + "tests/test_open_work_bindings.py::test_j16_j31_real_binding_move_disappearance_forget_keep_obligation[invalid syntax ???\\n-unknown]" + ], + "unique_node_count": 26 + }, + "all_copied_dependencies": [ + { + "owner": "J02", + "path": "jitmind/storage/__init__.py", + "snapshot_sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e", + "sha256": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "ff45e7aa0f7985ea7c11adc89e4889bd91b50358907372648fe1eb1766f0313e", + "owner_differs_at_review": false + }, + { + "owner": "J02", + "path": "jitmind/storage/migration.py", + "snapshot_sha256": "966fa1107445aa332122ce9a49844cb61d76ebad85780e87d81ffb71e7ee9b23", + "sha256": "966fa1107445aa332122ce9a49844cb61d76ebad85780e87d81ffb71e7ee9b23", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "26cf90e0911fe6bfae875ef31c50f0b8cbf94b05c2d5a694cd5408622533a15a", + "owner_differs_at_review": true + }, + { + "owner": "J02", + "path": "jitmind/storage/models.py", + "snapshot_sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354", + "sha256": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "db77d142af7c8d8a1c20307be9341b135f1e54e6b3c845e7c8a3da82f9588354", + "owner_differs_at_review": false + }, + { + "owner": "J02", + "path": "jitmind/storage/sqlite.py", + "snapshot_sha256": "a5b890e4fff708c476b8c481437b6d8abbe281abbc5c12857806aa63ddce3514", + "sha256": "a5b890e4fff708c476b8c481437b6d8abbe281abbc5c12857806aa63ddce3514", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "1201fbe05afc29b6452216fb21482cb1b97bb54557f15e7780a639cddcfd55eb", + "owner_differs_at_review": true + }, + { + "owner": "J02", + "path": "jitmind/agents/memory_agent.py", + "snapshot_sha256": "1c665b46b527c24e731850b66181c536e630bdc6cdf461523d32b5c5e6801cd2", + "sha256": "1c665b46b527c24e731850b66181c536e630bdc6cdf461523d32b5c5e6801cd2", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "1c665b46b527c24e731850b66181c536e630bdc6cdf461523d32b5c5e6801cd2", + "owner_differs_at_review": false + }, + { + "owner": "J02", + "path": "tests/test_durable_migration.py", + "snapshot_sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60", + "sha256": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "fd8d059cf599243df5e081203dcab1a6b0eb15cec35c2b2cdfa583f00dfa7c60", + "owner_differs_at_review": false + }, + { + "owner": "J02", + "path": "tests/test_durable_remediation.py", + "snapshot_sha256": "9d71f19f47da8d05775382fd89f1aed918e739b81adc09fac1575aae1e6d9383", + "sha256": "9d71f19f47da8d05775382fd89f1aed918e739b81adc09fac1575aae1e6d9383", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "1e8acdf24b9b98b02d07ee335e10d8e46403b0d52a134501d64b306afe409f47", + "owner_differs_at_review": true + }, + { + "owner": "J02", + "path": "tests/test_durable_storage.py", + "snapshot_sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00", + "sha256": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "ea08af202b8806b8d96fd20a8e5508dca6ef76d3abef8ab37479e6e8f684cc00", + "owner_differs_at_review": false + }, + { + "owner": "J03", + "path": "jitmind/scope.py", + "snapshot_sha256": "2762e46016b2f4e1a6ea6d95208954724f1cfef8e4e59812a19fc06e97bdf34a", + "sha256": "2762e46016b2f4e1a6ea6d95208954724f1cfef8e4e59812a19fc06e97bdf34a", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "2762e46016b2f4e1a6ea6d95208954724f1cfef8e4e59812a19fc06e97bdf34a", + "owner_differs_at_review": false + }, + { + "owner": "J03", + "path": "jitmind/scoped_research.py", + "snapshot_sha256": "5e6428640b58dbd63fc11d69b8417331fc2e995699447699ff2e655ff1bf4d20", + "sha256": "5e6428640b58dbd63fc11d69b8417331fc2e995699447699ff2e655ff1bf4d20", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "5e6428640b58dbd63fc11d69b8417331fc2e995699447699ff2e655ff1bf4d20", + "owner_differs_at_review": false + }, + { + "owner": "J03", + "path": "jitmind/scoped_temporal.py", + "snapshot_sha256": "cb463c776e743af32c55512a7cdb921f1134a9909e616af235c851d44db76326", + "sha256": "cb463c776e743af32c55512a7cdb921f1134a9909e616af235c851d44db76326", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "cb463c776e743af32c55512a7cdb921f1134a9909e616af235c851d44db76326", + "owner_differs_at_review": false + }, + { + "owner": "J03", + "path": "tests/test_scoped_authority.py", + "snapshot_sha256": "c62b826e6c8b562187dc6f0af7ccfa1961a7c9343d5e1570629f65a1c77e23b2", + "sha256": "c62b826e6c8b562187dc6f0af7ccfa1961a7c9343d5e1570629f65a1c77e23b2", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "c62b826e6c8b562187dc6f0af7ccfa1961a7c9343d5e1570629f65a1c77e23b2", + "owner_differs_at_review": false + }, + { + "owner": "J03", + "path": "tests/test_scoped_durable.py", + "snapshot_sha256": "03b01bf9b54bf379bb30b1ddabf9cddf62a619bb30f6086f48a2c7c864d64282", + "sha256": "03b01bf9b54bf379bb30b1ddabf9cddf62a619bb30f6086f48a2c7c864d64282", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "03b01bf9b54bf379bb30b1ddabf9cddf62a619bb30f6086f48a2c7c864d64282", + "owner_differs_at_review": false + }, + { + "owner": "J03", + "path": "tests/test_scoped_research.py", + "snapshot_sha256": "428d4c17df53220a76f4e38c1be91f50d025418063613eac58dc59ec5bd17108", + "sha256": "428d4c17df53220a76f4e38c1be91f50d025418063613eac58dc59ec5bd17108", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "428d4c17df53220a76f4e38c1be91f50d025418063613eac58dc59ec5bd17108", + "owner_differs_at_review": false + }, + { + "owner": "J03", + "path": "tests/test_scoped_temporal.py", + "snapshot_sha256": "e335712d09b7ecdc5e466b63008fb717dab4b9b772623e6b51df840ec71eb66e", + "sha256": "e335712d09b7ecdc5e466b63008fb717dab4b9b772623e6b51df840ec71eb66e", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "e335712d09b7ecdc5e466b63008fb717dab4b9b772623e6b51df840ec71eb66e", + "owner_differs_at_review": false + }, + { + "owner": "J04", + "path": "jitmind/code_context/__init__.py", + "snapshot_sha256": "0bdda619ccabbb7f4894b106572885cf15b5c86232bfd6f333f6ca1b8b75f211", + "sha256": "0bdda619ccabbb7f4894b106572885cf15b5c86232bfd6f333f6ca1b8b75f211", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "0bdda619ccabbb7f4894b106572885cf15b5c86232bfd6f333f6ca1b8b75f211", + "owner_differs_at_review": false + }, + { + "owner": "J04", + "path": "jitmind/code_context/models.py", + "snapshot_sha256": "84686d3cdb1f34e6111652956e65b90b01fd19487308a268022a66b14ea44878", + "sha256": "84686d3cdb1f34e6111652956e65b90b01fd19487308a268022a66b14ea44878", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "84686d3cdb1f34e6111652956e65b90b01fd19487308a268022a66b14ea44878", + "owner_differs_at_review": false + }, + { + "owner": "J04", + "path": "jitmind/code_context/process.py", + "snapshot_sha256": "ef9baf49a5bbe761fbffa1f60ef172b8f53c587eaffc13c4e179f2700462f77a", + "sha256": "ef9baf49a5bbe761fbffa1f60ef172b8f53c587eaffc13c4e179f2700462f77a", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "ef9baf49a5bbe761fbffa1f60ef172b8f53c587eaffc13c4e179f2700462f77a", + "owner_differs_at_review": false + }, + { + "owner": "J04", + "path": "jitmind/code_context/retriever.py", + "snapshot_sha256": "822dc84804992b8bd9fe7de62e535843585091350f8ff5a2311a05eaf51150f4", + "sha256": "822dc84804992b8bd9fe7de62e535843585091350f8ff5a2311a05eaf51150f4", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "822dc84804992b8bd9fe7de62e535843585091350f8ff5a2311a05eaf51150f4", + "owner_differs_at_review": false + }, + { + "owner": "J04", + "path": "jitmind/code_context/service.py", + "snapshot_sha256": "16daa9b16b9a55f130ca61204c96d40e8abb279709dbd4c36b81e4c99afbe873", + "sha256": "16daa9b16b9a55f130ca61204c96d40e8abb279709dbd4c36b81e4c99afbe873", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "16daa9b16b9a55f130ca61204c96d40e8abb279709dbd4c36b81e4c99afbe873", + "owner_differs_at_review": false + }, + { + "owner": "J04", + "path": "jitmind/code_context/snapshot.py", + "snapshot_sha256": "45a35d8a3455cde10816ff3e2feef3a7a21174bbec41326635d94394fec27272", + "sha256": "45a35d8a3455cde10816ff3e2feef3a7a21174bbec41326635d94394fec27272", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "45a35d8a3455cde10816ff3e2feef3a7a21174bbec41326635d94394fec27272", + "owner_differs_at_review": false + }, + { + "owner": "J04", + "path": "tests/test_code_context.py", + "snapshot_sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09", + "sha256": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "ecf614237e36094ddfcdebe37ec45af1ce92d3df3e433d89703435590ac3fa09", + "owner_differs_at_review": false + }, + { + "owner": "J04", + "path": "tests/test_code_context_process.py", + "snapshot_sha256": "67152ebf0b781d45feba30c232625d7bbb93ded937e2c87ea4811af5b06ffd81", + "sha256": "67152ebf0b781d45feba30c232625d7bbb93ded937e2c87ea4811af5b06ffd81", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "67152ebf0b781d45feba30c232625d7bbb93ded937e2c87ea4811af5b06ffd81", + "owner_differs_at_review": false + }, + { + "owner": "J05", + "path": "jitmind/code_memory/__init__.py", + "snapshot_sha256": "79312b29319783d400b5ce459dabe487e7b7cd2f2fbe0d3594334e2a9b377563", + "sha256": "79312b29319783d400b5ce459dabe487e7b7cd2f2fbe0d3594334e2a9b377563", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "79312b29319783d400b5ce459dabe487e7b7cd2f2fbe0d3594334e2a9b377563", + "owner_differs_at_review": false + }, + { + "owner": "J05", + "path": "jitmind/code_memory/anchors.py", + "snapshot_sha256": "60a778774b250ff761e4cef622ed8f45e5e358079a2c0646a3f718495fe5e2c6", + "sha256": "60a778774b250ff761e4cef622ed8f45e5e358079a2c0646a3f718495fe5e2c6", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "98d9715ad0faba844638859e5f49d8ccb58cd9a7e67c56c7376b81b08c24e31a", + "owner_differs_at_review": true + }, + { + "owner": "J05", + "path": "jitmind/code_memory/binding_models.py", + "snapshot_sha256": "39c9e9676f58314e4e3d9073efd19f0072023440cdb6fc61f9d802fc9a9f203c", + "sha256": "39c9e9676f58314e4e3d9073efd19f0072023440cdb6fc61f9d802fc9a9f203c", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "39c9e9676f58314e4e3d9073efd19f0072023440cdb6fc61f9d802fc9a9f203c", + "owner_differs_at_review": false + }, + { + "owner": "J05", + "path": "jitmind/code_memory/binding_storage.py", + "snapshot_sha256": "aacd73710c97f097f1c5934db142e20bd6ee8d6d6f8ae13d87ae3fbfdd17d9d7", + "sha256": "aacd73710c97f097f1c5934db142e20bd6ee8d6d6f8ae13d87ae3fbfdd17d9d7", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "5684d3bf4269703f87f4232f0d3fd32482d90be704170f57e1cc6670ab539c1f", + "owner_differs_at_review": true + }, + { + "owner": "J05", + "path": "jitmind/code_memory/revalidation.py", + "snapshot_sha256": "ada66aa4f8d553d8930eb37aff00662544d7216bdfae941d643485ca8cdd92d5", + "sha256": "ada66aa4f8d553d8930eb37aff00662544d7216bdfae941d643485ca8cdd92d5", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "ada66aa4f8d553d8930eb37aff00662544d7216bdfae941d643485ca8cdd92d5", + "owner_differs_at_review": false + }, + { + "owner": "J05", + "path": "tests/test_code_anchors.py", + "snapshot_sha256": "cc61bb85ed1b3e528941bfbde1241d0c720e674b1f47cafa4f89831b0eb670b1", + "sha256": "cc61bb85ed1b3e528941bfbde1241d0c720e674b1f47cafa4f89831b0eb670b1", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "8255edab92b341ef41dd5556a68f3f2be8e52b0e940e7e9e98891f2f5cced3cb", + "owner_differs_at_review": true + }, + { + "owner": "J06", + "path": "jitmind/code_memory/open_work.py", + "snapshot_sha256": "330b670fa75dfc33bd0013a4af3293fed415c29ef4f1df8df2f3295642e3a23c", + "sha256": "330b670fa75dfc33bd0013a4af3293fed415c29ef4f1df8df2f3295642e3a23c", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "330b670fa75dfc33bd0013a4af3293fed415c29ef4f1df8df2f3295642e3a23c", + "owner_differs_at_review": false + }, + { + "owner": "J06", + "path": "jitmind/code_memory/work_storage.py", + "snapshot_sha256": "2f06be2fbecfc979bc60d39d5cee6fc6a629d8a11940fd8d6f03d71595a28892", + "sha256": "2f06be2fbecfc979bc60d39d5cee6fc6a629d8a11940fd8d6f03d71595a28892", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "2f06be2fbecfc979bc60d39d5cee6fc6a629d8a11940fd8d6f03d71595a28892", + "owner_differs_at_review": false + }, + { + "owner": "J06", + "path": "jitmind/code_memory/lesson_models.py", + "snapshot_sha256": "17c1547051fb5338fd357615d8c673fc2ccb62d2b23e94110af8b7bd201cf4ff", + "sha256": "17c1547051fb5338fd357615d8c673fc2ccb62d2b23e94110af8b7bd201cf4ff", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "01b070099067132dbb5b9269a2657dcf1f22141d67c4cef5c32717f049ea93c8", + "owner_differs_at_review": true + }, + { + "owner": "J06", + "path": "jitmind/code_memory/preflight.py", + "snapshot_sha256": "dadb006f88ce520cfaf574259f1a577ca544b3d387486ff4e1b75e1c028c3bca", + "sha256": "dadb006f88ce520cfaf574259f1a577ca544b3d387486ff4e1b75e1c028c3bca", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "7119d160107db1f0828fa31affc3aba18bcd716163df562a8c77c45cfebc6258", + "owner_differs_at_review": true + }, + { + "owner": "J06", + "path": "tests/test_open_work.py", + "snapshot_sha256": "b0b192f5bd1ecfe39811346eb4ce912a85a15d00c446e31e8f2a01493e957597", + "sha256": "b0b192f5bd1ecfe39811346eb4ce912a85a15d00c446e31e8f2a01493e957597", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "b0b192f5bd1ecfe39811346eb4ce912a85a15d00c446e31e8f2a01493e957597", + "owner_differs_at_review": false + }, + { + "owner": "J06", + "path": "tests/test_open_work_bindings.py", + "snapshot_sha256": "96d38b318fe0e1dc8fa695c60ed4f2f2e50f6f60c2b02d168583845448cad405", + "sha256": "96d38b318fe0e1dc8fa695c60ed4f2f2e50f6f60c2b02d168583845448cad405", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "8c3f5e7c44588c7bbb4478e3c9b93fdedfbecbdf7496e4c1e4a41ec0fb4576e3", + "owner_differs_at_review": true + }, + { + "owner": "J06", + "path": "tests/test_preflight.py", + "snapshot_sha256": "3b5251f8dcaba3de82112d7760e162263fea96c7a59af70d6a32759c41324f26", + "sha256": "3b5251f8dcaba3de82112d7760e162263fea96c7a59af70d6a32759c41324f26", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "3b5251f8dcaba3de82112d7760e162263fea96c7a59af70d6a32759c41324f26", + "owner_differs_at_review": false + }, + { + "owner": "J07", + "path": ".gitignore", + "snapshot_sha256": "b5febaf8d92c40efc842d22cc481a0d3d9d732ca92891646e3e6b8a569261d68", + "sha256": "b5febaf8d92c40efc842d22cc481a0d3d9d732ca92891646e3e6b8a569261d68", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "b5febaf8d92c40efc842d22cc481a0d3d9d732ca92891646e3e6b8a569261d68", + "owner_differs_at_review": false + }, + { + "owner": "J07", + "path": "jitmind/checkpoints/__init__.py", + "snapshot_sha256": "4d54e3f91114b474c337fbd460653e46210c2c668fcb557c231560e8477c0017", + "sha256": "4d54e3f91114b474c337fbd460653e46210c2c668fcb557c231560e8477c0017", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "4d54e3f91114b474c337fbd460653e46210c2c668fcb557c231560e8477c0017", + "owner_differs_at_review": false + }, + { + "owner": "J07", + "path": "jitmind/checkpoints/ledger.py", + "snapshot_sha256": "c3c5b6805d6959a86ec242a6153818a1b4b2b95cd3789493d59f4ed23a790910", + "sha256": "c3c5b6805d6959a86ec242a6153818a1b4b2b95cd3789493d59f4ed23a790910", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "c3c5b6805d6959a86ec242a6153818a1b4b2b95cd3789493d59f4ed23a790910", + "owner_differs_at_review": false + }, + { + "owner": "J07", + "path": "jitmind/utils/checkpoint.py", + "snapshot_sha256": "84e108f0d5c1b87061425f5218a83b4f47b9cd2b3f805022a326bd059773c3ba", + "sha256": "84e108f0d5c1b87061425f5218a83b4f47b9cd2b3f805022a326bd059773c3ba", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "84e108f0d5c1b87061425f5218a83b4f47b9cd2b3f805022a326bd059773c3ba", + "owner_differs_at_review": false + }, + { + "owner": "J07", + "path": "tests/test_checkpoint_ledger.py", + "snapshot_sha256": "63d3df7dbc975322d1f201b497b70f7bef7829621dbe6fad2c71165a6f603a5c", + "sha256": "63d3df7dbc975322d1f201b497b70f7bef7829621dbe6fad2c71165a6f603a5c", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "63d3df7dbc975322d1f201b497b70f7bef7829621dbe6fad2c71165a6f603a5c", + "owner_differs_at_review": false + }, + { + "owner": "J07", + "path": "tests/test_checkpoint_manager.py", + "snapshot_sha256": "a85fd91122e6dbde9ddf7b7e5422af622d828192540ef3241d87ef51923f9b65", + "sha256": "a85fd91122e6dbde9ddf7b7e5422af622d828192540ef3241d87ef51923f9b65", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "a85fd91122e6dbde9ddf7b7e5422af622d828192540ef3241d87ef51923f9b65", + "owner_differs_at_review": false + }, + { + "owner": "J07", + "path": "tests/test_checkpoint_scope.py", + "snapshot_sha256": "5651f767a662c021f31022eef609cf2edbc39644c34d423c424a2d9e986f2fc8", + "sha256": "5651f767a662c021f31022eef609cf2edbc39644c34d423c424a2d9e986f2fc8", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "5651f767a662c021f31022eef609cf2edbc39644c34d423c424a2d9e986f2fc8", + "owner_differs_at_review": false + }, + { + "owner": "J09", + "path": "jitmind/temporal_history.py", + "snapshot_sha256": "87b2cc854522cd59f40b90eca48470c07511fb0bc5058dd8ea5e5ffbe0c04e33", + "sha256": "87b2cc854522cd59f40b90eca48470c07511fb0bc5058dd8ea5e5ffbe0c04e33", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "87b2cc854522cd59f40b90eca48470c07511fb0bc5058dd8ea5e5ffbe0c04e33", + "owner_differs_at_review": false + }, + { + "owner": "J09", + "path": "tests/test_temporal_history_sqlite.py", + "snapshot_sha256": "d70e74954ca0d86f2ee8400cf0e4e15efb08bc88b6230c9caaef75bc5c97ac23", + "sha256": "d70e74954ca0d86f2ee8400cf0e4e15efb08bc88b6230c9caaef75bc5c97ac23", + "contribution": false, + "refreshed_by_J10": false, + "owner_sha256_at_review": "d70e74954ca0d86f2ee8400cf0e4e15efb08bc88b6230c9caaef75bc5c97ac23", + "owner_differs_at_review": false + } + ], + "adapter": { + "owner": "J04", + "location": "delivery/J04/adapters/graft relative to orchestration ROOT; frozen copy used for J08 staged tests", + "copied": true, + "runtime_configuration": "JITMIND_TEST_GRAFT_ADAPTER; fallback to repository adapters/graft. JITMIND_TEST_NODE optional, otherwise PATH node.", + "source_digests": [ + { + "path": "LICENSE", + "sha256": "d671f52607b002fad21b4a09cf3a7bd6c507e95abfd90040c775fdd4d83e3d7c" + }, + { + "path": "PROVENANCE.md", + "sha256": "ecf27eddc3450bfdb9e447f3b7eef81ed55bc8eb231df50fa9ba4084e9e3f545" + }, + { + "path": "THIRD_PARTY_NOTICES.txt", + "sha256": "baa6d2158b7af0ca465bdf91261f796f826fdc1fdf168cc19dca3870c78e9889" + }, + { + "path": "adapter-requirements.json", + "sha256": "b56a819dd77bae14d2caa4a69f8236201d98d85e43de55ea55cafae3120a5115" + }, + { + "path": "donor-audit.json", + "sha256": "7423fa884bd1fc8843b623fb1c980db9b0e50431f651d873f8a4ba9c3b7b88e7" + }, + { + "path": "extract.mjs", + "sha256": "5eef6876d53933a7d54d2dae7ab99e793543fc2122573fbae1d53a20a9dc7914" + }, + { + "path": "package-lock.json", + "sha256": "87a7b5cca2ee883795063104eb4298aa8a0c841ac3d8a9b44ecc8d0adec3bef8" + }, + { + "path": "package.json", + "sha256": "ae646f9eb985c24480383f2264322a341ba94e82c556f4c8318a1bb060293145" + }, + { + "path": "runner.mjs", + "sha256": "f7f35fc019f64a169a0095a7c6f5013046cc7e79961b3a3696166b1c46bf6946" + } + ], + "installed_package_manifests": [ + { + "path": "node_modules/tree-sitter/package.json", + "sha256": "8cca5044dd3381dbf958dea36ef6d9f81f379886d32ef845919cf07679c6e42c", + "version": "0.21.1" + }, + { + "path": "node_modules/tree-sitter-python/package.json", + "sha256": "7743dc38552ccb2309f8ee7b5d56b0292ba7b8760ce35509d3d729f4f70a50d7", + "version": "0.21.0" + } + ] + }, + "remaining_limits": [ + "The frozen temporal oracle was read; this supplement adds no temporal acceptance claims.", + "No product modules, copied tests or dependency manifests are J10 contributions.", + "Static type checker not installed; no installs performed." + ], + "integration_review": { + "contribution": "J10 fixtures and mappings; J08 binding-authority configuration and final source attestation", + "historical_dependency_inventory": "all_copied_dependencies describes the original J10 run, not the final composite", + "source_owners": { + "J01": "commit b3fe1d51a4cb98ea2ddce7e94fd3f732010b623d", + "J02": "delivery/J02", + "J03": "delivery/J03", + "J04": "delivery/J04", + "J05": "delivery/J05", + "J06": "worktrees/J06", + "J07": "worktrees/J07", + "J09": "worktrees/J09" + }, + "release_qualified": false + } +} diff --git a/docs/engineering/evidence-kind-normalization.json b/docs/engineering/evidence-kind-normalization.json new file mode 100644 index 0000000..6477d5f --- /dev/null +++ b/docs/engineering/evidence-kind-normalization.json @@ -0,0 +1,453 @@ +{ + "notice": "Metadata normalization to the existing fixed runner vocabulary; node identities, assertions, stage requirements and not_run statuses are unchanged. Specific execution descriptions remain attached to each node.", + "changes": [ + { + "file": "acceptance-map.json", + "case": "J02", + "stage": "J-01", + "node_id": "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[advanced]", + "original_kind": "injected_filesystem_publication_fault", + "canonical_kind": "injected_storage_fault" + }, + { + "file": "acceptance-map.json", + "case": "J02", + "stage": "J-01", + "node_id": "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[memory]", + "original_kind": "injected_filesystem_publication_fault", + "canonical_kind": "injected_storage_fault" + }, + { + "file": "acceptance-map.json", + "case": "J02", + "stage": "J-01", + "node_id": "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[ttl_memory]", + "original_kind": "injected_filesystem_publication_fault", + "canonical_kind": "injected_storage_fault" + }, + { + "file": "acceptance-map.json", + "case": "J02", + "stage": "J-01", + "node_id": "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[pages]", + "original_kind": "injected_filesystem_publication_fault", + "canonical_kind": "injected_storage_fault" + }, + { + "file": "acceptance-map.json", + "case": "J02", + "stage": "J-01", + "node_id": "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[ttl_pages]", + "original_kind": "injected_filesystem_publication_fault", + "canonical_kind": "injected_storage_fault" + }, + { + "file": "acceptance-map.json", + "case": "J02", + "stage": "J-02", + "node_id": "tests/test_acceptance_edges.py::test_real_sqlite_full_rolls_back_every_effect_then_accepts_same_request", + "original_kind": "real_sqlite_capacity", + "canonical_kind": "real_storage" + }, + { + "file": "acceptance-map.json", + "case": "J04", + "stage": "J-02", + "node_id": "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[before_transaction-False]", + "original_kind": "real_process_exit", + "canonical_kind": "real_storage" + }, + { + "file": "acceptance-map.json", + "case": "J04", + "stage": "J-02", + "node_id": "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[after_page_insert-False]", + "original_kind": "real_process_exit", + "canonical_kind": "real_storage" + }, + { + "file": "acceptance-map.json", + "case": "J04", + "stage": "J-02", + "node_id": "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[after_fact_insert-False]", + "original_kind": "real_process_exit", + "canonical_kind": "real_storage" + }, + { + "file": "acceptance-map.json", + "case": "J04", + "stage": "J-02", + "node_id": "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[after_outbox_receipt-False]", + "original_kind": "real_process_exit", + "canonical_kind": "real_storage" + }, + { + "file": "acceptance-map.json", + "case": "J04", + "stage": "J-02", + "node_id": "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[after_commit-True]", + "original_kind": "real_process_exit", + "canonical_kind": "real_storage" + }, + { + "file": "acceptance-map.json", + "case": "J16", + "stage": "J-06", + "node_id": "tests/test_open_work_bindings.py::test_j16_j31_real_binding_move_disappearance_forget_keep_obligation[# code removed\\n-orphaned_confirmed]", + "original_kind": "real_parser_binding_open_work", + "canonical_kind": "real_parser" + }, + { + "file": "acceptance-map.json", + "case": "J16", + "stage": "J-06", + "node_id": "tests/test_open_work_bindings.py::test_j16_j31_real_binding_move_disappearance_forget_keep_obligation[invalid syntax ???\\n-unknown]", + "original_kind": "real_parser_binding_open_work", + "canonical_kind": "real_parser" + }, + { + "file": "acceptance-map.json", + "case": "J22", + "stage": "J-07", + "node_id": "tests/test_checkpoint_ledger.py::test_tool_boundaries_and_explicit_terminals[tool_result]", + "original_kind": "real_checkpoint_ledger", + "canonical_kind": "real_storage" + }, + { + "file": "acceptance-map.json", + "case": "J22", + "stage": "J-07", + "node_id": "tests/test_checkpoint_ledger.py::test_tool_boundaries_and_explicit_terminals[tool_cancel]", + "original_kind": "real_checkpoint_ledger", + "canonical_kind": "real_storage" + }, + { + "file": "acceptance-map.json", + "case": "J22", + "stage": "J-07", + "node_id": "tests/test_checkpoint_ledger.py::test_tool_boundaries_and_explicit_terminals[tool_timeout]", + "original_kind": "real_checkpoint_ledger", + "canonical_kind": "real_storage" + }, + { + "file": "acceptance-map.json", + "case": "J25", + "stage": "J-02", + "node_id": "tests/test_durable_migration.py::test_invalid_migration_refuses_without_changes[truncated]", + "original_kind": "real_migration_with_fault_boundaries", + "canonical_kind": "migration" + }, + { + "file": "acceptance-map.json", + "case": "J25", + "stage": "J-02", + "node_id": "tests/test_durable_migration.py::test_invalid_migration_refuses_without_changes[duplicate_json_key]", + "original_kind": "real_migration_with_fault_boundaries", + "canonical_kind": "migration" + }, + { + "file": "acceptance-map.json", + "case": "J25", + "stage": "J-02", + "node_id": "tests/test_durable_migration.py::test_invalid_migration_refuses_without_changes[nan]", + "original_kind": "real_migration_with_fault_boundaries", + "canonical_kind": "migration" + }, + { + "file": "acceptance-map.json", + "case": "J25", + "stage": "J-02", + "node_id": "tests/test_durable_migration.py::test_staged_failure_leaves_legacy_and_candidate_unchanged[before_import]", + "original_kind": "real_migration_with_fault_boundaries", + "canonical_kind": "migration" + }, + { + "file": "acceptance-map.json", + "case": "J25", + "stage": "J-02", + "node_id": "tests/test_durable_migration.py::test_staged_failure_leaves_legacy_and_candidate_unchanged[after_import_pages]", + "original_kind": "real_migration_with_fault_boundaries", + "canonical_kind": "migration" + }, + { + "file": "acceptance-map.json", + "case": "J25", + "stage": "J-02", + "node_id": "tests/test_durable_migration.py::test_staged_failure_leaves_legacy_and_candidate_unchanged[before_import_commit]", + "original_kind": "real_migration_with_fault_boundaries", + "canonical_kind": "migration" + }, + { + "file": "acceptance-map.json", + "case": "J25", + "stage": "J-02", + "node_id": "tests/test_acceptance_edges.py::test_real_migration_exit_preserves_source_and_allows_retry[after_import_pages]", + "original_kind": "real_migration_with_fault_boundaries", + "canonical_kind": "migration" + }, + { + "file": "acceptance-map.json", + "case": "J25", + "stage": "J-02", + "node_id": "tests/test_acceptance_edges.py::test_real_migration_exit_preserves_source_and_allows_retry[before_import_commit]", + "original_kind": "real_migration_with_fault_boundaries", + "canonical_kind": "migration" + }, + { + "file": "acceptance-map.json", + "case": "J29", + "stage": "J-04", + "node_id": "tests/test_acceptance_edges.py::test_real_parser_binding_projection_redelivery_and_primary_forget[projected]", + "original_kind": "real_parser_binding_projection_composition", + "canonical_kind": "projection" + }, + { + "file": "acceptance-map.json", + "case": "J29", + "stage": "J-04", + "node_id": "tests/test_acceptance_edges.py::test_real_parser_binding_projection_redelivery_and_primary_forget[add_pending]", + "original_kind": "real_parser_binding_projection_composition", + "canonical_kind": "projection" + }, + { + "file": "acceptance-map.json", + "case": "J31", + "stage": "J-04", + "node_id": "tests/test_acceptance_edges.py::test_real_parser_binding_projection_redelivery_and_primary_forget[projected]", + "original_kind": "real_parser_binding_preflight_forget_composition", + "canonical_kind": "projection" + }, + { + "file": "acceptance-map.json", + "case": "J31", + "stage": "J-04", + "node_id": "tests/test_acceptance_edges.py::test_real_parser_binding_projection_redelivery_and_primary_forget[add_pending]", + "original_kind": "real_parser_binding_preflight_forget_composition", + "canonical_kind": "projection" + }, + { + "file": "acceptance-supplement.json", + "case": "J02", + "stage": "J-01", + "node_id": "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[advanced]", + "original_kind": "injected_filesystem_publication_fault", + "canonical_kind": "injected_storage_fault" + }, + { + "file": "acceptance-supplement.json", + "case": "J02", + "stage": "J-01", + "node_id": "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[memory]", + "original_kind": "injected_filesystem_publication_fault", + "canonical_kind": "injected_storage_fault" + }, + { + "file": "acceptance-supplement.json", + "case": "J02", + "stage": "J-01", + "node_id": "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[ttl_memory]", + "original_kind": "injected_filesystem_publication_fault", + "canonical_kind": "injected_storage_fault" + }, + { + "file": "acceptance-supplement.json", + "case": "J02", + "stage": "J-01", + "node_id": "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[pages]", + "original_kind": "injected_filesystem_publication_fault", + "canonical_kind": "injected_storage_fault" + }, + { + "file": "acceptance-supplement.json", + "case": "J02", + "stage": "J-01", + "node_id": "tests/test_acceptance_edges.py::test_enospc_at_legacy_publication_preserves_ack_and_bytes[ttl_pages]", + "original_kind": "injected_filesystem_publication_fault", + "canonical_kind": "injected_storage_fault" + }, + { + "file": "acceptance-supplement.json", + "case": "J02", + "stage": "J-02", + "node_id": "tests/test_acceptance_edges.py::test_real_sqlite_full_rolls_back_every_effect_then_accepts_same_request", + "original_kind": "real_sqlite_capacity", + "canonical_kind": "real_storage" + }, + { + "file": "acceptance-supplement.json", + "case": "J04", + "stage": "J-02", + "node_id": "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[before_transaction-False]", + "original_kind": "real_process_exit", + "canonical_kind": "real_storage" + }, + { + "file": "acceptance-supplement.json", + "case": "J04", + "stage": "J-02", + "node_id": "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[after_page_insert-False]", + "original_kind": "real_process_exit", + "canonical_kind": "real_storage" + }, + { + "file": "acceptance-supplement.json", + "case": "J04", + "stage": "J-02", + "node_id": "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[after_fact_insert-False]", + "original_kind": "real_process_exit", + "canonical_kind": "real_storage" + }, + { + "file": "acceptance-supplement.json", + "case": "J04", + "stage": "J-02", + "node_id": "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[after_outbox_receipt-False]", + "original_kind": "real_process_exit", + "canonical_kind": "real_storage" + }, + { + "file": "acceptance-supplement.json", + "case": "J04", + "stage": "J-02", + "node_id": "tests/test_durable_storage.py::test_process_crash_fresh_reader_sees_zero_or_whole_pair[after_commit-True]", + "original_kind": "real_process_exit", + "canonical_kind": "real_storage" + }, + { + "file": "acceptance-supplement.json", + "case": "J16", + "stage": "J-06", + "node_id": "tests/test_open_work_bindings.py::test_j16_j31_real_binding_move_disappearance_forget_keep_obligation[# code removed\\n-orphaned_confirmed]", + "original_kind": "real_parser_binding_open_work", + "canonical_kind": "real_parser" + }, + { + "file": "acceptance-supplement.json", + "case": "J16", + "stage": "J-06", + "node_id": "tests/test_open_work_bindings.py::test_j16_j31_real_binding_move_disappearance_forget_keep_obligation[invalid syntax ???\\n-unknown]", + "original_kind": "real_parser_binding_open_work", + "canonical_kind": "real_parser" + }, + { + "file": "acceptance-supplement.json", + "case": "J22", + "stage": "J-07", + "node_id": "tests/test_checkpoint_ledger.py::test_tool_boundaries_and_explicit_terminals[tool_result]", + "original_kind": "real_checkpoint_ledger", + "canonical_kind": "real_storage" + }, + { + "file": "acceptance-supplement.json", + "case": "J22", + "stage": "J-07", + "node_id": "tests/test_checkpoint_ledger.py::test_tool_boundaries_and_explicit_terminals[tool_cancel]", + "original_kind": "real_checkpoint_ledger", + "canonical_kind": "real_storage" + }, + { + "file": "acceptance-supplement.json", + "case": "J22", + "stage": "J-07", + "node_id": "tests/test_checkpoint_ledger.py::test_tool_boundaries_and_explicit_terminals[tool_timeout]", + "original_kind": "real_checkpoint_ledger", + "canonical_kind": "real_storage" + }, + { + "file": "acceptance-supplement.json", + "case": "J25", + "stage": "J-02", + "node_id": "tests/test_durable_migration.py::test_invalid_migration_refuses_without_changes[truncated]", + "original_kind": "real_migration_with_fault_boundaries", + "canonical_kind": "migration" + }, + { + "file": "acceptance-supplement.json", + "case": "J25", + "stage": "J-02", + "node_id": "tests/test_durable_migration.py::test_invalid_migration_refuses_without_changes[duplicate_json_key]", + "original_kind": "real_migration_with_fault_boundaries", + "canonical_kind": "migration" + }, + { + "file": "acceptance-supplement.json", + "case": "J25", + "stage": "J-02", + "node_id": "tests/test_durable_migration.py::test_invalid_migration_refuses_without_changes[nan]", + "original_kind": "real_migration_with_fault_boundaries", + "canonical_kind": "migration" + }, + { + "file": "acceptance-supplement.json", + "case": "J25", + "stage": "J-02", + "node_id": "tests/test_durable_migration.py::test_staged_failure_leaves_legacy_and_candidate_unchanged[before_import]", + "original_kind": "real_migration_with_fault_boundaries", + "canonical_kind": "migration" + }, + { + "file": "acceptance-supplement.json", + "case": "J25", + "stage": "J-02", + "node_id": "tests/test_durable_migration.py::test_staged_failure_leaves_legacy_and_candidate_unchanged[after_import_pages]", + "original_kind": "real_migration_with_fault_boundaries", + "canonical_kind": "migration" + }, + { + "file": "acceptance-supplement.json", + "case": "J25", + "stage": "J-02", + "node_id": "tests/test_durable_migration.py::test_staged_failure_leaves_legacy_and_candidate_unchanged[before_import_commit]", + "original_kind": "real_migration_with_fault_boundaries", + "canonical_kind": "migration" + }, + { + "file": "acceptance-supplement.json", + "case": "J25", + "stage": "J-02", + "node_id": "tests/test_acceptance_edges.py::test_real_migration_exit_preserves_source_and_allows_retry[after_import_pages]", + "original_kind": "real_migration_with_fault_boundaries", + "canonical_kind": "migration" + }, + { + "file": "acceptance-supplement.json", + "case": "J25", + "stage": "J-02", + "node_id": "tests/test_acceptance_edges.py::test_real_migration_exit_preserves_source_and_allows_retry[before_import_commit]", + "original_kind": "real_migration_with_fault_boundaries", + "canonical_kind": "migration" + }, + { + "file": "acceptance-supplement.json", + "case": "J29", + "stage": "J-04", + "node_id": "tests/test_acceptance_edges.py::test_real_parser_binding_projection_redelivery_and_primary_forget[projected]", + "original_kind": "real_parser_binding_projection_composition", + "canonical_kind": "projection" + }, + { + "file": "acceptance-supplement.json", + "case": "J29", + "stage": "J-04", + "node_id": "tests/test_acceptance_edges.py::test_real_parser_binding_projection_redelivery_and_primary_forget[add_pending]", + "original_kind": "real_parser_binding_projection_composition", + "canonical_kind": "projection" + }, + { + "file": "acceptance-supplement.json", + "case": "J31", + "stage": "J-04", + "node_id": "tests/test_acceptance_edges.py::test_real_parser_binding_projection_redelivery_and_primary_forget[projected]", + "original_kind": "real_parser_binding_preflight_forget_composition", + "canonical_kind": "projection" + }, + { + "file": "acceptance-supplement.json", + "case": "J31", + "stage": "J-04", + "node_id": "tests/test_acceptance_edges.py::test_real_parser_binding_projection_redelivery_and_primary_forget[add_pending]", + "original_kind": "real_parser_binding_preflight_forget_composition", + "canonical_kind": "projection" + } + ] +} diff --git a/docs/engineering/qualification-review.md b/docs/engineering/qualification-review.md new file mode 100644 index 0000000..d594888 --- /dev/null +++ b/docs/engineering/qualification-review.md @@ -0,0 +1,27 @@ +# Final qualification contract alignment + +This is a source-review record, not a passing execution report. The qualification +runner records actual results separately against a committed candidate and wheel. + +## Preserved requirements + +The map retains 32 cases, all 41 required stages, 100 stage-node associations and +94 unique identities (93 pytest nodes and one separately executed installed smoke). +Case text, node identities, parameter variants, fixture assertions and original +handoff/oracle hashes are unchanged. Source-controlled statuses remain `not_run`. + +## Metadata correction + +The J10 supplement used descriptive evidence labels outside the runner's existing +fixed vocabulary. `evidence-kind-normalization.json` records each translation. +Specific fixture descriptions, assertions and limitations remain with the nodes. +The two reused compound workflow nodes now have one consistent `projection` kind. +No runner allowlist, expected-test denominator or release blocker was weakened. + +## Capability contract correction + +The missing-node smoke now requires the actual typed `Unavailable` exception with +`node_executable_unavailable`. New negative controls reject ordinary filesystem +and attribute errors, unrelated typed failures and the obsolete generic code. +The real installed smoke still runs outside the checkout with Node and optional +provider packages absent; checkout helper tests cannot substitute for it. diff --git a/docs/release-qualification.md b/docs/release-qualification.md new file mode 100644 index 0000000..594afa8 --- /dev/null +++ b/docs/release-qualification.md @@ -0,0 +1,453 @@ +# Release qualification and recovery + +This is a reproducible **checks gate**, not a production certificate. The J08 +worktree contains the baseline library plus qualification tooling and reviewed +J10 test contributions. Final owner sources were exercised in a frozen temporary +composite for mapping review; the supervisor must assemble the actual candidate +and rerun qualification before scenarios receive gate credit. +No peer-worktree result, mocked tool test, or generic pytest exit code establishes +acceptance of the combined candidate. + +The original audit baseline is Git +`dc6877e85b4048f81ce801d8700dfb934277e5f3`: Python 3.12.12 on macOS arm64, +38 tests passing with three expected optional-provider warnings, as recorded by +the supervising baseline run. This document does not reinterpret that result as +validation of new components, other platforms, or production durability. + +## Prepare an offline candidate check + +Use an isolated Python with the reviewed core dependencies and pytest already +installed. Wheel building also needs the existing `pyproject.toml` build +requirements, **setuptools >=68 and wheel**, in this interpreter: build isolation +and network resolution are deliberately disabled. Python 3.12's default venv does +not necessarily include setuptools. Missing prerequisites produce a failed check, +not an automatic package installation or a retry. + +The supervisor has supplied setuptools 84, wheel 0.48 and 31 hashed offline +wheels for the current isolated environment. The previous missing-setuptools +blocker is resolved; this remediation does not install anything or claim an +installed-wheel result. The supervisor runs that path after final assembly. +For another environment, separately supply a reviewed wheelhouse containing the complete +core dependency closure for the target Python/platform. Qualification installs +only into its own fresh temporary venv. It never installs a donor whole package, +Node, Cohere, Neo4j, FAISS, or another user product. Do not put provider credentials +into this environment. No extra Python dependency was added for this tool. + +Portable shell recipes (replace the placeholder paths): + +```sh +JITMIND_PYTHON=/path/to/isolated/bin/python +JITMIND_WHEELHOUSE=/path/to/reviewed-core-wheels + +# Optional prerequisite preparation by the supervisor, offline: +"$JITMIND_PYTHON" -m pip install --no-index --only-binary=:all: \ + --find-links "$JITMIND_WHEELHOUSE" 'setuptools>=68' wheel + +# Run from the candidate checkout. Output must be NEW and outside the checkout. +# No --worktree means dirty source/untracked files are refused. +"$JITMIND_PYTHON" scripts/qualify_jitmind.py run \ + --output /path/to/new-candidate-report \ + --wheelhouse "$JITMIND_WHEELHOUSE" \ + --overall-seconds 900 --command-seconds 180 + +# Developer checks explicitly allow and label an uncommitted worktree: +"$JITMIND_PYTHON" scripts/qualify_jitmind.py run --worktree \ + --output /path/to/new-developer-report \ + --wheelhouse "$JITMIND_WHEELHOUSE" +``` + +The output parent must already exist. The output directory is created exclusively +with mode 0700; reruns need new paths. Reports and logs are never overwritten. +Exit 0 means `checks_only_complete`, 1 means failed/incomplete checks, and 2 means +invalid/unavailable qualification input or setup. **No exit code means production +signoff.** `release_qualified` remains false in this version. + +The fixed suite is: + +1. `python -m pytest -q tests -p scripts.qualify_jitmind`, with explicit checkout + `PYTHONPATH` and third-party pytest plugin autoload disabled. +2. `python -m compileall -q jitmind scripts/qualify_jitmind.py`. +3. `python -m pip wheel --no-index --no-deps --no-build-isolation`, building from a + fresh copy of the pinned source snapshot. Ignored stale build outputs do not + enter this copy. The wheel is retained and hashed in the report. +4. `python -m venv` in a private temporary directory outside the checkout. +5. That venv's `python -I -m pip install --no-index --only-binary=:all:` of the built + wheel and reviewed wheelhouse dependencies. A missing dependency fails; no + network fallback or install into the calling interpreter occurs. +6. That venv's `python -I` executes `tests/test_standalone_install.py` from a + temporary working directory, without `PYTHONPATH`. PATH contains only that + venv's bin directory, so Node cannot be accidentally discovered on host PATH. + +All commands use trusted argv constructors with `shell=False`. Acceptance-map and +imported-report fields never become executable commands. The environment is a +small explicit allowlist; API keys, provider configuration, proxy variables, +PYTHONPATH, pip credentials/config, NODE_OPTIONS and pytest injection settings are +not inherited. The runner gives HOME/TMPDIR private scratch locations. It does +not read user credential files. Repository tests/build code are trusted executable +candidate code; process containment is not an OS sandbox for malicious tests. + +## Standalone installed-package contract + +The smoke can also be run against an actual already installed candidate venv: + +```sh +# Set CHECKOUT before leaving it. The result path must not exist. +CHECKOUT=$PWD +cd /path/to/empty-temporary-directory +env -i LANG=C.UTF-8 PATH=/path/to/candidate-venv/bin \ + /path/to/candidate-venv/bin/python -I \ + "$CHECKOUT/tests/test_standalone_install.py" --installed-smoke \ + /path/to/candidate-venv /path/to/new-installed-results.json +``` + +Prefer the complete runner: it also scrubs provider keys and ties the install to +the freshly built wheel hash. Direct users must supply an equally clean environment. +The smoke asserts `sys.flags.isolated`, the expected venv prefix, a jitmind module +origin inside that venv, absence of checkout from cwd/sys.path, and absence of +Cohere, Neo4j, FAISS and discoverable Node. Socket connections are denied inside +the smoke process, including accidental provider connections. + +It executes actual legacy `MemoryAgent.memorize` and `ResearchAgent.research` +using a deterministic generator, reopens the persisted memory/pages, and checks +retrieved evidence, answer and provenance. No language-model quality claim follows +from this fake generator. If the durable backend is installed, its `diagnostics()` +records actual application connection settings; the separate stdlib probe is +explicitly not a product-storage setting. + +The optional adapter must import without Node. Configuring an absent Node/adapter +path must produce its meaningful typed `Unavailable` capability error; arbitrary +`FileNotFoundError`, `AttributeError`, a failed import, or silent remote fallback +is not acceptance. The corrected J04 constructor raises `CapabilityUnavailable`, +a subtype of `Unavailable`, with `node_executable_unavailable` for a missing or +nonexecutable Node, `adapter_directory_unavailable` for an absent adapter directory, +and `adapter_runner_unavailable` for a missing, unreadable or symlink runner. +Relative configuration paths still raise `ValueError`. Construction does not +start Node, import optional providers or fall back remotely; final owner tests +executed these boundaries successfully in the staged composite. + +The unchanged installed-smoke helper currently accepts only `runtime_unavailable` +or `adapter_unavailable`. Executing that helper against final J04 reproduces an +assertion failure on `node_executable_unavailable`; this is a smoke/product +reason-code contract mismatch, not an unfixed constructor. The baseline-only J08 +checkout also lacks `jitmind.code_context`. Neither checkout helper tests nor the +staged helper reproduction establish installed-wheel qualification. No install +was performed in the final mapping task, and J32 remains unrun. The supervisor +must resolve the reason-code contract explicitly and rerun the isolated smoke; +this task does not change its assertions. + +Pytest's two checks in this file verify the guard and the fake-generator fixture +**from the checkout**. They cannot satisfy J32. J32's separate exact node identity +is `tests/test_standalone_install.py::installed_smoke`; only the runner's installed +artifact can supply its result. + +## Acceptance and evidence schema + +`docs/engineering/acceptance-map.json` retains the derived handoff's **32 cases and +41 required ticket stages**. Each case has one owner. Repeated stages remain +required, including J02 failure propagation, J03/J04 scope/path/cache checks, +J02/J04/J05 outbox chains, and J02/J04/J05/J06 forget/retention chains. + +The map carries the supplied `source_handoff_sha256`, the digest of the derived +map itself, and the frozen temporal oracle's digest and seven expected answers: +3, 3, 4, 3, 4, 5, 3. Latest-perspective Jan20 is 4; equal instants with timezone +offsets agree; conflicting single-valued overlaps are errors. The legacy naive +API is unchanged. This derived map is not the original full-fixture handoff and +is not execution evidence or a signature. + +Every case/stage stays `status: not_run` in source control. Nodes contain: + +- `node_id`: exact pytest ID including every parameter suffix, or the distinct + installed-smoke identity. Prefix matches and inferred test names do not count. +- `kind`: real storage, injected storage fault, real parser, migration, projection, + public API, temporal oracle, or installed package. Tool/qualification tests and + mocked-tool records cannot become product acceptance. +- `source`: repository-relative source file and SHA-256. +- `fixtures`: nonempty source-attested artifact references. Existing peer tests + construct synthetic deterministic fixtures in their test source; they are + labeled as such and do not claim original full-fixture execution. + +Final mappings are based on actual owner-source definitions and staged execution, +not inherited peer pass reports. Changing a test source requires reviewing its +assertions and refreshing its hash. `nodes: []` or +`additional_mapping_required: true` still blocks a stage. All eight previous +mapping gaps now have the exact J10 supplement nodes, retaining parameters, +fixture intent, kinds and `not_run` status. The map has 100 stage-node associations +and 94 unique identities: 93 pytest nodes and the distinct installed smoke. +Every original mapped node remains, with 14 additional atomic durability checks +using J07's legitimate v2 checkpoint adaptation. The temporal oracle is unchanged. + +Mapping coverage is separate from schema compatibility. The unchanged runner +rejects eight detailed J10 kinds with `unsupported_evidence_kind`; the two +compound nodes also have different kinds in J29 and J31, triggering the runner's +`conflicting_node_kind` rule. No kind was silently normalized and no runner or +schema was changed to accept them. These are genuine unresolved qualification +contract blockers. The supervisor must review a schema-compatible representation +that retains the fixture distinctions before rerunning the combined candidate. +Never delete a required stage to match a smaller denominator. This gate implements +no implicit feature exclusions: +any proposed exclusion needs a separate reviewed scope record and a reviewed gate +change that preserves the original denominator and states the exclusion. + +The report directory contains: + +| Artifact | Meaning | +| --- | --- | +| `report.json` | `jitmind.qualification/v2`: candidate Git SHA, dirty flag, complete source snapshot digest/roster, mode, host facts, fixed command records, package hash, findings and artifact manifest. | +| `acceptance-map.json` | Exact mapping used for this run, hashed by the report. | +| `pytest-results.json` | `jitmind.pytest/v2`: selected IDs/count, setup/call/teardown outcomes, per-node source digest/kind, pytest exit, phase counts, session counters and independent collection artifact hash. | +| `expected-collection.json` | `jitmind.collection/v1`: candidate identity, every item observed before deselection, final selected IDs, deselected IDs, collection failures/skips and filtering flag. Exclusively written at collection finish, before runtime results. | +| `installed-results.json` | Separate installed-package checks, origin relative to its venv, dependency versions and connection probes, when installation reached this step. | +| `sources/` | Every live entry in the candidate snapshot, including non-code fixtures and configuration. Deleted entries have null digests and no artifact. Peer files are never substituted. | +| `*.log`, `*.whl` | Bounded command logs and the built candidate wheel, if build succeeded. | +| `verdict.json` | Recomputed per-case/stage outcomes, counts, findings and release blockers. | + +Missing, failed, skipped, timed-out, incomplete-phase, wrong-source, or unmapped +nodes cannot pass. Empty pytest collection cannot pass. An unavailable collection +has null counts, not fabricated zeros. Known findings survive a checker failing +to run. Truncated logs block success. Unknown performance measurements are null. +All enabled cases must have all required nodes/stages executed and passed. + +The v2 schemas deliberately reject old bundles lacking independent collection +or snapshot evidence; regenerate evidence rather than upgrading a claim in place. +`snapshot_files` is a nonempty sorted list of unique `[relative_path, sha256_or_null]` +pairs. Paths must already be normalized POSIX relative paths. The verifier +recomputes `snapshot_sha256` from UTF-8 `json.dumps(roster, separators=(",", ":"))` +(with Python's default ASCII escaping), then binds every live entry to a verified +`sources/` artifact. Extra sources outside the roster are rejected. Every +runtime record's source hash must agree with that roster; mapped source paths +must also agree with the node's file and the reviewed acceptance map. + +The plugin observes `pytest_itemcollected`, `pytest_deselected` and +`pytest_collectreport`, preserving collection failures and module-level +`skip`/`importorskip`. `-k` (including `pytest.ini addopts`), `-m`, explicit +ignore/deselect, last-failed selection, collect-only and file/node-targeted +invocations cannot complete the fixed suite. Collection IDs must be unique; +selected/deselected sets must partition the original inventory. Runtime phase +counters and pytest's collected/failed counters are checked against the records. +Deleting an unmapped failing record and shrinking runtime collection cannot +change the independently recorded expected inventory. Missing expected records +remain unknown in the full denominator; `collection_count` reports that expected +count and `selected_count` separately reports executed selection. Unavailable +runtime measurements remain null. A collection artifact missing entirely blocks +verification. These checks detect internal contradictions, not a malicious +author rewriting all artifacts consistently or deliberately deceptive test code. + +Reports are strict bounded JSON: duplicate keys, nonfinite numbers (including +exponent overflow), booleans as integers, duplicate cases/tests/artifacts, invalid +SHA formats, missing stages, path traversal/symlink artifacts and modified bytes +are rejected. Externally supplied JUnit/XML is **not imported**. This version +prefers its own pytest plugin records; adding an XML importer would require +separate hardening and tests. No imported artifact triggers network access or +command execution. + +Validate an existing bundle against the **trusted map in the current checkout** +and independently selected expected candidate identities: + +```sh +"$JITMIND_PYTHON" scripts/qualify_jitmind.py verify /path/to/report \ + --candidate-sha \ + --snapshot-sha +``` + +Input JSON is capped at 8 MiB; each artifact at 128 MiB; source and evidence +rosters at 10,000 files and 512 MiB in aggregate. File hashing/copy loops also +check the overall deadline; blocking host filesystem calls are not hard real-time. +`bounded_copy(source, destination, expected_hash=None, deadline=None)` prechecks +regular-file size, opens without following a symlink, pins inode/device/size and +nanosecond modification/change times, and streams unbuffered reads of at most the +remaining limit plus one byte. Oversize/growth, replacement, metadata changes or +an expected-hash mismatch fail and remove partial output. Destinations are +exclusive. Snapshot/build/evidence copies and wheel acquisition all use this +helper; installation uses the copied, hashed wheel. This is a stable-file check, +not a filesystem snapshot or protection against a malicious privileged writer. + +The API `evaluate(trusted_mapping, report, artifact_root)` likewise expects its +first argument from the reviewer, not an untrusted report. Hashes establish byte +consistency, not authorship. A malicious party can manufacture mutually consistent +JSON and hashes; independent execution and authenticated review remain necessary. +Imported claims of release approval are ignored. Keep raw logs private: they may +contain trusted test diagnostics or local paths. Public errors are fixed codes; +unknown imported findings are retained as a sanitized finding marker. Redacted +sharing copies are new artifacts, not silently edited originals. + +## Runtime bounds and operational limits + +Each command has both a relative timeout and the shared absolute suite deadline. +Stdout/stderr are drained concurrently before either can fill a pipe; logs are +capped during capture (2 MiB per command), not sliced after an unbounded capture. +Overflow fails the command. Cancellation/timeout kills the owned POSIX process +group and reaps the direct child, including when a child inherited pipes after +the leader exited. Both pipes are closed on every cleanup path. `run_command` +returns `status: cancelled` for SIGINT/KeyboardInterrupt and SIGTERM. During a +main-thread call, a scoped SIGTERM handler sets the cancellation event and the +previous handler is restored afterward. A caller in another thread never changes +process-global signal handlers: its owner must forward cancellation through the +explicit `threading.Event`. There is no process-wide handler installed on import. +An active command wrapper can therefore return normally with a cancelled result; +the CLI retains incomplete/cancelled evidence rather than claiming success. +SIGKILL cannot be trapped, and interpreter/host death cannot promise cleanup. +There is also no scoped signal handler between commands. A supervisor requiring +whole-lifetime containment must own that process lifecycle. The OS reaps orphan grandchildren. Commands with unknown +external effects are never retried. A process deliberately escaping its group +is outside this trusted-command containment model. + +The process runner and new legacy locks are POSIX-only. Windows is explicitly +unsupported, not validated production Windows. Existing core Ubuntu Python +3.10/3.11/3.12 CI remains unchanged; no Windows skip matrix or unverified platform +job was introduced. macOS integration/platform matrix signoff remains separate. + +Optional parser qualification requires Node >=20 and exactly tree-sitter 0.21.1 / +tree-sitter-python 0.21.0 in the reviewed extracted `adapters/graft` runtime. Use +`npm ci --ignore-scripts --no-audit --no-fund` only as a separate reviewed runtime +provisioning step; never install/run the whole donor package's lifecycle hooks. +Pass `--node-binary /absolute/path/to/node` to the runner on systems where it is +outside the allowlisted PATH. That runtime is supplied only to checkout parser +tests, never to the standalone smoke. A native parser probe must actually run; +installation success alone is insufficient. Python AST is the first-release +subset; other languages and whole-donor parity are not claimed. + +SQLite 3.51.2 in the supplied environment has the noted WAL-reset issue. The new +local stores use DELETE/FULL; WAL requires a patched version accepted by the +storage component. Do not globally enable WAL or infer safe settings from the +qualification runner's unrelated stdlib connection. Review actual application +`diagnostics()` and failure/recovery tests for each candidate. + +| Component disabled/unavailable | Required behavior and limit | +| --- | --- | +| Durable authority | Legacy format remains available by explicit configuration; arbitrary legacy memory/page pairs do not become transactional. | +| Structural adapter | Ordinary authorized memory continues independently; code evidence reports unavailable, with no other-product or remote fallback. | +| Code bindings | Preserve historical facts; unknown/stale source does not expire a fact or manufacture a current binding. | +| Preflight | Explicit no-match/deferred behavior; obligations remain open; imported law labels confer no trust. | +| Checkpoint ledger | Legacy state remains unvalidated; iteration lists do not become closed event ranges. | +| Providers/optional retrievers | No live-provider qualification in this gate; fake-generator success is only local public-API behavior. | + +## Cutover and rollback drill + +Perform this against disposable copies before any real cutover. The supervisor +records actual commands, candidate hashes, settings, data digests and outcomes in +a new evidence bundle; these instructions themselves are not a successful drill. + +1. Inventory source formats, exact namespace/repository identities, outstanding + operation keys and writer processes. Stop **all** old writers and confirm + quiescence. J01's persistent flock strategy cannot mix with old O_EXCL writers; + never unlink a live lock file or steal ownership based on age. +2. Preserve untouched legacy files and a manifest of their hashes. Corrupt or + ambiguous input is a blocking finding, not an empty successful migration. + Use J02 `stage_legacy(source, quiesced=True)` and explicitly import into an empty + namespace of a new SQLite authority. Quiescence is an operator responsibility, + not a property proven by that boolean. +3. Compare stable fact IDs, page aliases/provenance, temporal/version histories, + namespace visibility, queries, receipts and outbox state. Record the explicit + old-to-new ID mapping; never infer page aliases from basenames/list positions. + Refuse unknown custom stores as transactional backends. +4. Exercise writes before COMMIT and after COMMIT/before acknowledgement with + actual tests. Reconcile uncertain acknowledgements using the same operation + key and payload. Do not allocate a new key or repeat a provider/tool effect + merely because the acknowledgement was lost. +5. Cut over one quiesced configuration to the new authority; do not dual write. + Exercise public ingest/research and scoped current-source filtering. Deliver + duplicate/out-of-order projection events; verify primary durability, current + authority filtering, and visible lag. External consumers need their own + delivery ledger, not the built-in reference projection's delivered bit. +6. Commit a distinct **post-cutover write**. Stop candidate writers, take a fresh + SQLite API backup including receipts/aliases/history/outbox, and restore it + with `SQLiteDurableStore.restore(backup, new_destination)`. Never copy only a + live main database file or overwrite the current authority with an old backup. +7. Verify that the restored candidate-era write and its receipt survive, replay + the same key without regeneration, and compare queries/aliases/counts. Restart + bindings/projections explicitly: code snapshots are process-local and require + rebuilding; retained metadata is not proof of current code validation. +8. A rollback to **old application code** is not equivalent to restoring a new + SQLite backup. Preserve the latest candidate authority, reconcile every + candidate-era write, and require a reviewed export/mapping compatible with the + old format before routing traffic. If none exists, keep writers stopped and + choose a forward repair or compatible candidate restore. Never silently lose + post-cutover writes by switching back to the pre-cutover files. +9. Checkpoint v2 hashed IDs also need explicit mapping for old consumers. Back up + exact stored IDs, stop old/new writers, and do not guess sanitized aliases. + Closed-range replay requires the original events/source digest; summaries do + not replace missing events. Replay is not restoration of external side effects. +10. Record remaining limits: single-host local filesystem only; injected faults + and process kills are not physical power-loss tests; historical data/backups + may remain after logical forget; grants must be reissued after restart. + +## Release decision and performance claims + +`checks_only_complete` and `release_qualified` are separate. Even a fully passing +checks bundle retains independent signoff, platform matrix, provider evaluation, +power-loss drill and benchmark-comparison blockers. This tool has no flag that +silently converts these unrun dimensions into approval. A release owner must +review and scope them explicitly in a separate authenticated decision record. + +No benchmark runner or donor comparison is claimed here. `benchmark_measurement` +is null. Future measurements must freeze datasets, source hashes, configs, +provider/token budgets and the complete unique baseline/candidate grid. Preserve +failed/inconclusive cells and raw bounded logs. Label synthetic workloads; never +convert unauthorized reads, lost writes, or poor anchors into a favorable speed +score. Retrieval correctness, durability and anchor quality stay separate from +performance, and unrun comparisons remain `not_run`. + +## Final mapping review and staged execution + +The earlier worker and remediation observations below are historical; they are +not final assembled-candidate results. The final mapping review closed the eight +source-mapping gaps without removing cases, required stages or existing nodes: + +| Case/stage | Exact added J10 node associations | +| --- | ---: | +| J02 / J-01: real legacy publication ENOSPC | 5 | +| J02 / J-02: native SQLite capacity exhaustion | 1 | +| J04 / J-02: real process-exit boundaries | 5 | +| J16 / J-06: parser, bindings and open-work fallback | 2 | +| J22 / J-07: tool result/cancel/timeout boundaries | 3 | +| J25 / J-02: corrupt migration, faults and process exits | 8 | +| J29 / J-04: parser/binding/projection replay composition | 2 | +| J31 / J-04: forget, retained metadata and open obligation | 2 | + +These are 28 associations for 26 unique nodes, including 10 J10-authored edge +cases and 16 reused owner cases. J08 adapted only the compound fixture's explicit +`DurableBindingAuthority` configuration; all forget, obligation and authorized +raw-source assertions remain. Memory forget hides derived bodies and leaves the +obligation open; authorized source files remain readable. Physical erasure and +backup purge are not asserted. + +The frozen composite used J01 at `b3fe1d51a4cb98ea2ddce7e94fd3f732010b623d`, +corrected `delivery/J02` through `delivery/J05`, and final `worktrees/J06`, +`worktrees/J07`, `worktrees/J09`, relative to the orchestration root. Only owned +files were overlaid; stale dependency copies were excluded. The provisioned local +Node/tree-sitter adapter came from `delivery/J04/adapters/graft`. + +Actual full staged execution: **861 collected; 860 passed, 1 failed, 0 skipped**. +The sole failure is the unchanged qualification test rejecting the supplement's +preserved evidence kinds. All **93 mapped pytest identities** passed all three +phases, including **26/26 supplement nodes**. Independent collection recorded no +filtering, deselection or collection errors/skips. These raw diagnostic records +are not an accepted qualification bundle; their kinds remain `unmapped` because +the preserved kind conflicts cannot be certified by this runner. No passing +case/stage status or release approval was synthesized from the raw outcomes. + +Separate diagnostic reproductions demonstrate the compound kind conflict and +the unchanged smoke reason-code mismatch. At that diagnostic stage, J32 installed execution was +unrun and no full gate result was credited. See [the contract alignment record](engineering/qualification-review.md) +for exact commands, source ownership, copied-test inventory and remaining limits. + +## Historical J08 remediation verification record + +The initial regression run reproduced 11 failures and one already-passing SIGINT +case. Final verification: **96 focused helper tests passed** and **134 full checkout +tests passed**, each with three expected optional-provider warnings. Compile and +Ruff E9/F passed; mypy is unavailable. Exact commands and controlled probe results +are in the private historical remediation record. Prior historical counts were 59 helper tests and 97 full checkout +tests; their missing-setuptools build failure is historical and no longer an +environment blocker. No installation, live provider call, peer write, commit or +publication is part of this remediation. Release requirements remain unchanged. + + +## Final delivery contract corrections + +The final delivery normalizes supplement labels to the existing fixed evidence +vocabulary and binds the missing-runtime smoke to the implemented typed reason. +No case, stage, assertion or release blocker was removed. See +[qualification-review.md](engineering/qualification-review.md) and the adjacent +normalization ledger. Re-run against the actual committed candidate; historical +worker counts are not the final candidate result. diff --git a/scripts/qualify_jitmind.py b/scripts/qualify_jitmind.py new file mode 100644 index 0000000..2cf9a1e --- /dev/null +++ b/scripts/qualify_jitmind.py @@ -0,0 +1,1436 @@ +#!/usr/bin/env python3 +"""Offline, fail-closed candidate checks. Imported evidence never executes commands. + +This module also supplies a pytest plugin recording exact node IDs and all phases. +Only the CLI's fixed command constructors execute tools; map data is never argv. +""" + +from __future__ import annotations + +import argparse +from contextlib import contextmanager +import hashlib +import importlib.metadata +import json +import math +import os +from pathlib import Path +import platform +import re +import selectors +import signal +import sqlite3 +import stat +import subprocess +import sys +import tempfile +import threading +import time +from typing import Any + +MAX_JSON = 8 * 1024 * 1024 +MAX_LOG = 2 * 1024 * 1024 +MAX_ARTIFACT = 128 * 1024 * 1024 +MAX_TOTAL_BYTES = 512 * 1024 * 1024 +MAX_FILES = 10000 +SHA256 = re.compile(r"[0-9a-f]{64}\Z") +GIT_SHA = re.compile(r"[0-9a-f]{40}\Z") +KINDS = { + "real_storage", + "injected_storage_fault", + "real_parser", + "public_api", + "migration", + "projection", + "installed_package", + "temporal_oracle", +} +COMMANDS = {"pytest", "compile", "wheel", "venv", "install", "smoke"} +SMOKE_NODE = "tests/test_standalone_install.py::installed_smoke" +SMOKE_CHECKS = { + "isolated_origin", + "optional_dependencies_absent", + "legacy_memory_research", + "optional_adapter_import", + "missing_adapter_capability", +} +RELEASE_BLOCKERS = [ + "independent_signoff_not_recorded", + "platform_matrix_not_run", + "provider_checks_not_run", + "power_loss_drill_not_run", + "benchmark_comparisons_not_run", +] + + +class EvidenceError(ValueError): + """Messages are fixed reason codes, never input payloads or paths.""" + + +def require(condition: Any, code: str) -> None: + if not condition: + raise EvidenceError(code) + + +def strict_json(path: Path, limit: int = MAX_JSON) -> Any: + def pairs(items): + result = {} + for key, value in items: + require(key not in result, "duplicate_json_key") + result[key] = value + return result + + def constant(_value): + raise EvidenceError("nonfinite_json") + + try: + require(path.is_file() and not path.is_symlink(), "invalid_json_artifact") + with path.open("rb") as stream: + raw = stream.read(limit + 1) + require(len(raw) <= limit, "input_too_large") + value = json.loads(raw, object_pairs_hook=pairs, parse_constant=constant) + + # 1e999 is parsed as infinity without invoking parse_constant. + def finite(item): + if isinstance(item, float): + require(math.isfinite(item), "nonfinite_json") + elif isinstance(item, dict): + for val in item.values(): + finite(val) + elif isinstance(item, list): + for val in item: + finite(val) + + finite(value) + return value + except (OSError, UnicodeError, json.JSONDecodeError, RecursionError): + raise EvidenceError("invalid_json_artifact") from None + + +def digest(path: Path, *, deadline: float | None = None) -> str: + require(path.is_file() and not path.is_symlink(), "artifact_missing_or_symlink") + require(path.stat().st_size <= MAX_ARTIFACT, "artifact_too_large") + result = hashlib.sha256() + total = 0 + with path.open("rb") as stream: + for block in iter(lambda: stream.read(65536), b""): + if deadline is not None: + require(time.monotonic() < deadline, "overall_deadline") + total += len(block) + require(total <= MAX_ARTIFACT, "artifact_too_large") + result.update(block) + return result.hexdigest() + + +def bounded_copy( + source: Path, + destination: Path, + *, + expected_hash: str | None = None, + deadline: float | None = None, +) -> str: + """Exclusive, bounded copy of a stable regular file; remove partial output. + + Pin the opened inode and reject replacement or metadata changes during copying. + Hash checks bind bytes when copying a previously inventoried source. + """ + + def identity(info): + return ( + info.st_dev, + info.st_ino, + info.st_mode, + info.st_size, + info.st_mtime_ns, + info.st_ctime_ns, + ) + + before = source.lstat() + require(stat.S_ISREG(before.st_mode), "artifact_missing_or_symlink") + require(before.st_size <= MAX_ARTIFACT, "artifact_too_large") + created = False + try: + fd = os.open(source, os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK) + with os.fdopen(fd, "rb", buffering=0) as src: + opened = os.fstat(src.fileno()) + require(identity(opened) == identity(before), "source_changed_during_copy") + total = 0 + hasher = hashlib.sha256() + with destination.open("xb") as dst: + created = True + while True: + if deadline is not None: + require(time.monotonic() < deadline, "overall_deadline") + block = src.read(min(65536, MAX_ARTIFACT - total + 1)) + if not block: + break + total += len(block) + require(total <= MAX_ARTIFACT, "artifact_too_large") + hasher.update(block) + dst.write(block) + require( + identity(os.fstat(src.fileno())) == identity(opened) + and identity(source.lstat()) == identity(opened), + "source_changed_during_copy", + ) + require(total == opened.st_size, "source_changed_during_copy") + result = hasher.hexdigest() + require( + expected_hash is None or result == expected_hash, + "source_hash_mismatch", + ) + return result + except BaseException: + if created: + destination.unlink(missing_ok=True) + raise + + +@contextmanager +def command_signals(cancel: threading.Event): + """Temporarily translate SIGTERM on the main thread; never change worker signals.""" + installed = threading.current_thread() is threading.main_thread() + if installed: + previous = signal.getsignal(signal.SIGTERM) + signal.signal(signal.SIGTERM, lambda _signum, _frame: cancel.set()) + try: + yield + finally: + if installed: + signal.signal(signal.SIGTERM, previous) + + +def relative_file(root: Path, name: str) -> Path: + require( + isinstance(name, str) and bool(name) and "\\" not in name, + "invalid_artifact_path", + ) + path = Path(name) + require(not path.is_absolute() and ".." not in path.parts, "invalid_artifact_path") + current = root.resolve() + for part in path.parts: + current = current / part + require(not current.is_symlink(), "artifact_symlink") + require(current.is_relative_to(root.resolve()), "artifact_escape") + return current + + +def artifact(root: Path, name: str) -> dict: + path = relative_file(root, name) + return {"path": name, "sha256": digest(path), "bytes": path.stat().st_size} + + +def verify_artifact(root: Path, ref: dict) -> Path: + require(isinstance(ref, dict), "invalid_artifact") + require( + isinstance(ref.get("sha256"), str) and SHA256.fullmatch(ref["sha256"]), + "invalid_artifact_digest", + ) + require( + type(ref.get("bytes")) is int and 0 <= ref["bytes"] <= MAX_ARTIFACT, + "invalid_artifact_size", + ) + path = relative_file(root, ref.get("path")) + require( + digest(path) == ref["sha256"] and path.stat().st_size == ref["bytes"], + "artifact_modified", + ) + return path + + +def write_json(path: Path, value: Any) -> None: + data = json.dumps(value, indent=2, sort_keys=True, allow_nan=False) + "\n" + require(len(data.encode()) <= MAX_JSON, "report_too_large") + with path.open("x", encoding="utf-8") as stream: + stream.write(data) + + +def clean_env(home: Path, python: Path, checkout: Path | None = None) -> dict: + """Allowlist: do not inherit credentials, proxy config, plugins, or PYTHONPATH.""" + env = { + "HOME": str(home), + "TMPDIR": str(home), + "LANG": "C.UTF-8", + "LC_ALL": "C.UTF-8", + "PATH": str(python.parent) + os.pathsep + "/usr/bin:/bin", + "PYTHONNOUSERSITE": "1", + "PYTHONDONTWRITEBYTECODE": "1", + "PIP_CONFIG_FILE": os.devnull, + "PIP_DISABLE_PIP_VERSION_CHECK": "1", + "PIP_NO_INDEX": "1", + "PYTEST_DISABLE_PLUGIN_AUTOLOAD": "1", + } + if checkout is not None: + env["PYTHONPATH"] = str(checkout) + return env + + +def run_command( + argv: list[str], + *, + cwd: Path, + env: dict, + log: Path, + deadline: float, + timeout: float = 120, + max_bytes: int = MAX_LOG, + cancel: threading.Event | None = None, +) -> dict: + """Trusted internal argv only. Drain both pipes; bound storage before capture. + + POSIX owned process groups include children inheriting pipes after leader exit. + Kill the group even on successful leader exit; never retry a command. + """ + require(os.name == "posix", "process_groups_unsupported_platform") + require( + isinstance(argv, list) + and bool(argv) + and all(isinstance(arg, str) for arg in argv), + "invalid_argv", + ) + require(type(max_bytes) is int and max_bytes > 0, "invalid_log_budget") + require( + type(timeout) in (int, float) and math.isfinite(timeout) and timeout > 0, + "invalid_timeout", + ) + require( + type(deadline) in (int, float) and math.isfinite(deadline), "invalid_deadline" + ) + started = time.monotonic() + end = min(deadline, started + timeout) + outcome = "not_run" + emitted = 0 + proc = None + cancel = cancel if cancel is not None else threading.Event() + with command_signals(cancel), log.open("xb") as output: + try: + if cancel is not None and cancel.is_set(): + outcome = "cancelled" + elif started >= end: + outcome = "timeout" + else: + proc = subprocess.Popen( + argv, + cwd=cwd, + env=env, + shell=False, + stdin=subprocess.DEVNULL, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + start_new_session=True, + ) + outcome = "passed" + with selectors.DefaultSelector() as selector: + for pipe in (proc.stdout, proc.stderr): + os.set_blocking(pipe.fileno(), False) + selector.register(pipe, selectors.EVENT_READ) + while selector.get_map() or proc.poll() is None: + if cancel is not None and cancel.is_set(): + outcome = "cancelled" + break + if time.monotonic() >= end: + outcome = "timeout" + break + for key, _ in selector.select( + min(0.02, max(0, end - time.monotonic())) + ): + chunk = os.read(key.fileobj.fileno(), 16384) + if not chunk: + selector.unregister(key.fileobj) + continue + room = max_bytes - emitted + output.write(chunk[:room]) + emitted += min(room, len(chunk)) + if len(chunk) > room: + outcome = "output_limit" + break + if outcome != "passed": + break + if outcome == "passed" and proc.poll() != 0: + outcome = "failed" + except KeyboardInterrupt: + outcome = "cancelled" + except OSError: + outcome = "launch_error" + finally: + if proc is not None: + try: + os.killpg(proc.pid, signal.SIGKILL) + except ProcessLookupError: + pass + proc.wait() + proc.stdout.close() + proc.stderr.close() + return { + "status": outcome, + "exit_code": None if proc is None else proc.returncode, + "elapsed_seconds": time.monotonic() - started, + "log_bytes": emitted, + "log_truncated": outcome == "output_limit", + } + + +def candidate_identity( + repo: Path, scratch: Path, python: Path, deadline: float +) -> dict: + def git(name, args): + log = scratch / (name + ".log") + result = run_command( + ["/usr/bin/git", "-c", "core.fsmonitor=false", *args], + cwd=repo, + env=clean_env(scratch, python), + log=log, + deadline=deadline, + timeout=20, + max_bytes=MAX_JSON, + ) + require(result["status"] == "passed", "git_identity_unavailable") + return log.read_bytes() + + sha = git("head", ["rev-parse", "HEAD"]).decode().strip() + require(GIT_SHA.fullmatch(sha), "invalid_candidate_sha") + # --porcelain suppresses warning output only on standard installations; fail closed otherwise. + status = git("status", ["status", "--porcelain=v1", "-z", "--untracked-files=all"]) + paths = git( + "files", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"] + ) + records = [] + source_names = sorted(set(paths.split(b"\0")) - {b""}) + require(len(source_names) <= MAX_FILES, "too_many_source_files") + source_bytes = 0 + for raw in source_names: + require(time.monotonic() < deadline, "overall_deadline") + name = raw.decode("utf-8") + path = relative_file(repo, name) + if path.exists(): + source_bytes += path.stat().st_size + require(source_bytes <= MAX_TOTAL_BYTES, "source_snapshot_too_large") + records.append( + [name, digest(path, deadline=deadline) if path.exists() else None] + ) + snapshot = hashlib.sha256( + json.dumps(records, separators=(",", ":")).encode() + ).hexdigest() + return { + "git_sha": sha, + "dirty": bool(status), + "snapshot_sha256": snapshot, + "snapshot_files": records, + } + + +def snapshot_roster(identity: dict) -> dict: + records = identity.get("snapshot_files") + require( + isinstance(records, list) and bool(records) and len(records) <= MAX_FILES, + "invalid_snapshot_roster", + ) + names = [] + for record in records: + require(isinstance(record, list) and len(record) == 2, "invalid_snapshot_entry") + name, sha = record + require( + isinstance(name, str) + and bool(name) + and "\\" not in name + and not Path(name).is_absolute() + and ".." not in Path(name).parts + and Path(name).as_posix() == name + and name != ".", + "invalid_snapshot_path", + ) + require( + sha is None or isinstance(sha, str) and SHA256.fullmatch(sha), + "invalid_snapshot_source_digest", + ) + names.append(name) + require(names == sorted(set(names)), "snapshot_roster_not_normalized") + expected = hashlib.sha256( + json.dumps(records, separators=(",", ":")).encode() + ).hexdigest() + require(identity["snapshot_sha256"] == expected, "snapshot_digest_mismatch") + return dict(records) + + +def validate_map(mapping: dict) -> list[dict]: + require( + isinstance(mapping, dict) + and mapping.get("schema") == "jitmind.acceptance-map/v1", + "invalid_map_schema", + ) + require( + isinstance(mapping.get("source_handoff_sha256"), str) + and SHA256.fullmatch(mapping["source_handoff_sha256"]), + "invalid_handoff_digest", + ) + cases = mapping.get("cases") + require(isinstance(cases, list) and bool(cases), "empty_cases") + ids = set() + for case in cases: + require( + isinstance(case, dict) + and isinstance(case.get("case_id"), str) + and re.fullmatch(r"J[0-9]{2}", case["case_id"]), + "invalid_case", + ) + require(case["case_id"] not in ids, "duplicate_case") + ids.add(case["case_id"]) + required = case.get("required_in_tickets") + require( + isinstance(required, list) + and required + and all( + isinstance(s, str) and re.fullmatch(r"J-[0-9]{2}", s) for s in required + ) + and len(set(required)) == len(required), + "invalid_required_stages", + ) + require( + case.get("ticket") in required and case.get("status") == "not_run", + "invalid_case_owner_or_status", + ) + stages = case.get("stages") + require( + isinstance(stages, list) and len(stages) == len(required), "missing_stage" + ) + require({s.get("stage_id") for s in stages} == set(required), "missing_stage") + for stage in stages: + require(stage.get("status") == "not_run", "map_is_not_execution_evidence") + require( + type(stage.get("additional_mapping_required", False)) is bool, + "invalid_mapping_gap", + ) + nodes = stage.get("nodes") + require(isinstance(nodes, list), "invalid_nodes") + seen = set() + for node in nodes: + node_id = node.get("node_id") + require( + isinstance(node_id, str) and node_id and node_id not in seen, + "duplicate_or_invalid_node", + ) + require( + node_id.startswith("tests/") + and ".." not in node_id.split("::")[0].split("/"), + "invalid_test_path", + ) + require( + not node_id.startswith("tests/test_qualification") + and ( + not node_id.startswith("tests/test_standalone_install.py::") + or node_id == SMOKE_NODE + ), + "tool_test_is_not_acceptance", + ) + seen.add(node_id) + require(node.get("kind") in KINDS, "unsupported_evidence_kind") + require( + isinstance(node.get("source"), dict) and node.get("fixtures"), + "missing_source_or_fixture", + ) + for ref in [node["source"], *node["fixtures"]]: + require( + isinstance(ref, dict) + and isinstance(ref.get("path"), str) + and isinstance(ref.get("sha256"), str) + and SHA256.fullmatch(ref["sha256"]), + "invalid_source_ref", + ) + return cases + + +def evaluate(mapping: dict, report: dict, root: Path) -> dict: + """Validate evidence bytes and recompute verdict. No command execution or network. + + A digest verifies consistency, not authorship. External input is never signoff. + Structural errors raise; incomplete/failed checks remain in the denominator. + """ + cases = validate_map(mapping) + require(report.get("schema") == "jitmind.qualification/v2", "invalid_report_schema") + identity = report.get("candidate", {}) + require( + isinstance(identity.get("git_sha"), str) + and GIT_SHA.fullmatch(identity["git_sha"]), + "invalid_candidate_sha", + ) + require( + isinstance(identity.get("snapshot_sha256"), str) + and SHA256.fullmatch(identity["snapshot_sha256"]), + "invalid_snapshot_digest", + ) + roster = snapshot_roster(identity) + require(type(identity.get("dirty")) is bool, "invalid_dirty_flag") + require(report.get("mode") in {"worktree", "release"}, "invalid_run_mode") + require(not identity["dirty"] or report["mode"] == "worktree", "dirty_release") + map_path = verify_artifact(root, report.get("acceptance_map")) + require(strict_json(map_path) == mapping, "map_identity_mismatch") + artifacts = report.get("artifacts") + require(isinstance(artifacts, list), "invalid_artifacts") + require(len(artifacts) <= MAX_FILES, "too_many_artifacts") + refs = {} + artifact_bytes = 0 + for ref in artifacts: + require( + isinstance(ref, dict) + and type(ref.get("bytes")) is int + and ref["bytes"] >= 0, + "invalid_artifact_size", + ) + artifact_bytes += ref["bytes"] + require(artifact_bytes <= MAX_TOTAL_BYTES, "artifacts_too_large") + verify_artifact(root, ref) + require(ref["path"] not in refs, "duplicate_artifact") + refs[ref["path"]] = ref + for name, sha in roster.items(): + ref = refs.get("sources/" + name) + require( + (ref is None if sha is None else ref is not None and ref["sha256"] == sha), + "snapshot_source_mismatch", + ) + require( + all(not name.startswith("sources/") or name[8:] in roster for name in refs), + "source_outside_snapshot", + ) + commands = report.get("commands") + require(isinstance(commands, list), "missing_commands") + command_ids = set() + command_ok = bool(commands) + findings = report.get("findings", []) + require( + isinstance(findings, list) and all(isinstance(f, str) for f in findings), + "invalid_findings", + ) + # Preserve the existence of imported findings without echoing arbitrary payloads. + safe_findings = { + "candidate_wheel_missing", + "candidate_changed_during_checks", + "candidate_final_identity_unavailable", + } + findings = [ + f if f in safe_findings else "retained_external_finding" for f in findings + ] + for cmd in commands: + require( + cmd.get("id") in COMMANDS and cmd["id"] not in command_ids, + "invalid_command_id", + ) + command_ids.add(cmd["id"]) + require( + type(cmd.get("exit_code")) is int or cmd.get("exit_code") is None, + "invalid_exit_code", + ) + require(type(cmd.get("log_truncated")) is bool, "invalid_truncation_flag") + require(cmd.get("log") in refs, "missing_command_log") + command_ok &= ( + cmd.get("status") == "passed" + and cmd.get("exit_code") == 0 + and not cmd["log_truncated"] + ) + command_ok &= command_ids == COMMANDS + require(report.get("test_results") in refs, "missing_test_results") + test_data = strict_json(root / report["test_results"]) + require(test_data.get("schema") == "jitmind.pytest/v2", "invalid_test_schema") + require(test_data.get("candidate") == identity, "test_source_identity_mismatch") + expected_name = report.get("expected_collection") + require(expected_name in refs, "missing_expected_collection") + expected = strict_json(root / expected_name) + require( + expected.get("schema") == "jitmind.collection/v1" + and expected.get("candidate") == identity, + "collection_identity_mismatch", + ) + require( + test_data.get("expected_collection_sha256") == refs[expected_name]["sha256"], + "collection_digest_mismatch", + ) + for field in ("nodes", "selected", "deselected"): + values = expected.get(field) + require( + isinstance(values, list) + and all(isinstance(n, str) for n in values) + and len(values) == len(set(values)), + "duplicate_or_invalid_collection", + ) + require(type(expected.get("filtered")) is bool, "invalid_collection_filter") + collection_reports = expected.get("collection_reports") + require( + isinstance(collection_reports, list) + and all( + isinstance(r, dict) + and isinstance(r.get("node_id"), str) + and r.get("outcome") in {"failed", "skipped"} + for r in collection_reports + ), + "invalid_collection_reports", + ) + require( + set(expected["selected"]).isdisjoint(expected["deselected"]) + and set(expected["nodes"]) + == set(expected["selected"]) | set(expected["deselected"]), + "collection_inventory_mismatch", + ) + collected = test_data.get("collected") + require( + isinstance(collected, list) + and all(isinstance(n, str) for n in collected) + and len(collected) == len(set(collected)), + "duplicate_or_invalid_collection", + ) + available = test_data.get("available", True) + require(type(available) is bool, "invalid_test_availability") + require( + ( + available + and type(test_data.get("collection_count")) is int + and test_data["collection_count"] == len(collected) + ) + or ( + not available + and test_data.get("collection_count") is None + and not collected + ), + "invalid_collection_count", + ) + records = test_data.get("records") + require(isinstance(records, list), "missing_test_records") + by_node = {} + counts = {"passed": 0, "failed": 0, "skipped": 0, "unknown": 0} + for record in records: + node_id = record.get("node_id") + require( + isinstance(node_id, str) + and node_id in collected + and node_id not in by_node, + "duplicate_or_uncollected_test", + ) + source_name = node_id.split("::")[0] + require( + source_name in roster + and roster[source_name] is not None + and record.get("source_sha256") == roster[source_name], + "record_source_mismatch", + ) + phases = record.get("phases") + require( + isinstance(phases, dict) and set(phases) <= {"setup", "call", "teardown"}, + "invalid_phases", + ) + require( + all(p in {"passed", "failed", "skipped"} for p in phases.values()), + "invalid_phase_outcome", + ) + status = ( + "failed" + if "failed" in phases.values() + else "skipped" + if "skipped" in phases.values() + else "passed" + if phases == {"setup": "passed", "call": "passed", "teardown": "passed"} + else "unknown" + ) + require(record.get("status") == status, "false_test_pass") + counts[status] += 1 + by_node[node_id] = record + counts["unknown"] += len((set(collected) | set(expected["nodes"])) - set(by_node)) + phase_counts = { + outcome: sum(p == outcome for r in records for p in r["phases"].values()) + for outcome in ("passed", "failed", "skipped") + } + if available: + counters = test_data.get("phase_counts") + require( + isinstance(counters, dict) + and set(counters) == set(phase_counts) + and all(type(v) is int for v in counters.values()) + and counters == phase_counts, + "inconsistent_plugin_counters", + ) + require( + type(test_data.get("session_testscollected")) is int + and test_data["session_testscollected"] == len(collected) + and type(test_data.get("session_testsfailed")) is int + and test_data["session_testsfailed"] + == phase_counts["failed"] + + sum(r["outcome"] == "failed" for r in collection_reports), + "inconsistent_plugin_counters", + ) + else: + require( + all( + test_data.get(k) is None + for k in ( + "phase_counts", + "session_testscollected", + "session_testsfailed", + ) + ), + "inconsistent_plugin_counters", + ) + tests_ok = ( + available + and collected == expected["selected"] + and set(collected) == set(expected["nodes"]) + and not expected["filtered"] + and not expected["deselected"] + and not collection_reports + and bool(collected) + and counts["passed"] == len(collected) + and test_data.get("exit_code") == 0 + ) + require(type(test_data.get("exit_code")) is int, "invalid_pytest_exit") + if not tests_ok: + findings.append("pytest_incomplete_or_failed") + if not command_ok: + findings.append("fixed_suite_incomplete_or_failed") + package = report.get("package_sha256") + package_ok = ( + isinstance(package, str) + and SHA256.fullmatch(package) + and any( + name.endswith(".whl") and ref["sha256"] == package + for name, ref in refs.items() + ) + ) + if not package_ok: + findings.append("candidate_wheel_unverified") + installed = None + if "installed-results.json" in refs: + installed = strict_json(root / "installed-results.json") + require( + installed.get("schema") == "jitmind.installed-smoke/v1", + "invalid_smoke_schema", + ) + checks = installed.get("checks") + require( + isinstance(checks, dict) and set(checks) == SMOKE_CHECKS, + "invalid_smoke_checks", + ) + require(installed.get("node_id") == SMOKE_NODE, "invalid_smoke_identity") + require( + type(installed.get("provider_calls")) is int + and installed["provider_calls"] == 0, + "invalid_smoke_provider_count", + ) + smoke_ok = ( + package_ok + and installed.get("status") == "passed" + and all(s == "passed" for s in checks.values()) + ) + by_node[SMOKE_NODE] = { + "kind": "installed_package", + "source_sha256": installed.get("source_sha256"), + "status": "passed" if smoke_ok else "failed", + } + if installed is None or by_node[SMOKE_NODE]["status"] != "passed": + findings.append("installed_smoke_incomplete") + require(report.get("benchmark_measurement") is None, "unreviewed_benchmark_claim") + outcomes = [] + for case in cases: + stages = [] + for stage in case["stages"]: + statuses = [] + for node in stage["nodes"]: + source_ok = node["node_id"].split("::")[0] == node["source"]["path"] + for ref in [node["source"], *node["fixtures"]]: + name = "sources/" + ref["path"] + source_ok &= name in refs and refs[name]["sha256"] == ref["sha256"] + record = by_node.get(node["node_id"]) + if not source_ok: + status = "source_unverified" + elif not record: + status = "not_run" + elif record.get("kind") != node["kind"]: + status = "evidence_kind_mismatch" + elif record.get("source_sha256") != node["source"]["sha256"]: + status = "source_unverified" + else: + status = record["status"] + statuses.append(status) + stages.append( + { + "stage_id": stage["stage_id"], + "node_results": statuses, + "status": "passed" + if statuses + and not stage.get("additional_mapping_required", False) + and all(s == "passed" for s in statuses) + else "inconclusive", + } + ) + outcomes.append( + { + "case_id": case["case_id"], + "stages": stages, + "status": "passed" + if all(s["status"] == "passed" for s in stages) + else "inconclusive", + } + ) + complete = ( + tests_ok + and command_ok + and not findings + and all(c["status"] == "passed" for c in outcomes) + ) + return { + "checks_only_complete": bool(complete), + "release_qualified": False, + "evidence_authorship": "digest_consistency_only_not_signer_identity", + "case_count": len(cases), + "stage_count": sum(len(c["stages"]) for c in cases), + "passed_cases": sum(c["status"] == "passed" for c in outcomes), + "test_counts": counts if available else dict.fromkeys(counts), + "collection_count": len(expected["nodes"]) if available else None, + "selected_count": len(collected) if available else None, + "cases": outcomes, + "findings": findings, + "release_blockers": RELEASE_BLOCKERS + + (["worktree_candidate"] if report["mode"] == "worktree" else []), + "benchmark_measurement": None, + } + + +# Fixed pytest plugin. These hooks only activate in an authorized runner session. +_SESSION: dict = {} + + +def pytest_sessionstart(session): + context = os.environ.get("JITMIND_QUALIFICATION_CONTEXT") + if context: + _SESSION.clear() + _SESSION.update(strict_json(Path(context))) + _SESSION["records"] = {} + _SESSION["collected"] = [] + _SESSION["nodes"] = [] + _SESSION["deselected"] = [] + _SESSION["collection_reports"] = [] + _SESSION["expected_path"] = str( + Path(_SESSION["output"]).with_name("expected-collection.json") + ) + + +def pytest_itemcollected(item): + if _SESSION: + _SESSION["nodes"].append(item.nodeid) + + +def pytest_deselected(items): + if _SESSION: + _SESSION["deselected"].extend(item.nodeid for item in items) + + +def pytest_collectreport(report): + if _SESSION and report.outcome != "passed": + _SESSION["collection_reports"].append( + {"node_id": report.nodeid, "outcome": report.outcome} + ) + + +def collection_record(session): + options = session.config.option + filtered = any( + getattr(options, name, None) + for name in ( + "keyword", + "markexpr", + "deselect", + "ignore", + "ignore_glob", + "lf", + "ff", + "collectonly", + ) + ) + # Fixed runner invokes the full tests directory. Keep arbitrary diagnostic runs + # observable but never credit a file/node-targeted invocation as the fixed suite. + filtered |= session.config.args != ["tests"] + return { + "schema": "jitmind.collection/v1", + "candidate": _SESSION["candidate"], + "nodes": _SESSION["nodes"], + "selected": _SESSION["collected"], + "deselected": _SESSION["deselected"], + "collection_reports": _SESSION["collection_reports"], + "filtered": bool(filtered), + } + + +def pytest_collection_finish(session): + if _SESSION: + _SESSION["collected"] = [item.nodeid for item in session.items] + # Exclusive artifact captured before execution, independent of runtime records. + write_json(Path(_SESSION["expected_path"]), collection_record(session)) + + +def pytest_runtest_logreport(report): + if _SESSION: + phases = _SESSION["records"].setdefault(report.nodeid, {}) + require(report.when not in phases, "duplicate_test_phase") + phases[report.when] = ( + "skipped" if hasattr(report, "wasxfail") else report.outcome + ) + + +def pytest_sessionfinish(session, exitstatus): + if not _SESSION: + return + expected_path = Path(_SESSION["expected_path"]) + if not expected_path.exists(): + write_json(expected_path, collection_record(session)) + records = [] + for node, phases in _SESSION["records"].items(): + status = ( + "failed" + if "failed" in phases.values() + else "skipped" + if "skipped" in phases.values() + else "passed" + if phases == {"setup": "passed", "call": "passed", "teardown": "passed"} + else "unknown" + ) + source = relative_file(Path(_SESSION["repo"]), node.split("::")[0]) + records.append( + { + "node_id": node, + "phases": phases, + "status": status, + "source_sha256": digest(source), + "kind": _SESSION["kinds"].get(node, "unmapped"), + } + ) + write_json( + Path(_SESSION["output"]), + { + "schema": "jitmind.pytest/v2", + "candidate": _SESSION["candidate"], + "collected": _SESSION["collected"], + "available": True, + "collection_count": len(_SESSION["collected"]), + "expected_collection_sha256": digest(expected_path), + "session_testscollected": session.testscollected, + "session_testsfailed": session.testsfailed, + "phase_counts": { + outcome: sum( + p == outcome for r in records for p in r["phases"].values() + ) + for outcome in ("passed", "failed", "skipped") + }, + "records": records, + "exit_code": int(exitstatus), + }, + ) + + +def host_facts(home: Path) -> dict: + with sqlite3.connect(home / "qualification-probe.sqlite") as conn: + pragmas = { + key: conn.execute("PRAGMA " + key).fetchone()[0] + for key in ("journal_mode", "synchronous", "foreign_keys", "busy_timeout") + } + return { + "python": platform.python_version(), + "implementation": platform.python_implementation(), + "os": platform.system(), + "os_release": platform.release(), + "machine": platform.machine(), + "processor": platform.processor() or None, + "cpu_count": os.cpu_count(), + "sqlite": sqlite3.sqlite_version, + "probe_connection_pragmas": pragmas, + "pragma_scope": "fresh stdlib connection; not product storage settings", + "dependencies": sorted( + [ + [d.metadata["Name"], d.version] + for d in importlib.metadata.distributions() + ] + ), + } + + +def run_suite( + repo: Path, + output: Path, + wheelhouse: Path | None, + worktree: bool, + overall: float, + per_command: float, + node_binary: Path | None = None, +) -> dict: + require(os.name == "posix", "process_groups_unsupported_platform") + require( + math.isfinite(overall) + and overall > 0 + and math.isfinite(per_command) + and per_command > 0, + "invalid_deadline", + ) + repo = repo.resolve() + output = output.absolute() + require( + not output.resolve().is_relative_to(repo), "output_must_be_outside_checkout" + ) + output.mkdir(mode=0o700, parents=False, exist_ok=False) + python = Path(sys.executable).absolute() + deadline = time.monotonic() + overall + with tempfile.TemporaryDirectory(prefix="jitmind-qualification-") as temporary: + scratch = Path(temporary) + identity = candidate_identity(repo, scratch, python, deadline) + require(worktree or not identity["dirty"], "dirty_release") + mapping_path = repo / "docs/engineering/acceptance-map.json" + mapping = strict_json(mapping_path) + cases = validate_map(mapping) + write_json(output / "acceptance-map.json", mapping) + report = { + "schema": "jitmind.qualification/v2", + "mode": "worktree" if worktree else "release", + "candidate": identity, + "host": host_facts(scratch), + "findings": [], + "commands": [], + "artifacts": [], + "test_results": "pytest-results.json", + "expected_collection": "expected-collection.json", + "acceptance_map": artifact(output, "acceptance-map.json"), + "package_sha256": None, + "suite_source": "trusted_fixed_argv_v1", + "checkout_tests_pythonpath": "explicit_checkout_only", + } + build_source = scratch / "build-source" + build_source.mkdir() + for name, expected_hash in identity["snapshot_files"]: + require(time.monotonic() < deadline, "overall_deadline") + if expected_hash is None: + continue + source = relative_file(repo, name) + require( + digest(source, deadline=deadline) == expected_hash, + "candidate_changed_during_snapshot", + ) + destination = build_source / name + destination.parent.mkdir(parents=True, exist_ok=True) + bounded_copy( + source, destination, expected_hash=expected_hash, deadline=deadline + ) + require( + digest(destination, deadline=deadline) == expected_hash, + "candidate_changed_during_snapshot", + ) + report["build_source"] = ( + "fresh_copy_of_pinned_snapshot_without_ignored_build_outputs" + ) + report["node_binary_sha256"] = digest(node_binary) if node_binary else None + kinds = {} + for case in cases: + for stage in case["stages"]: + for node in stage["nodes"]: + previous = kinds.setdefault(node["node_id"], node["kind"]) + require(previous == node["kind"], "conflicting_node_kind") + # Every live snapshot entry is retained, including non-code fixtures/config. + copied_bytes = 0 + for name, expected_hash in identity["snapshot_files"]: + if expected_hash is None: + continue + src = relative_file(build_source, name) + copied_bytes += src.stat().st_size + require(copied_bytes <= MAX_TOTAL_BYTES, "source_snapshot_too_large") + dest = output / "sources" / name + dest.parent.mkdir(parents=True, exist_ok=True) + bounded_copy(src, dest, expected_hash=expected_hash, deadline=deadline) + report["artifacts"].append(artifact(output, "sources/" + name)) + context = scratch / "context.json" + write_json( + context, + { + "repo": str(repo), + "output": str(output / "pytest-results.json"), + "candidate": identity, + "kinds": kinds, + }, + ) + env = clean_env(scratch, python, repo) + env["JITMIND_QUALIFICATION_CONTEXT"] = str(context) + if node_binary is not None: + require( + node_binary.is_absolute() and node_binary.is_file(), + "invalid_node_runtime", + ) + env["JITMIND_TEST_NODE"] = str(node_binary.resolve()) + + cancelled = threading.Event() + + def execute(name, argv, cwd, environment): + record = run_command( + argv, + cwd=cwd, + env=environment, + log=output / (name + ".log"), + deadline=deadline, + timeout=per_command, + cancel=cancelled, + ) + if record["status"] == "cancelled": + cancelled.set() + # Exact argv may contain private local paths; report portable placeholders. + record.update( + { + "id": name, + "argv": [ + arg.replace(str(repo), "") + .replace(str(scratch), "") + .replace(str(output), "") + .replace(str(python), "") + .replace(str(wheelhouse), "") + if wheelhouse + else arg.replace(str(repo), "") + .replace(str(scratch), "") + .replace(str(output), "") + .replace(str(python), "") + for arg in argv + ], + "log": name + ".log", + } + ) + report["commands"].append(record) + report["artifacts"].append(artifact(output, name + ".log")) + return record["status"] == "passed" + + execute( + "pytest", + [ + str(python), + "-m", + "pytest", + "-q", + "tests", + "-p", + "scripts.qualify_jitmind", + ], + repo, + env, + ) + if not (output / "expected-collection.json").exists(): + write_json( + output / "expected-collection.json", + { + "schema": "jitmind.collection/v1", + "candidate": identity, + "nodes": [], + "selected": [], + "deselected": [], + "collection_reports": [], + "filtered": True, + }, + ) + report["artifacts"].append(artifact(output, "expected-collection.json")) + if not (output / "pytest-results.json").exists(): + write_json( + output / "pytest-results.json", + { + "schema": "jitmind.pytest/v2", + "candidate": identity, + "collected": [], + "collection_count": None, + "expected_collection_sha256": digest( + output / "expected-collection.json" + ), + "session_testscollected": None, + "session_testsfailed": None, + "phase_counts": None, + "available": False, + "records": [], + "exit_code": 99, + }, + ) + report["artifacts"].append(artifact(output, "pytest-results.json")) + execute( + "compile", + [ + str(python), + "-m", + "compileall", + "-q", + "jitmind", + "scripts/qualify_jitmind.py", + ], + repo, + env, + ) + wheels = scratch / "wheels" + wheels.mkdir() + build_env = clean_env(scratch, python) + built = execute( + "wheel", + [ + str(python), + "-m", + "pip", + "wheel", + "--no-index", + "--no-deps", + "--no-build-isolation", + "--wheel-dir", + str(wheels), + str(build_source), + ], + scratch, + build_env, + ) + available = list(wheels.glob("jitmind-*.whl")) + if built and len(available) == 1: + wheel = available[0] + dest = output / wheel.name + wheel_hash = bounded_copy(wheel, dest, deadline=deadline) + report["artifacts"].append(artifact(output, wheel.name)) + report["package_sha256"] = wheel_hash + venv = scratch / "installed" + created = execute( + "venv", [str(python), "-m", "venv", str(venv)], scratch, build_env + ) + vpython = venv / "bin/python" + install_env = clean_env(scratch, vpython) + install_argv = [ + str(vpython), + "-I", + "-m", + "pip", + "install", + "--no-index", + "--only-binary=:all:", + ] + if wheelhouse is not None: + install_argv += ["--find-links", str(wheelhouse.resolve())] + if created and execute( + "install", install_argv + [str(dest)], scratch, install_env + ): + install_env["PATH"] = str(vpython.parent) + execute( + "smoke", + [ + str(vpython), + "-I", + str(repo / "tests/test_standalone_install.py"), + "--installed-smoke", + str(venv), + str(output / "installed-results.json"), + ], + scratch, + install_env, + ) + if (output / "installed-results.json").exists(): + report["artifacts"].append( + artifact(output, "installed-results.json") + ) + smoke = strict_json(output / "installed-results.json") + report["installed"] = smoke + else: + report["findings"].append("candidate_wheel_missing") + # Preserve every suite slot even when an upstream prerequisite failed. + for name in sorted(COMMANDS - {c["id"] for c in report["commands"]}): + with (output / (name + ".log")).open("xb"): + pass + report["commands"].append( + { + "id": name, + "status": "not_run", + "exit_code": None, + "elapsed_seconds": None, + "log_bytes": 0, + "log_truncated": False, + "log": name + ".log", + "argv": None, + "reason": "prerequisite_not_passed", + } + ) + report["artifacts"].append(artifact(output, name + ".log")) + # Detect mutations during tests/build; build output is gitignored, source is not. + final_scratch = scratch / "final" + final_scratch.mkdir() + try: + after = candidate_identity(repo, final_scratch, python, deadline) + if after != identity: + report["findings"].append("candidate_changed_during_checks") + except EvidenceError: + report["findings"].append("candidate_final_identity_unavailable") + write_json(output / "report.json", report) + verdict = evaluate(mapping, report, output) + write_json(output / "verdict.json", verdict) + return verdict + + +def main(argv=None) -> int: + parser = argparse.ArgumentParser(description=__doc__) + sub = parser.add_subparsers(dest="action", required=True) + run = sub.add_parser("run") + run.add_argument( + "--output", type=Path, required=True, help="new directory outside checkout" + ) + run.add_argument( + "--wheelhouse", type=Path, help="reviewed offline core dependency wheels" + ) + run.add_argument( + "--node-binary", + type=Path, + help="trusted provisioned Node executable for parser tests only", + ) + run.add_argument( + "--worktree", action="store_true", help="label dirty developer checks" + ) + run.add_argument("--overall-seconds", type=float, default=900) + run.add_argument("--command-seconds", type=float, default=180) + verify = sub.add_parser( + "verify", help="read-only validation; never execute evidence commands" + ) + verify.add_argument("report_dir", type=Path) + verify.add_argument( + "--candidate-sha", required=True, help="expected reviewed Git SHA" + ) + verify.add_argument( + "--snapshot-sha", + required=True, + help="expected reviewed source snapshot SHA-256", + ) + args = parser.parse_args(argv) + try: + if args.action == "run": + verdict = run_suite( + Path(__file__).resolve().parents[1], + args.output, + args.wheelhouse, + args.worktree, + args.overall_seconds, + args.command_seconds, + args.node_binary, + ) + else: + report = strict_json(args.report_dir / "report.json") + require( + report.get("candidate", {}).get("git_sha") == args.candidate_sha, + "unexpected_candidate_sha", + ) + require( + report.get("candidate", {}).get("snapshot_sha256") == args.snapshot_sha, + "unexpected_snapshot_sha", + ) + # Expected mapping is trusted checkout configuration, not imported claims. + mapping = strict_json( + Path(__file__).resolve().parents[1] + / "docs/engineering/acceptance-map.json" + ) + verdict = evaluate(mapping, report, args.report_dir) + print(json.dumps(verdict, sort_keys=True, allow_nan=False)) + return 0 if verdict["checks_only_complete"] else 1 + except (EvidenceError, OSError, KeyError, TypeError, AttributeError, ValueError): + print( + json.dumps( + { + "checks_only_complete": False, + "release_qualified": False, + "error": "qualification_invalid_or_unavailable", + } + ) + ) + return 2 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tests/test_acceptance_edges.py b/tests/test_acceptance_edges.py new file mode 100644 index 0000000..fa26498 --- /dev/null +++ b/tests/test_acceptance_edges.py @@ -0,0 +1,538 @@ +"""Acceptance supplements using real local storage and the provisioned parser. + +Only ENOSPC is injected. SQLite capacity and child exit are real, bounded faults. +No provider, source execution, package installation, or external fixture is used. +""" + +import errno +import hashlib +import json +import multiprocessing +import os +import shutil +import sqlite3 +from contextlib import contextmanager +from pathlib import Path +from uuid import uuid4 + +import pytest + +from jitmind.code_context import CodeContext, CodeQuery, NodeParser, RepoRegistry +from jitmind.code_memory.anchors import CodeMemoryService +from jitmind.code_memory.lesson_models import ( + DurableBindingAuthority, + DurableFactAuthority, + LessonProjection, + ProposedAction, +) +from jitmind.code_memory.open_work import OpenWorkService +from jitmind.code_memory.preflight import PreflightService +from jitmind.code_memory.work_storage import Budget, WorkDatabase +from jitmind.schemas import MemoryEntry, Page +from jitmind.schemas.advanced_memory import AdvancedMemoryStore +from jitmind.schemas.memory import InMemoryMemoryStore +from jitmind.schemas.page import InMemoryPageStore +from jitmind.schemas.ttl_memory import TTLMemoryStore +from jitmind.schemas.ttl_page import TTLPageStore +from jitmind.scope import ScopeAuthority +from jitmind.storage import ( + DurableMemoryAdapter, + DurablePageAdapter, + IngestRequest, + Proposal, + SQLiteDurableStore, + StorageFailure, + stage_legacy, +) +from jitmind.utils import atomic_io + + +@pytest.mark.parametrize( + "store_class,filename", + [ + (AdvancedMemoryStore, "advanced_memory_state.json"), + (InMemoryMemoryStore, "memory_state.json"), + (TTLMemoryStore, "ttl_memory_state.json"), + (InMemoryPageStore, "pages.json"), + (TTLPageStore, "ttl_pages.json"), + ], + ids=["advanced", "memory", "ttl_memory", "pages", "ttl_pages"], +) +def test_enospc_at_legacy_publication_preserves_ack_and_bytes( + tmp_path, monkeypatch, store_class, filename +): + def reader(): + kwargs = ( + {"enable_auto_cleanup": False} + if store_class in (AdvancedMemoryStore, TTLMemoryStore, TTLPageStore) + else {} + ) + return store_class(str(tmp_path), **kwargs) + + def append(store, body): + store.add( + Page(header="fixture", content=body) + if store_class in (InMemoryPageStore, TTLPageStore) + else body + ) + + def contents(store): + state = store.load() + return ( + state.abstracts + if hasattr(state, "abstracts") + else [p.content for p in state] + ) + + store = reader() + append(store, "previously committed") + path = tmp_path / filename + previous = path.read_bytes() + calls = [] + cause = OSError(errno.ENOSPC, "sanitized_fixture") + + def full(source, destination): + # Exercise the actual post-fsync, pre-publication filesystem boundary. + assert Path(destination) == path + assert Path(source).is_file() + assert b"unacknowledged memory" in Path(source).read_bytes() + calls.append((Path(source).name, Path(destination).name)) + raise cause + + with monkeypatch.context() as fault: + fault.setattr(atomic_io.os, "replace", full) + with pytest.raises(atomic_io.PersistenceError) as raised: + append(store, "unacknowledged memory") + assert len(calls) == 1 + assert raised.value.__cause__ is cause + assert cause.errno == errno.ENOSPC + assert not raised.value.outcome_uncertain + assert "sanitized_fixture" not in str(raised.value) + assert path.read_bytes() == previous + assert contents(store) == contents(reader()) == ["previously committed"] + assert not list(tmp_path.glob("*.tmp")) + append(store, "positive after fault removed") + assert contents(reader()) == [ + "previously committed", + "positive after fault removed", + ] + + +def _proposal(body, operation="add", target=None): + return Proposal( + abstract=body, + header="fixture", + decorated=body, + decision={"operation": operation, "target_id": target}, + ) + + +def test_real_sqlite_full_rolls_back_every_effect_then_accepts_same_request( + tmp_path, monkeypatch +): + store = SQLiteDurableStore(tmp_path / "capacity.sqlite") + original = store._connection + native_errors = [] + capacities = [] + + @contextmanager + def capped(**kwargs): + with original(**kwargs) as connection: + pages = connection.execute("PRAGMA page_count").fetchone()[0] + cap = connection.execute(f"PRAGMA max_page_count={pages}").fetchone()[0] + capacities.append((pages, cap)) + try: + yield connection + except sqlite3.Error as exc: + native_errors.append(exc.sqlite_errorcode) + raise + + # Below the public 131072-character input bound; comfortably larger than + # this empty DB's free space. This never attempts to fill the host disk. + request = IngestRequest.create("tenant", "capacity-write", "x" * 100000) + with monkeypatch.context() as fault: + fault.setattr(store, "_connection", capped) + with pytest.raises(StorageFailure, match="^storage_failure$"): + store.ingest(request, lambda _: _proposal("bounded capacity fact")) + assert native_errors == [sqlite3.SQLITE_FULL] + assert capacities and all(count == cap for count, cap in capacities) + fresh = SQLiteDurableStore(store.path) + assert fresh.status("tenant") == { + "revision": 0, + "pending_events": 0, + "delivery_watermark": 0, + "pages": 0, + "facts": 0, + "operations": 0, + } + assert fresh.lookup_receipt(request) is None + assert fresh.snapshot("tenant").entries == () + assert fresh.pending_events("tenant") == [] + assert fresh.projected_entries("tenant") == [] + with sqlite3.connect(store.path) as connection: + for table in ( + "namespaces", + "facts", + "pages", + "operations", + "outbox", + "projection", + ): + assert ( + connection.execute(f"SELECT count(*) FROM {table}").fetchone()[0] == 0 + ) + connection.execute("PRAGMA max_page_count=10000") + assert connection.execute("PRAGMA integrity_check").fetchone()[0] == "ok" + receipt = fresh.ingest(request, lambda _: _proposal("bounded capacity fact")) + assert receipt.revision == 1 + assert ( + fresh.get_entry("tenant", receipt.memory_id).source_page_id == receipt.page_id + ) + assert fresh.get_page("tenant", receipt.page_id).content == request.message + assert fresh.lookup_receipt(request) == receipt + assert len(fresh.pending_events("tenant")) == 1 + assert fresh.ingest(request, lambda _: pytest.fail("replay generated")) == receipt + fresh.deliver_event("tenant", receipt.event_id) + assert [entry.id for entry in fresh.projected_entries("tenant")] == [ + receipt.memory_id + ] + + +def _interrupt_import(source, destination, stage): + staged = stage_legacy(source, quiesced=True) + + def interrupt(current): + if current == stage: + os._exit(73) + + SQLiteDurableStore(destination, fault_hook=interrupt).import_staged( + staged, "tenant" + ) + + +@pytest.mark.parametrize("stage", ["after_import_pages", "before_import_commit"]) +def test_real_migration_exit_preserves_source_and_allows_retry(tmp_path, stage): + source = tmp_path / "legacy" + source.mkdir() + fact = MemoryEntry( + id="legacy-fact", + content="migration fixture fact", + source_page_id="0", + t_created="2026-01-01T00:00:00+00:00", + t_observed="2026-01-01T00:00:00+00:00", + ) + page = Page( + header="fixture", + content="migration provenance", + meta={"page_id": 0, "memory_id": fact.id}, + ) + (source / "advanced_memory_state.json").write_text( + json.dumps({"entries": [fact.model_dump()]}) + ) + (source / "pages.json").write_text(json.dumps([page.model_dump()])) + originals = {p.name: p.read_bytes() for p in source.iterdir()} + path = tmp_path / "candidate.sqlite" + SQLiteDurableStore(path) + child = multiprocessing.get_context("spawn").Process( + target=_interrupt_import, args=(str(source), str(path), stage) + ) + try: + child.start() + child.join(20) + assert child.exitcode == 73, "child must exit at the actual import boundary" + finally: + if child.is_alive(): + child.terminate() + child.join(5) + if child.is_alive(): + child.kill() + child.join(5) + assert not child.is_alive() + child.close() + assert {p.name: p.read_bytes() for p in source.iterdir()} == originals + fresh = SQLiteDurableStore(path) + with sqlite3.connect(path) as connection: + for table in ( + "namespaces", + "pages", + "facts", + "operations", + "outbox", + "aliases", + "imports", + ): + assert ( + connection.execute(f"SELECT count(*) FROM {table}").fetchone()[0] == 0 + ) + assert connection.execute("PRAGMA integrity_check").fetchone()[0] == "ok" + staged = stage_legacy(source, quiesced=True) + report = fresh.import_staged(staged, "tenant") + assert report["page_count"] == report["fact_count"] == 1 + restored = fresh.get_entry("tenant", fact.id) + assert restored.content == fact.content + assert fresh.get_page("tenant", restored.source_page_id).content == page.content + assert fresh.resolve_page_alias("tenant", "0") == restored.source_page_id + assert fresh.import_staged(staged, "tenant") == report + assert fresh.status("tenant")["revision"] == 1 + assert {p.name: p.read_bytes() for p in source.iterdir()} == originals + + +@pytest.mark.parametrize("delay_add", [False, True], ids=["projected", "add_pending"]) +def test_real_parser_binding_projection_redelivery_and_primary_forget( + tmp_path, delay_add +): + sentinel = "MEMORY_ONLY_SENTINEL_83f91c" + source = "def original(x):\n return x + 123\n" + checkout = tmp_path / "checkout" + checkout.mkdir() + path = checkout / "source.py" + path.write_text(source) + assert sentinel not in source + repo = str(uuid4()) + authority = ScopeAuthority() + authority.grant("alice", "tenant", [repo]) + + def scope(): + return authority.context("alice", "tenant", str(uuid4())) + + registry = RepoRegistry() + registry.register(repo, str(checkout.resolve()), "tenant") + adapter = Path( + os.environ.get( + "JITMIND_TEST_GRAFT_ADAPTER", + Path(__file__).resolve().parents[1] / "adapters/graft", + ) + ) + node = os.environ.get("JITMIND_TEST_NODE") or shutil.which("node") + assert node and adapter.is_dir(), ( + "Provision the actual J04 Node/tree-sitter adapter" + ) + context = CodeContext( + authority, + registry, + NodeParser(str(Path(node).resolve()), str(adapter.resolve())), + ) + facts = SQLiteDurableStore(tmp_path / "facts.sqlite") + + def ingest(key, operation="add", target=None): + return facts.ingest( + IngestRequest.create("tenant", key, sentinel), + lambda _: _proposal(sentinel, operation, target), + ) + + fact = ingest("add") + duplicate = ingest("noop", "noop", fact.memory_id) + bindings = CodeMemoryService( + authority, facts, context, tmp_path / "bindings.sqlite" + ) + + def build(): + result = context.build(scope(), repo, deadline_ms=10000) + assert result.status == "ok", result + return result + + first = build() + binding = bindings.create_binding( + scope(), + logical_binding_id="logical", + fact_version_id=fact.memory_id, + repo_id=repo, + snapshot_id=first.snapshot_id, + path="source.py", + qualified_name="original", + ) + assert binding.validation_state == "verified_current" + database = WorkDatabase(tmp_path / "work.sqlite") + work = OpenWorkService(database, authority) + item = work.create( + scope(), + repo, + summary="Complete the outstanding review", + expected_revision=0, + idempotency_key="obligation", + binding_refs=("logical",), + decision_refs=(fact.memory_id,), + ) + assert ( + work.binding_locations(scope(), repo, item.id, bindings)[0]["path"] + == "source.py" + ) + projection = LessonProjection( + database, + authority, + DurableFactAuthority(facts, authority), + binding_authority=DurableBindingAuthority(bindings, authority), + ) + + def project(version): + return projection.project_binding_observation( + scope(), + repo, + bindings, + logical_binding_id="logical", + lesson_id="lesson", + version=version, + source_revision=fact.revision, + body=sentinel, + ) + + assert project(1) + service = PreflightService(projection) + delivery_scope = scope() + session = service.start_session(delivery_scope, repo) + original_target = ProposedAction(repo, "source.py", "original") + before = service.deliver( + delivery_scope, session, original_target, delivery_key="original" + ) + assert before.state == "delivered" and sentinel in before.payload + assert facts.status("tenant")["pending_events"] == 2 + assert facts.status("tenant")["delivery_watermark"] == 0 + assert facts.get_entry("tenant", fact.memory_id).content == sentinel + + # Source generation and fact outbox revision are independent watermarks. + path.rename(checkout / "moved.py") + stale = context.query( + scope(), + CodeQuery( + operation="find_code", + repo_id=repo, + snapshot_id=first.snapshot_id, + query="original", + ), + ) + assert stale.freshness["state"] != "fresh" + assert bindings.get_current(scope(), "logical").validation_state == "unknown" + current = build() + assert ( + current.generation > first.generation + and current.snapshot_id != first.snapshot_id + ) + relocated = bindings.revalidate( + scope(), + "logical", + snapshot_id=current.snapshot_id, + expected_revision=binding.revision, + ) + assert ( + relocated.reason_code == "file_move" + and relocated.validation_state == "verified_current" + ) + assert relocated.source_generation == current.generation + assert ( + work.binding_locations(scope(), repo, item.id, bindings)[0]["path"] + == "moved.py" + ) + assert project(2) + assert project(2) # Same material version is idempotent. + assert not project(1) # Out-of-order lesson cannot replace the moved version. + target = ProposedAction(repo, "moved.py", "original") + lessons = projection.candidates(scope(), target, Budget(2)) + assert len(lessons) == 1 and lessons[0].version == 2 + delivered = service.deliver(delivery_scope, session, target, delivery_key="moved") + assert delivered.state == "delivered" and sentinel in delivered.payload + assert bindings.project_fact( + scope(), fact_version_id=fact.memory_id, event_revision=fact.revision + ) + assert not bindings.project_fact( + scope(), fact_version_id=fact.memory_id, event_revision=fact.revision + ) + facts.deliver_event("tenant", duplicate.event_id) + facts.deliver_event("tenant", duplicate.event_id) + assert facts.status("tenant")["delivery_watermark"] == 0 + if delay_add: + assert facts.status("tenant")["pending_events"] == 1 + assert facts.projected_entries("tenant") == [] + else: + facts.deliver_event("tenant", fact.event_id) + assert facts.status("tenant")["pending_events"] == 0 + assert facts.status("tenant")["delivery_watermark"] == duplicate.revision + assert [entry.id for entry in facts.projected_entries("tenant")] == [ + fact.memory_id + ] + assert ( + bindings.get_current(scope(), "logical").source_generation == current.generation + ) + + deleted = ingest("forget", "delete", fact.memory_id) + # Delay all deletion projections. Current output must already be hidden. + assert facts.status("tenant")["pending_events"] == 1 + int(delay_add) + assert facts.get_entry("tenant", fact.memory_id) is None + assert facts.snapshot("tenant").entries == () + assert facts.projected_entries("tenant") == [] + assert DurableMemoryAdapter(facts, "tenant").load().abstracts == [] + assert DurablePageAdapter(facts, "tenant").load() == [] + for receipt in (fact, duplicate, deleted): + assert facts.get_page("tenant", receipt.page_id) is None + assert sentinel not in repr(facts.memory_update(receipt)) + assert sentinel not in repr(facts.receipt_content(receipt)) + assert sentinel not in receipt.model_dump_json() + assert projection.candidates(scope(), target, Budget(2)) == [] + for action, key in ((original_target, "original"), (target, "moved")): + result = service.deliver(delivery_scope, session, action, delivery_key=key) + assert result.state == "nothing_relevant" and result.payload == "" + assert bindings.get_current(scope(), "logical").reason_code == "fact_unavailable" + assert not project(3) + # New deletion metadata first, then delayed old events: no resurrection. + assert bindings.project_fact( + scope(), fact_version_id=fact.memory_id, event_revision=deleted.revision + ) + assert not bindings.project_fact( + scope(), fact_version_id=fact.memory_id, event_revision=fact.revision + ) + report = projection.forget( + scope(), fact.memory_id, tombstone_revision=deleted.revision + ) + assert report["purge"] == "projection_purged" + assert not project(1) + facts.deliver_event("tenant", deleted.event_id) + if delay_add: + assert facts.status("tenant")["delivery_watermark"] == 0 + assert facts.pending_events("tenant")[0]["event_id"] == fact.event_id + for receipt in (duplicate, fact, deleted): + facts.deliver_event("tenant", receipt.event_id) + assert facts.status("tenant")["pending_events"] == 0 + assert facts.status("tenant")["delivery_watermark"] == deleted.revision + assert facts.projected_entries("tenant") == [] + assert projection.candidates(scope(), target, Budget(2)) == [] + assert work.get(scope(), repo, item.id).status == "open" + assert work.get(scope(), repo, item.id).revision == 1 + assert work.binding_locations(scope(), repo, item.id, bindings) == ( + {"binding_id": "logical", "repo_id": repo, "grain": "repo"}, + ) + history = bindings.history(scope(), "logical") + assert len(history) == 2 and sentinel not in repr(history) + assert sentinel not in repr(work.history(scope(), repo, item.id)) + with database.connect(Budget(2)) as connection: + assert connection.execute("SELECT count(*) FROM lessons").fetchone()[0] == 0 + for table in ( + "history", + "work_receipts", + "deliveries", + "delivery_receipts", + "tombstones", + ): + assert sentinel not in repr( + [tuple(row) for row in connection.execute(f"SELECT * FROM {table}")] + ) + with bindings.store.connection() as connection: + for table in ("history", "requests", "sources", "facts"): + assert sentinel not in repr( + connection.execute(f"SELECT * FROM {table}").fetchall() + ) + # J04 indexes authorized source, not fact bodies. Forgetting a memory does + # not delete source files; raw code remains readable with correct identity. + code = context.query( + scope(), + CodeQuery( + operation="find_code", + repo_id=repo, + snapshot_id=current.snapshot_id, + query="original", + ), + ) + assert code.status == "ok" and code.freshness["state"] == "fresh" + assert len(code.results) == 1 and code.results[0].source == source + assert code.generation == current.generation + assert code.results[0].digest == hashlib.sha256(source.encode()).hexdigest() + assert sentinel not in code.model_dump_json() + assert (checkout / "moved.py").read_text() == source diff --git a/tests/test_qualification.py b/tests/test_qualification.py new file mode 100644 index 0000000..76d4a1e --- /dev/null +++ b/tests/test_qualification.py @@ -0,0 +1,628 @@ +"""Gate/tool tests use controlled evidence, never product-acceptance credit.""" + +from __future__ import annotations + +import copy +import hashlib +import json +from pathlib import Path +import signal +import sys +import threading +import time + +import pytest + +from scripts import qualify_jitmind as q + + +def save(path, data): + path.write_text(json.dumps(data, allow_nan=False)) + + +@pytest.fixture +def bundle(tmp_path): + source = tmp_path / "sources/tests/test_product.py" + source.parent.mkdir(parents=True) + source.write_text("def test_contract():\n assert True\n") + ref = {"path": "tests/test_product.py", "sha256": q.digest(source)} + mapping = { + "schema": "jitmind.acceptance-map/v1", + "source_handoff_sha256": "a" * 64, + "cases": [ + { + "case_id": "J01", + "ticket": "J-01", + "status": "not_run", + "required_in_tickets": ["J-01"], + "stages": [ + { + "stage_id": "J-01", + "status": "not_run", + "nodes": [ + { + "node_id": "tests/test_product.py::test_contract", + "kind": "real_storage", + "source": ref, + "fixtures": [ref], + } + ], + } + ], + } + ], + } + roster = [[ref["path"], ref["sha256"]]] + candidate = { + "git_sha": "b" * 40, + "snapshot_files": roster, + "snapshot_sha256": hashlib.sha256( + json.dumps(roster, separators=(",", ":")).encode() + ).hexdigest(), + "dirty": False, + } + node = mapping["cases"][0]["stages"][0]["nodes"][0]["node_id"] + tests = { + "schema": "jitmind.pytest/v2", + "candidate": copy.deepcopy(candidate), + "collected": [node], + "collection_count": 1, + "exit_code": 0, + "records": [ + { + "node_id": node, + "kind": "real_storage", + "source_sha256": ref["sha256"], + "status": "passed", + "phases": {"setup": "passed", "call": "passed", "teardown": "passed"}, + } + ], + } + expected = { + "schema": "jitmind.collection/v1", + "candidate": copy.deepcopy(candidate), + "nodes": [node], + "selected": [node], + "deselected": [], + "collection_reports": [], + "filtered": False, + } + save(tmp_path / "expected-collection.json", expected) + tests.update( + expected_collection_sha256=q.digest(tmp_path / "expected-collection.json"), + phase_counts={"passed": 3, "failed": 0, "skipped": 0}, + session_testscollected=1, + session_testsfailed=0, + ) + save(tmp_path / "pytest-results.json", tests) + save(tmp_path / "acceptance-map.json", mapping) + (tmp_path / "candidate.whl").write_bytes( + b"controlled-test-fixture-not-an-installable-wheel" + ) + smoke = { + "schema": "jitmind.installed-smoke/v1", + "node_id": q.SMOKE_NODE, + "checks": dict.fromkeys(q.SMOKE_CHECKS, "passed"), + "status": "passed", + "provider_calls": 0, + "source_sha256": "d" * 64, + } + save(tmp_path / "installed-results.json", smoke) + commands = [] + for name in sorted(q.COMMANDS): + (tmp_path / (name + ".log")).write_text( + "controlled fixture, not actual execution\n" + ) + commands.append( + { + "id": name, + "status": "passed", + "exit_code": 0, + "log_truncated": False, + "log": name + ".log", + } + ) + report = { + "schema": "jitmind.qualification/v2", + "candidate": candidate, + "mode": "release", + "commands": commands, + "findings": [], + "test_results": "pytest-results.json", + "expected_collection": "expected-collection.json", + "package_sha256": q.digest(tmp_path / "candidate.whl"), + "acceptance_map": q.artifact(tmp_path, "acceptance-map.json"), + "artifacts": [ + q.artifact(tmp_path, str(p.relative_to(tmp_path))) + for p in tmp_path.rglob("*") + if p.is_file() and p.name != "acceptance-map.json" + ], + } + return tmp_path, mapping, report, tests + + +def refresh(bundle, *, tests=True, mapping=True): + root, expected, report, records = bundle + if tests: + collection = q.strict_json(root / "expected-collection.json") + collection["candidate"] = copy.deepcopy(report["candidate"]) + save(root / "expected-collection.json", collection) + records["expected_collection_sha256"] = q.digest( + root / "expected-collection.json" + ) + if records.get("available", True): + records["phase_counts"] = { + outcome: sum( + p == outcome + for r in records["records"] + for p in r["phases"].values() + ) + for outcome in ("passed", "failed", "skipped") + } + records["session_testscollected"] = records["collection_count"] + records["session_testsfailed"] = records["phase_counts"]["failed"] + sum( + r["outcome"] == "failed" for r in collection["collection_reports"] + ) + else: + records.update( + phase_counts=None, session_testscollected=None, session_testsfailed=None + ) + save(root / "pytest-results.json", records) + if mapping: + save(root / "acceptance-map.json", expected) + report["acceptance_map"] = q.artifact(root, "acceptance-map.json") + report["artifacts"] = [q.artifact(root, ref["path"]) for ref in report["artifacts"]] + + +def verdict(bundle): + root, mapping, report, _ = bundle + return q.evaluate(mapping, report, root) + + +def test_complete_controlled_fixture_is_consistent_but_never_signoff(bundle): + result = verdict(bundle) + assert result["checks_only_complete"] is True + assert result["release_qualified"] is False + assert result["case_count"] == result["stage_count"] == result["passed_cases"] == 1 + assert result["benchmark_measurement"] is None + assert "independent_signoff_not_recorded" in result["release_blockers"] + + +@pytest.mark.parametrize( + "raw", ['{"a":1,"a":2}', '{"n":NaN}', '{"n":Infinity}', '{"n":1e999}', "{"] +) +def test_untrusted_json_rejects_duplicates_nonfinite_truncation(tmp_path, raw): + path = tmp_path / "input.json" + path.write_text(raw) + with pytest.raises(q.EvidenceError): + q.strict_json(path) + + +def test_oversized_json_is_bounded_before_decode(tmp_path): + path = tmp_path / "input.json" + path.write_bytes(b" " * 101) + with pytest.raises(q.EvidenceError, match="input_too_large"): + q.strict_json(path, limit=100) + + +def test_duplicate_case_rejected(bundle): + bundle[1]["cases"].append(copy.deepcopy(bundle[1]["cases"][0])) + refresh(bundle) + with pytest.raises(q.EvidenceError, match="duplicate_case"): + verdict(bundle) + + +def test_missing_repeat_stage_rejected(bundle): + bundle[1]["cases"][0]["required_in_tickets"].append("J-04") + refresh(bundle) + with pytest.raises(q.EvidenceError, match="missing_stage"): + verdict(bundle) + + +def test_unmapped_stage_keeps_denominator(bundle): + case = bundle[1]["cases"][0] + case["required_in_tickets"].append("J-04") + case["stages"].append({"stage_id": "J-04", "nodes": [], "status": "not_run"}) + refresh(bundle) + result = verdict(bundle) + assert result["case_count"] == 1 and result["stage_count"] == 2 + assert result["passed_cases"] == 0 and not result["checks_only_complete"] + + +def test_partial_mapping_cannot_complete_stage(bundle): + bundle[1]["cases"][0]["stages"][0]["additional_mapping_required"] = True + refresh(bundle) + assert not verdict(bundle)["checks_only_complete"] + + +def test_no_checks_false_pass_rejected(bundle): + bundle[2]["commands"] = [] + assert not verdict(bundle)["checks_only_complete"] + + +@pytest.mark.parametrize("field", ["collection_count", "exit_code"]) +def test_boolean_is_not_integer(bundle, field): + bundle[3][field] = True if field == "collection_count" else False + refresh(bundle) + with pytest.raises(q.EvidenceError): + verdict(bundle) + + +def test_modified_artifact_rejected(bundle): + (bundle[0] / "pytest.log").write_text("tampered") + with pytest.raises(q.EvidenceError, match="artifact_modified"): + verdict(bundle) + + +@pytest.mark.parametrize("value", ["main", "a" * 39, "z" * 40, True]) +def test_invalid_candidate_sha(bundle, value): + bundle[2]["candidate"]["git_sha"] = value + with pytest.raises(q.EvidenceError, match="invalid_candidate_sha"): + verdict(bundle) + + +def test_source_identity_mismatch(bundle): + bundle[3]["candidate"]["snapshot_sha256"] = "e" * 64 + refresh(bundle) + with pytest.raises(q.EvidenceError, match="test_source_identity_mismatch"): + verdict(bundle) + + +def test_absent_fixture_never_passes(bundle): + bundle[1]["cases"][0]["stages"][0]["nodes"][0]["fixtures"] = [ + {"path": "fixtures/missing.json", "sha256": "e" * 64} + ] + refresh(bundle) + assert not verdict(bundle)["checks_only_complete"] + + +def test_source_digest_not_current_cannot_pass(bundle): + bundle[1]["cases"][0]["stages"][0]["nodes"][0]["source"]["sha256"] = "e" * 64 + refresh(bundle) + assert not verdict(bundle)["checks_only_complete"] + + +def test_unit_stub_cannot_be_product_acceptance(bundle): + bundle[3]["records"][0]["kind"] = "unit_stub" + refresh(bundle) + assert not verdict(bundle)["checks_only_complete"] + + +def test_synthetic_measurement_cannot_claim_unrun_real_comparison(bundle): + bundle[2]["benchmark_measurement"] = { + "workload": "real_donor", + "synthetic": True, + "latency": 0, + } + with pytest.raises(q.EvidenceError, match="unreviewed_benchmark_claim"): + verdict(bundle) + + +def test_empty_pytest_collection_never_passes(bundle): + bundle[3].update(collected=[], records=[], collection_count=0) + refresh(bundle) + assert not verdict(bundle)["checks_only_complete"] + + +def test_missing_expected_node_never_passes(bundle): + bundle[1]["cases"][0]["stages"][0]["nodes"][0]["node_id"] += "_missing" + refresh(bundle) + assert not verdict(bundle)["checks_only_complete"] + + +@pytest.mark.parametrize( + "phase,outcome", [("call", "failed"), ("setup", "skipped"), ("teardown", "failed")] +) +def test_nonpass_retains_case_and_count(bundle, phase, outcome): + record = bundle[3]["records"][0] + record["phases"][phase] = outcome + record["status"] = outcome + refresh(bundle) + result = verdict(bundle) + assert not result["checks_only_complete"] and result["case_count"] == 1 + assert result["test_counts"][outcome] == 1 + + +def test_missing_teardown_is_unknown(bundle): + record = bundle[3]["records"][0] + del record["phases"]["teardown"] + record["status"] = "unknown" + refresh(bundle) + assert verdict(bundle)["test_counts"]["unknown"] == 1 + + +def test_claimed_pass_with_failed_phase_rejected(bundle): + bundle[3]["records"][0]["phases"]["call"] = "failed" + refresh(bundle) + with pytest.raises(q.EvidenceError, match="false_test_pass"): + verdict(bundle) + + +def test_duplicate_test_record_rejected(bundle): + bundle[3]["records"].append(copy.deepcopy(bundle[3]["records"][0])) + refresh(bundle) + with pytest.raises(q.EvidenceError, match="duplicate_or_uncollected_test"): + verdict(bundle) + + +def test_truncated_logs_never_pass(bundle): + bundle[2]["commands"][0]["log_truncated"] = True + assert not verdict(bundle)["checks_only_complete"] + + +def test_missing_checker_retains_existing_finding(bundle): + bundle[2]["findings"] = ["known_prior_failure"] + bundle[2]["commands"].pop() + result = verdict(bundle) + assert result["findings"] and not result["checks_only_complete"] + + +def test_dirty_release_refused_worktree_labeled(bundle): + bundle[2]["candidate"]["dirty"] = True + bundle[3]["candidate"]["dirty"] = True + refresh(bundle) + with pytest.raises(q.EvidenceError, match="dirty_release"): + verdict(bundle) + bundle[2]["mode"] = "worktree" + assert "worktree_candidate" in verdict(bundle)["release_blockers"] + + +def test_artifact_escape_and_symlink_refused(tmp_path): + (tmp_path / "target").write_text("x") + (tmp_path / "link").symlink_to(tmp_path / "target") + for name in ["../outside", "/etc/passwd", "link", "a\\b"]: + with pytest.raises(q.EvidenceError): + q.artifact(tmp_path, name) + + +def test_exclusive_report_creation(tmp_path): + path = tmp_path / "report.json" + q.write_json(path, {"original": True}) + with pytest.raises(FileExistsError): + q.write_json(path, {"changed": True}) + assert q.strict_json(path) == {"original": True} + + +def child(tmp_path, code, *, seconds=2, max_bytes=4096, cancel=None): + return q.run_command( + [sys.executable, "-I", "-c", code], + cwd=tmp_path, + env=q.clean_env(tmp_path, Path(sys.executable)), + log=tmp_path / "child.log", + deadline=time.monotonic() + seconds, + timeout=seconds, + max_bytes=max_bytes, + cancel=cancel, + ) + + +def test_process_both_pipes_drained_and_output_bounded(tmp_path): + result = child( + tmp_path, + 'import os\nwhile True:\n os.write(1,b"a"*8192)\n os.write(2,b"b"*8192)', + ) + assert result["status"] == "output_limit" + assert result["log_truncated"] and (tmp_path / "child.log").stat().st_size == 4096 + + +def test_process_nonzero_has_no_automatic_retry(tmp_path): + result = child(tmp_path, 'import sys; print("once"); sys.exit(7)') + assert result["status"] == "failed" and result["exit_code"] == 7 + assert (tmp_path / "child.log").read_text() == "once\n" + + +def test_process_timeout_reaps_leader(tmp_path): + result = child(tmp_path, "import time; time.sleep(60)", seconds=0.2) + assert result["status"] == "timeout" and result["exit_code"] == -signal.SIGKILL + assert result["elapsed_seconds"] < 2 + + +def test_process_cancellation(tmp_path): + cancel = threading.Event() + timer = threading.Timer(0.1, cancel.set) + timer.start() + try: + result = child(tmp_path, "import time; time.sleep(60)", cancel=cancel) + finally: + timer.join() + assert result["status"] == "cancelled" + + +def test_exited_parent_with_grandchild_pipes_times_out(tmp_path): + result = child( + tmp_path, + 'import subprocess,sys; subprocess.Popen([sys.executable,"-I","-c","import time; time.sleep(60)"])', + seconds=0.2, + ) + assert result["status"] == "timeout" and result["elapsed_seconds"] < 2 + + +def test_deadline_exhausted_does_not_launch(tmp_path): + result = q.run_command( + [sys.executable, "-c", "raise Exception()"], + cwd=tmp_path, + env={}, + log=tmp_path / "child.log", + deadline=time.monotonic() - 1, + ) + assert result["status"] == "timeout" and result["exit_code"] is None + + +def test_environment_excludes_ambient_keys_and_pythonpath(tmp_path, monkeypatch): + monkeypatch.setenv("OPENAI_API_KEY", "sentinel") + monkeypatch.setenv("PYTHONPATH", "/bad") + monkeypatch.setenv("PYTEST_ADDOPTS", "--bad") + monkeypatch.setenv("PIP_INDEX_URL", "https://secret") + result = child(tmp_path, "import os,json; print(json.dumps(dict(os.environ)))") + assert result["status"] == "passed" + env = json.loads((tmp_path / "child.log").read_text()) + assert ( + not {"OPENAI_API_KEY", "PYTHONPATH", "PYTEST_ADDOPTS", "PIP_INDEX_URL"} + & env.keys() + ) + + +def test_verification_import_never_executes_argv(bundle, monkeypatch): + bundle[2]["commands"][0]["argv"] = ["sh", "-c", "arbitrary effects"] + monkeypatch.setattr( + q.subprocess, "Popen", lambda *a, **k: pytest.fail("executed evidence") + ) + verdict(bundle) + + +def test_installed_smoke_missing_checks_is_not_a_pass(bundle): + root = bundle[0] + smoke = q.strict_json(root / "installed-results.json") + smoke["checks"].pop("missing_adapter_capability") + save(root / "installed-results.json", smoke) + refresh(bundle) + with pytest.raises(q.EvidenceError, match="invalid_smoke_checks"): + verdict(bundle) + + +def test_installed_smoke_failure_blocks_generic_pytest_success(bundle): + root = bundle[0] + smoke = q.strict_json(root / "installed-results.json") + smoke["checks"]["missing_adapter_capability"] = "not_run" + save(root / "installed-results.json", smoke) + refresh(bundle) + assert not verdict(bundle)["checks_only_complete"] + + +def test_real_pytest_plugin_records_exact_nodes_and_teardown(tmp_path): + repo = Path(__file__).resolve().parents[1] + (tmp_path / "test_sample.py").write_text("def test_one():\n assert 2 + 2 == 4\n") + output = tmp_path / "pytest-results.json" + context = tmp_path / "context.json" + q.write_json( + context, + {"repo": str(tmp_path), "output": str(output), "candidate": {}, "kinds": {}}, + ) + env = q.clean_env(tmp_path, Path(sys.executable), repo) + env["JITMIND_QUALIFICATION_CONTEXT"] = str(context) + result = q.run_command( + [ + sys.executable, + "-m", + "pytest", + "-q", + "-p", + "scripts.qualify_jitmind", + "test_sample.py", + ], + cwd=tmp_path, + env=env, + log=tmp_path / "pytest.log", + deadline=time.monotonic() + 10, + ) + assert result["status"] == "passed", (tmp_path / "pytest.log").read_text() + record = q.strict_json(output) + assert record["collected"] == ["test_sample.py::test_one"] + assert record["collection_count"] == 1 + assert record["records"][0]["phases"] == dict.fromkeys( + ["setup", "call", "teardown"], "passed" + ) + assert record["records"][0]["kind"] == "unmapped" + + +def test_shipped_map_preserves_32_cases_41_stages_and_not_run(): + path = Path(__file__).resolve().parents[1] / "docs/engineering/acceptance-map.json" + mapping = q.strict_json(path) + cases = q.validate_map(mapping) + assert len(cases) == 32 and sum(len(c["stages"]) for c in cases) == 41 + assert all(c["status"] == "not_run" for c in cases) + assert [x[-1] for x in mapping["temporal_oracle"]["answers"]] == [ + 3, + 3, + 4, + 3, + 4, + 5, + 3, + ] + + +def test_missing_test_artifact_measurements_are_null(bundle): + bundle[3].update( + available=False, collected=[], collection_count=None, records=[], exit_code=99 + ) + refresh(bundle) + result = verdict(bundle) + assert result["collection_count"] is None + assert result["test_counts"] == dict.fromkeys( + ["passed", "failed", "skipped", "unknown"] + ) + assert not result["checks_only_complete"] + + +def test_tool_tests_cannot_be_mapped_as_product_acceptance(bundle): + bundle[1]["cases"][0]["stages"][0]["nodes"][0]["node_id"] = ( + "tests/test_qualification.py::test_fake" + ) + refresh(bundle) + with pytest.raises(q.EvidenceError, match="tool_test_is_not_acceptance"): + verdict(bundle) + + +def test_unknown_external_finding_is_retained_without_echoing_payload(bundle): + bundle[2]["findings"] = ["private-path API_KEY=negative-sentinel"] + result = verdict(bundle) + assert result["findings"] == ["retained_external_finding"] + assert "negative-sentinel" not in json.dumps(result) + + +def test_timeout_kills_owned_grandchild(tmp_path): + import os + + pid_path = tmp_path / "grandchild.pid" + script = ( + "import pathlib,subprocess,sys,time; " + 'p=subprocess.Popen([sys.executable,"-I","-c","import time; time.sleep(60)"]); ' + f"pathlib.Path({str(pid_path)!r}).write_text(str(p.pid)); time.sleep(60)" + ) + result = child(tmp_path, script, seconds=1) + assert result["status"] == "timeout" + pid = int(pid_path.read_text()) + until = time.monotonic() + 2 + while time.monotonic() < until: + try: + os.kill(pid, 0) + except ProcessLookupError: + return + linux_state = Path(f"/proc/{pid}/stat") + if linux_state.exists() and linux_state.read_text().split()[2] == "Z": + return # direct child is reaped; orphan zombie belongs to OS init + time.sleep(0.01) + pytest.fail("owned grandchild remained live after timeout") + + +@pytest.mark.parametrize("target", ["command_exit", "artifact_bytes"]) +def test_evidence_boolean_numeric_fields_refused(bundle, target): + if target == "command_exit": + bundle[2]["commands"][0]["exit_code"] = False + else: + bundle[2]["artifacts"][0]["bytes"] = True + with pytest.raises(q.EvidenceError): + verdict(bundle) + + +def test_json_symlinks_and_special_files_refused(tmp_path): + import os + + path = tmp_path / "fifo" + os.mkfifo(path) + with pytest.raises(q.EvidenceError): + q.strict_json(path) + target = tmp_path / "real.json" + target.write_text("{}") + link = tmp_path / "link.json" + link.symlink_to(target) + with pytest.raises(q.EvidenceError): + q.strict_json(link) + + +def test_hashing_observes_exhausted_deadline(tmp_path): + path = tmp_path / "source" + path.write_bytes(b"source bytes") + with pytest.raises(q.EvidenceError, match="overall_deadline"): + q.digest(path, deadline=time.monotonic() - 1) diff --git a/tests/test_qualification_contracts.py b/tests/test_qualification_contracts.py new file mode 100644 index 0000000..c9b935c --- /dev/null +++ b/tests/test_qualification_contracts.py @@ -0,0 +1,32 @@ +"""Reporting-contract controls, not installed-product acceptance evidence.""" + +import pytest + +from jitmind.code_context.process import Unavailable +from test_standalone_install import missing_adapter_capability + + +def test_smoke_accepts_real_typed_missing_runtime(tmp_path): + missing_adapter_capability(tmp_path) + + +@pytest.mark.parametrize( + "error,expected", + [ + (Unavailable("unrelated_failure"), AssertionError), + (Unavailable("runtime_unavailable"), AssertionError), + (FileNotFoundError("node_executable_unavailable"), FileNotFoundError), + (AttributeError("node_executable_unavailable"), AttributeError), + ], +) +def test_smoke_does_not_accept_wrong_reason_or_untyped_error( + tmp_path, monkeypatch, error, expected +): + import jitmind.code_context as module + + def fail(**kwargs): + raise error + + monkeypatch.setattr(module, "NodeParser", fail) + with pytest.raises(expected): + missing_adapter_capability(tmp_path) diff --git a/tests/test_qualification_regressions.py b/tests/test_qualification_regressions.py new file mode 100644 index 0000000..e7e12ff --- /dev/null +++ b/tests/test_qualification_regressions.py @@ -0,0 +1,493 @@ +"""Reproduced review defects; controlled tool evidence, never acceptance credit.""" + +import copy +import hashlib +import json +import os +from pathlib import Path +import signal +import subprocess +import sys +import time + +import pytest + +from scripts import qualify_jitmind as q +import test_qualification as helpers +from test_qualification import refresh, verdict + + +@pytest.fixture +def bundle(tmp_path): + return helpers.bundle.__wrapped__(tmp_path) + + +def rejected(bundle): + try: + assert not verdict(bundle)["checks_only_complete"] + except q.EvidenceError: + pass + + +@pytest.mark.parametrize( + "corruption", ["digest", "bytes", "missing", "duplicate", "alias"] +) +def test_snapshot_roster_is_bound(bundle, corruption): + identity = bundle[2]["candidate"] + name = "tests/test_product.py" + roster = [[name, q.digest(bundle[0] / "sources" / name)]] + if corruption == "bytes": + roster[0][1] = "e" * 64 + elif corruption == "missing": + roster.append(["absent.py", "e" * 64]) + elif corruption == "duplicate": + roster *= 2 + elif corruption == "alias": + roster[0][0] = "tests/./test_product.py" + identity["snapshot_files"] = roster + identity["snapshot_sha256"] = hashlib.sha256( + json.dumps(roster, separators=(",", ":")).encode() + ).hexdigest() + if corruption == "digest": + identity["snapshot_sha256"] = "e" * 64 + bundle[3]["candidate"] = copy.deepcopy(identity) + refresh(bundle) + rejected(bundle) + + +@pytest.mark.parametrize("mode", ["filter", "skip", "importorskip", "error"]) +def test_real_collection_omissions_are_recorded(tmp_path, mode): + (tmp_path / "tests").mkdir() + (tmp_path / "tests/test_good.py").write_text( + "def test_expected(): pass\ndef test_other(): pass\n" + ) + if mode == "filter": + (tmp_path / "pytest.ini").write_text("[pytest]\naddopts = -k test_expected\n") + else: + text = { + "skip": 'import pytest\npytest.skip("collection", allow_module_level=True)', + "importorskip": 'import pytest\npytest.importorskip("jitmind_nonexistent_fixture_module")', + "error": 'raise RuntimeError("collection failure")', + }[mode] + (tmp_path / "tests/test_bad.py").write_text(text) + output = tmp_path / "pytest-results.json" + q.write_json( + tmp_path / "context.json", + {"repo": str(tmp_path), "output": str(output), "candidate": {}, "kinds": {}}, + ) + env = q.clean_env( + tmp_path, Path(sys.executable), Path(__file__).resolve().parents[1] + ) + env["JITMIND_QUALIFICATION_CONTEXT"] = str(tmp_path / "context.json") + q.run_command( + [ + sys.executable, + "-m", + "pytest", + "-q", + "-p", + "no:cacheprovider", + "-p", + "scripts.qualify_jitmind", + "tests", + ], + cwd=tmp_path, + env=env, + log=tmp_path / "pytest.log", + deadline=time.monotonic() + 10, + ) + data = q.strict_json(output) + expected = q.strict_json(tmp_path / "expected-collection.json") + assert len(expected["nodes"]) == 2 + if mode == "filter": + assert expected["deselected"] == ["tests/test_good.py::test_other"] + assert expected["filtered"] is True + else: + assert expected["collection_reports"][-1]["outcome"] == ( + "failed" if mode == "error" else "skipped" + ) + assert data["expected_collection_sha256"] == q.digest( + tmp_path / "expected-collection.json" + ) + + +def test_oversized_copy_rejected_before_destination(tmp_path, monkeypatch): + monkeypatch.setattr(q, "MAX_ARTIFACT", 4096) + src, dst = tmp_path / "large.whl", tmp_path / "copy.whl" + src.write_bytes(b"x" * 5000) + with pytest.raises(q.EvidenceError, match="artifact_too_large"): + q.bounded_copy(src, dst) + assert not dst.exists() + + +def alive(pid): + try: + os.kill(pid, 0) + except ProcessLookupError: + return False + stat = Path(f"/proc/{pid}/stat") + return not (stat.exists() and stat.read_text().split()[2] == "Z") + + +@pytest.mark.parametrize("sig", [signal.SIGINT, signal.SIGTERM]) +def test_signal_wrapper_cleans_owned_descendants(tmp_path, sig): + repo = Path(__file__).resolve().parents[1] + grand = "import time; time.sleep(60)" + code = f'import os,pathlib,subprocess,sys,time; p=subprocess.Popen([sys.executable,"-c",{grand!r}]); pathlib.Path("pids").write_text(str(os.getpid())+" "+str(p.pid)); time.sleep(60)' + wrapper = f'from scripts import qualify_jitmind as q; from pathlib import Path; import sys,time,json; p=Path.cwd(); r=q.run_command([sys.executable,"-c",{code!r}],cwd=p,env=q.clean_env(p,Path(sys.executable)),log=p/"child.log",deadline=time.monotonic()+10); print(json.dumps(r))' + pids = [] + with (tmp_path / "wrapper.log").open("wb") as log: + proc = subprocess.Popen( + [sys.executable, "-c", wrapper], + cwd=tmp_path, + env=q.clean_env(tmp_path, Path(sys.executable), repo), + stdout=log, + stderr=log, + ) + try: + end = time.monotonic() + 5 + while not (tmp_path / "pids").exists() and time.monotonic() < end: + time.sleep(0.01) + pids = [int(x) for x in (tmp_path / "pids").read_text().split()] + proc.send_signal(sig) + assert proc.wait(timeout=3) == 0 + assert ( + json.loads((tmp_path / "wrapper.log").read_text())["status"] + == "cancelled" + ) + end = time.monotonic() + 2 + while any(alive(pid) for pid in pids) and time.monotonic() < end: + time.sleep(0.01) + assert not any(alive(pid) for pid in pids) + finally: + if proc.poll() is None: + proc.kill() + proc.wait(timeout=3) + for pid in pids: + try: + os.kill(pid, signal.SIGKILL) + except ProcessLookupError: + pass + + +def test_deleting_unmapped_failure_does_not_shrink_expected_collection(bundle): + root, _, _, tests = bundle + extra = "tests/test_product.py::test_unmapped_failure" + expected = q.strict_json(root / "expected-collection.json") + expected["nodes"].append(extra) + expected["selected"].append(extra) + (root / "expected-collection.json").write_text(json.dumps(expected)) + tests["collected"].append(extra) + tests["collection_count"] += 1 + tests["records"].append( + dict( + node_id=extra, + kind="unmapped", + source_sha256=tests["records"][0]["source_sha256"], + status="failed", + phases=dict(setup="passed", call="failed", teardown="passed"), + ) + ) + tests["exit_code"] = 1 + refresh(bundle) + assert not verdict(bundle)["checks_only_complete"] + tests["records"].pop() + tests["collected"].pop() + tests["collection_count"] -= 1 + tests["exit_code"] = 0 + refresh(bundle) + assert not verdict(bundle)["checks_only_complete"] + + +def test_missing_unmapped_record_retains_unknown_denominator(bundle): + root, _, _, tests = bundle + extra = "tests/test_product.py::test_missing_record" + expected = q.strict_json(root / "expected-collection.json") + expected["nodes"].append(extra) + expected["selected"].append(extra) + (root / "expected-collection.json").write_text(json.dumps(expected)) + tests["collected"].append(extra) + tests["collection_count"] += 1 + refresh(bundle) + result = verdict(bundle) + assert not result["checks_only_complete"] + assert result["test_counts"]["unknown"] == 1 + + +@pytest.mark.parametrize("field", ["nodes", "selected", "deselected"]) +def test_duplicate_collection_nodes_refused(bundle, field): + path = bundle[0] / "expected-collection.json" + expected = q.strict_json(path) + expected[field] = expected["nodes"] * 2 + path.write_text(json.dumps(expected)) + refresh(bundle) + with pytest.raises(q.EvidenceError, match="duplicate_or_invalid_collection"): + verdict(bundle) + + +@pytest.mark.parametrize( + "field,value", + [ + ("session_testscollected", 2), + ("session_testsfailed", 1), + ("session_testsfailed", False), + ("phase_counts", {"passed": 4, "failed": 0, "skipped": 0}), + ], +) +def test_inconsistent_plugin_counters_refused(bundle, field, value): + bundle[3][field] = value + (bundle[0] / "pytest-results.json").write_text(json.dumps(bundle[3])) + refresh(bundle, tests=False) + with pytest.raises(q.EvidenceError, match="inconsistent_plugin_counters"): + verdict(bundle) + + +@pytest.mark.parametrize("field", ["filtered", "deselected", "collection_reports"]) +def test_collection_incompleteness_blocks_evaluator(bundle, field): + path = bundle[0] / "expected-collection.json" + expected = q.strict_json(path) + if field == "filtered": + expected[field] = True + elif field == "deselected": + expected["nodes"].append("tests/test_product.py::test_omitted") + expected[field] = ["tests/test_product.py::test_omitted"] + else: + expected[field] = [{"node_id": "tests/test_skip.py", "outcome": "skipped"}] + path.write_text(json.dumps(expected)) + refresh(bundle) + assert not verdict(bundle)["checks_only_complete"] + + +def test_runtime_record_source_must_match_snapshot(bundle): + bundle[3]["records"][0]["source_sha256"] = "e" * 64 + refresh(bundle) + with pytest.raises(q.EvidenceError, match="record_source_mismatch"): + verdict(bundle) + + +def test_expected_collection_identity_and_digest_are_independent(bundle): + bundle[3]["expected_collection_sha256"] = "e" * 64 + (bundle[0] / "pytest-results.json").write_text(json.dumps(bundle[3])) + refresh(bundle, tests=False) + with pytest.raises(q.EvidenceError, match="collection_digest_mismatch"): + verdict(bundle) + + +@pytest.mark.parametrize("change", ["grow", "replace", "same_size"]) +def test_copy_rejects_source_change_during_stream(tmp_path, monkeypatch, change): + source, dest = tmp_path / "source", tmp_path / "dest" + source.write_bytes(b"a" * 32) + monkeypatch.setattr(q, "MAX_ARTIFACT", 64) + real_fdopen = os.fdopen + requests = [] + + class ChangingReader: + def __init__(self, fd, mode, **kwargs): + self.stream = real_fdopen(fd, mode, **kwargs) + self.changed = False + + def __enter__(self): + return self + + def __exit__(self, *args): + self.stream.close() + + def fileno(self): + return self.stream.fileno() + + def read(self, size): + requests.append(size) + if not self.changed: + self.changed = True + if change == "grow": + with source.open("ab") as out: + out.write(b"b" * 64) + elif change == "replace": + other = tmp_path / "replacement" + other.write_bytes(b"a" * 32) + other.replace(source) + else: + source.write_bytes(b"b" * 32) + return self.stream.read(size) + + monkeypatch.setattr(q.os, "fdopen", ChangingReader) + with pytest.raises( + q.EvidenceError, match="artifact_too_large|source_changed_during_copy" + ): + q.bounded_copy(source, dest) + assert max(requests) <= 65 + assert not dest.exists() + + +def test_copy_exclusive_hash_deadline_and_exact_limit(tmp_path, monkeypatch): + source, dest = tmp_path / "source", tmp_path / "dest" + source.write_bytes(b"a" * 64) + monkeypatch.setattr(q, "MAX_ARTIFACT", 64) + assert q.bounded_copy(source, dest, expected_hash=q.digest(source)) == q.digest( + dest + ) + with pytest.raises(FileExistsError): + q.bounded_copy(source, dest) + assert dest.read_bytes() == b"a" * 64 + dest.unlink() + with pytest.raises(q.EvidenceError, match="source_hash_mismatch"): + q.bounded_copy(source, dest, expected_hash="e" * 64) + assert not dest.exists() + with pytest.raises(q.EvidenceError, match="overall_deadline"): + q.bounded_copy(source, dest, deadline=time.monotonic() - 1) + assert not dest.exists() + + +def test_copy_symlink_refused(tmp_path): + source = tmp_path / "source" + source.symlink_to(__file__) + with pytest.raises(q.EvidenceError, match="artifact_missing_or_symlink"): + q.bounded_copy(source, tmp_path / "dest") + + +def test_signals_restored_and_worker_threads_do_not_mutate_signals( + tmp_path, monkeypatch +): + import threading + + previous = signal.getsignal(signal.SIGTERM) + seen = [] + real_signal = signal.signal + + def observed(*args): + seen.append(threading.current_thread()) + return real_signal(*args) + + monkeypatch.setattr(q.signal, "signal", observed) + + def run(name): + return q.run_command( + [sys.executable, "-c", 'print("done")'], + cwd=tmp_path, + env=q.clean_env(tmp_path, Path(sys.executable)), + log=tmp_path / name, + deadline=time.monotonic() + 3, + ) + + assert run("main.log")["status"] == "passed" + assert signal.getsignal(signal.SIGTERM) is previous + assert len(seen) == 2 + results = [] + thread = threading.Thread(target=lambda: results.append(run("thread.log"))) + thread.start() + thread.join(timeout=5) + assert not thread.is_alive() + assert results[0]["status"] == "passed" + assert len(seen) == 2 + + +@pytest.mark.parametrize("mode", ["normal", "timeout", "loglimit"]) +def test_owned_group_cleanup_does_not_kill_unrelated_child(tmp_path, mode): + other = subprocess.Popen([sys.executable, "-c", "import time; time.sleep(30)"]) + pids = [] + grand = "import time; time.sleep(30)" + ending = { + "normal": "sys.exit(0)", + "timeout": "time.sleep(30)", + "loglimit": '\nwhile True: os.write(1,b"x"*8192)', + }[mode] + script = f'import os,pathlib,subprocess,sys,time; p=subprocess.Popen([sys.executable,"-c",{grand!r}],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL); pathlib.Path("pids").write_text(str(os.getpid())+" "+str(p.pid)); {ending}' + try: + result = q.run_command( + [sys.executable, "-c", script], + cwd=tmp_path, + env=q.clean_env(tmp_path, Path(sys.executable)), + log=tmp_path / "child.log", + deadline=time.monotonic() + 1, + max_bytes=100, + ) + pids = list(map(int, (tmp_path / "pids").read_text().split())) + assert ( + result["status"] + == {"normal": "passed", "timeout": "timeout", "loglimit": "output_limit"}[ + mode + ] + ) + end = time.monotonic() + 2 + while any(alive(pid) for pid in pids) and time.monotonic() < end: + time.sleep(0.01) + assert not any(alive(pid) for pid in pids) + assert other.poll() is None + finally: + other.kill() + other.wait(timeout=3) + for pid in pids: + try: + os.kill(pid, signal.SIGKILL) + except ProcessLookupError: + pass + + +def test_real_plugin_result_evaluates_with_attested_source(bundle, tmp_path): + root, _, report, tests = bundle + execution = root / "execution" + execution.mkdir() + q.write_json( + execution / "context.json", + { + "repo": str(root / "sources"), + "output": str(execution / "pytest-results.json"), + "candidate": report["candidate"], + "kinds": {tests["collected"][0]: "real_storage"}, + }, + ) + env = q.clean_env( + execution, Path(sys.executable), Path(__file__).resolve().parents[1] + ) + env["JITMIND_QUALIFICATION_CONTEXT"] = str(execution / "context.json") + result = q.run_command( + [ + sys.executable, + "-m", + "pytest", + "-q", + "-p", + "no:cacheprovider", + "-p", + "scripts.qualify_jitmind", + "tests", + ], + cwd=root / "sources", + env=env, + log=execution / "pytest.log", + deadline=time.monotonic() + 10, + ) + assert result["status"] == "passed" + for name in ("pytest-results.json", "expected-collection.json"): + (root / name).write_bytes((execution / name).read_bytes()) + refresh(bundle, tests=False) + assert verdict(bundle)["checks_only_complete"] + + +def test_normal_completion_closes_both_pipes(tmp_path, monkeypatch): + real_popen = q.subprocess.Popen + children = [] + + def capture(*args, **kwargs): + child = real_popen(*args, **kwargs) + children.append(child) + return child + + monkeypatch.setattr(q.subprocess, "Popen", capture) + previous = signal.getsignal(signal.SIGTERM) + handler = lambda _signum, _frame: None + signal.signal(signal.SIGTERM, handler) + try: + result = q.run_command( + [sys.executable, "-c", 'print("ok")'], + cwd=tmp_path, + env=q.clean_env(tmp_path, Path(sys.executable)), + log=tmp_path / "child.log", + deadline=time.monotonic() + 3, + ) + assert result["status"] == "passed" + assert signal.getsignal(signal.SIGTERM) is handler + assert children[0].returncode == 0 + assert children[0].stdout.closed and children[0].stderr.closed + finally: + signal.signal(signal.SIGTERM, previous) diff --git a/tests/test_standalone_install.py b/tests/test_standalone_install.py new file mode 100644 index 0000000..b60f955 --- /dev/null +++ b/tests/test_standalone_install.py @@ -0,0 +1,216 @@ +"""Executable installed-wheel smoke. No pytest dependency in the installed venv. + +Run only with: /bin/python -I /tests/test_standalone_install.py + --installed-smoke +A pytest run of this file tests smoke guards; it is NOT installed acceptance. +""" + +from __future__ import annotations + +import argparse +import hashlib +import importlib.metadata +import importlib.util +import json +import os +from pathlib import Path +import shutil +import socket +import sqlite3 +import sys +import tempfile + +SMOKE_NODE = "tests/test_standalone_install.py::installed_smoke" +CHECKS = { + "isolated_origin", + "optional_dependencies_absent", + "legacy_memory_research", + "optional_adapter_import", + "missing_adapter_capability", +} + + +def verify_isolation(venv: Path, origin: Path) -> None: + assert sys.flags.isolated == 1, "isolated_interpreter_required" + assert "PYTHONPATH" not in os.environ, "pythonpath_must_be_absent" + assert Path(sys.prefix).resolve() == venv.resolve(), "wrong_virtual_environment" + assert sys.prefix != sys.base_prefix, "fresh_virtual_environment_required" + assert origin.resolve().is_relative_to(venv.resolve()), "checkout_import_refused" + checkout = Path(__file__).resolve().parents[1] + assert not Path.cwd().resolve().is_relative_to(checkout), "checkout_cwd_refused" + assert not any(Path(p).resolve() == checkout for p in sys.path if p), ( + "checkout_path_refused" + ) + + +def legacy_roundtrip(directory: Path) -> None: + from jitmind import MemoryAgent, ResearchAgent + from jitmind.schemas import InMemoryMemoryStore, InMemoryPageStore + + class FakeGenerator: + def __init__(self): + self.calls = [] + + def generate_single(self, prompt=None, schema=None, **kwargs): + self.calls.append(schema) + properties = (schema or {}).get("properties", {}) + if "operation" in properties: + return {"json": {"operation": "add"}} + if "info_needs" in properties: + return {"json": {"tools": ["page_index"], "page_index": [0]}} + if "content" in properties: + assert "cobalt" in prompt, "retrieved_page_missing_from_prompt" + return {"json": {"content": "cobalt preference", "sources": ["0"]}} + if "enough" in properties: + return {"json": {"enough": True}} + if schema is None: + return {"text": "cobalt preference"} + raise AssertionError("unexpected_generator_contract") + + generator = FakeGenerator() + memory = InMemoryMemoryStore(dir_path=str(directory)) + pages = InMemoryPageStore(dir_path=str(directory)) + agent = MemoryAgent(memory_store=memory, page_store=pages, generator=generator) + result = agent.memorize("cobalt is the user's preferred color") + assert result.new_state.abstracts == ["cobalt preference"] + memory = InMemoryMemoryStore(dir_path=str(directory)) + pages = InMemoryPageStore(dir_path=str(directory)) + assert memory.load().abstracts == ["cobalt preference"] + assert pages.get(0).content == "cobalt is the user's preferred color" + research = ResearchAgent( + page_store=pages, + memory_store=memory, + generator=generator, + max_iters=1, + enable_hyde=False, + enable_self_rag=False, + ) + answer = research.research("preferred color") + assert answer.integrated_memory == "cobalt preference" + assert answer.raw_memory["temp_memory"]["sources"] == ["0"] + assert len(generator.calls) == 5, "public_api_did_not_use_expected_generator_calls" + + +def missing_adapter_capability(directory: Path) -> None: + """Exercise actual public missing-runtime handling, never a mocked parser. + + This deliberately fails until the assembled adapter supports an absent runtime + with a typed capability failure or an unavailable result. Arbitrary IO/import + exceptions and AttributeError are not meaningful capability errors. + """ + from jitmind.code_context import NodeParser + from jitmind.code_context.process import Unavailable + + try: + NodeParser( + node_binary=str(directory / "absent-node"), + adapter_dir=str(directory / "absent-adapter"), + ) + except Unavailable as error: + assert error.reason == "node_executable_unavailable" + else: + raise AssertionError("missing_runtime_requires_capability_error") + + +def installed_smoke(venv: Path) -> dict: + results = {name: "not_run" for name in sorted(CHECKS)} + report = { + "schema": "jitmind.installed-smoke/v1", + "node_id": SMOKE_NODE, + "checks": results, + "status": "failed", + "kind": "installed_package", + "source_sha256": hashlib.sha256(Path(__file__).read_bytes()).hexdigest(), + "dependencies": None, + "sqlite_pragmas": None, + "product_storage_diagnostics": None, + "provider_calls": 0, + "network_policy": "socket_connections_denied", + } + + def no_network(*args, **kwargs): + raise AssertionError("network_forbidden_in_standalone_smoke") + + # Prevent accidental live provider connections even if a regression adds one. + socket.socket.connect = no_network + socket.socket.connect_ex = no_network + socket.create_connection = no_network + try: + results["isolated_origin"] = "failed" + import jitmind + + verify_isolation(venv, Path(jitmind.__file__)) + results["isolated_origin"] = "passed" + report["origin"] = str( + Path(jitmind.__file__).resolve().relative_to(venv.resolve()) + ) + report["dependencies"] = sorted( + [ + [d.metadata["Name"], d.version] + for d in importlib.metadata.distributions() + ] + ) + results["optional_dependencies_absent"] = "failed" + assert all( + importlib.util.find_spec(name) is None + for name in ("cohere", "neo4j", "faiss") + ) + assert shutil.which("node") is None, "node_must_be_absent_from_smoke_path" + results["optional_dependencies_absent"] = "passed" + with tempfile.TemporaryDirectory(prefix="jitmind-installed-") as temp: + directory = Path(temp) + results["legacy_memory_research"] = "failed" + legacy_roundtrip(directory) + results["legacy_memory_research"] = "passed" + with sqlite3.connect(directory / "probe.sqlite") as connection: + report["sqlite_pragmas"] = { + key: connection.execute("PRAGMA " + key).fetchone()[0] + for key in ("journal_mode", "synchronous", "foreign_keys") + } + if importlib.util.find_spec("jitmind.storage") is not None: + from jitmind.storage import SQLiteDurableStore + + report["product_storage_diagnostics"] = SQLiteDurableStore( + directory / "authority.sqlite" + ).diagnostics() + # Import must work independently of the optional native dependency. + results["optional_adapter_import"] = "failed" + import jitmind.code_context # noqa: F401 + + results["optional_adapter_import"] = "passed" + results["missing_adapter_capability"] = "failed" + missing_adapter_capability(directory) + results["missing_adapter_capability"] = "passed" + report["status"] = "passed" + except Exception: + # Do not expose paths, provider payloads, or arbitrary exception strings. + report["error"] = "installed_contract_failed" + return report + + +def test_checkout_cannot_masquerade_as_installed_package(tmp_path): + import pytest + + with pytest.raises(AssertionError): + verify_isolation(tmp_path, Path(__file__)) + + +def test_legacy_fake_generator_roundtrip_is_a_checkout_unit_check(tmp_path): + legacy_roundtrip(tmp_path) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--installed-smoke", action="store_true", required=True) + parser.add_argument("venv", type=Path) + parser.add_argument("result", type=Path) + args = parser.parse_args() + result = installed_smoke(args.venv) + with args.result.open("x", encoding="utf-8") as stream: + json.dump(result, stream, allow_nan=False, sort_keys=True, indent=2) + print( + json.dumps( + {"status": result["status"], "checks": result["checks"]}, sort_keys=True + ) + ) + raise SystemExit(0 if result["status"] == "passed" else 1) From fa91dc003261924a46fc3e5009a45fdecabe72cf Mon Sep 17 00:00:00 2001 From: Divyam Talwar Date: Tue, 29 Sep 2026 01:32:03 +0530 Subject: [PATCH 2/8] test(preflight): separate expiry semantics from scheduler timing --- docs/open-work-preflight.md | 6 ++++++ tests/test_open_work_bindings.py | 4 ++++ tests/test_preflight.py | 14 +++++++++++--- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/docs/open-work-preflight.md b/docs/open-work-preflight.md index d2fd0f7..7b567da 100644 --- a/docs/open-work-preflight.md +++ b/docs/open-work-preflight.md @@ -585,3 +585,9 @@ indefinitely. The production preflight deadline remains 150 ms. Temporal-only and post-contention recovery assertions use an explicit three-second test policy to separate eligibility/recovery from shared-runner fsync speed; the original blocked-call elapsed-time and deadline tests keep their original limits. + +Session expiry tests advance only the preflight wall clock explicitly and check +both just-before and exactly-at expiry, avoiding a scheduler-dependent 10 ms +session setup. Binding-invalidation fixtures likewise use a separate functional +three-second policy; production and explicit deadline/blocked-call tests retain +the original 150 ms deadline. No runtime behavior is relaxed by these fixtures. diff --git a/tests/test_open_work_bindings.py b/tests/test_open_work_bindings.py index b612102..e17d509 100644 --- a/tests/test_open_work_bindings.py +++ b/tests/test_open_work_bindings.py @@ -292,6 +292,10 @@ def test_known_j05_change_blocks_delayed_projection_and_receipt( service, scope, session, target = ( h[k] for k in ("service", "scope", "session", "target") ) + # This fixture verifies source invalidation, not shared-runner fsync speed. + from dataclasses import replace + + service.policy = replace(service.policy, deadline_seconds=3.0) first = service.deliver(scope, session, target, delivery_key="saved") assert ( first.state == "delivered" and "Trusted authored instruction" in first.payload diff --git a/tests/test_preflight.py b/tests/test_preflight.py index ec589a5..d6f462e 100644 --- a/tests/test_preflight.py +++ b/tests/test_preflight.py @@ -386,8 +386,14 @@ def test_independent_process_lock_bounded_deferred_and_release(setup, mode, whic assert service.deliver(scope, session, target).state == "delivered" -def test_session_expiry_cleanup_quota_and_end(setup): +def test_session_expiry_cleanup_quota_and_end(setup, monkeypatch): + from types import SimpleNamespace + import jitmind.code_memory.preflight as module + _, scope, _, database, _, service, session, target = setup + now = [time.time()] + monkeypatch.setattr(module, "time", SimpleNamespace(time=lambda: now[0])) + service.policy = replace(service.policy, deadline_seconds=3.0) add(setup) service.deliver(scope, session, target) service.end_session(scope, session) @@ -396,8 +402,10 @@ def test_session_expiry_cleanup_quota_and_end(setup): with database.connect(Budget(1)) as db: assert db.execute("SELECT count(*) FROM deliveries").fetchone()[0] == 0 assert db.execute("SELECT count(*) FROM delivery_receipts").fetchone()[0] == 0 - expiring = service.start_session(scope, REPO, ttl_seconds=0.01) - time.sleep(0.02) + expiring = service.start_session(scope, REPO, ttl_seconds=10) + now[0] = expiring.expires - 0.001 + assert service.deliver(scope, expiring, target).state == "delivered" + now[0] = expiring.expires # half-open expiry boundary, without scheduler sleep with pytest.raises(ScopeDenied): service.deliver(scope, expiring, target) assert service.cleanup(scope) == 1 From b4d751221c41ab9cea0782bbd55636c0c5461b99 Mon Sep 17 00:00:00 2001 From: Divyam Talwar Date: Tue, 29 Sep 2026 01:36:34 +0530 Subject: [PATCH 3/8] test(release): refresh acceptance identities after timing-oracle correction --- docs/engineering/acceptance-map.json | 36 ++++++++++----------- docs/engineering/acceptance-supplement.json | 8 ++--- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/engineering/acceptance-map.json b/docs/engineering/acceptance-map.json index c53f463..ca2f632 100644 --- a/docs/engineering/acceptance-map.json +++ b/docs/engineering/acceptance-map.json @@ -1399,12 +1399,12 @@ "status": "not_run", "source": { "path": "tests/test_open_work_bindings.py", - "sha256": "645628f66ceddab3ebc92c5260f3289aa4c7bea19a165c135d337417e9857f59" + "sha256": "3af47733e7e47425d5c6ec79986033433c6b27a54f8eb88d1f1cc8023d28727e" }, "fixtures": [ { "path": "tests/test_open_work_bindings.py", - "sha256": "645628f66ceddab3ebc92c5260f3289aa4c7bea19a165c135d337417e9857f59" + "sha256": "3af47733e7e47425d5c6ec79986033433c6b27a54f8eb88d1f1cc8023d28727e" } ], "fixture_description": "Reviewed existing J06 test: temporary Git checkout parsed by actual J04 Node/tree-sitter, J02 fact, J05 logical binding, J06 obligation; file move then confirmed removal or malformed-source uncertainty.", @@ -1498,12 +1498,12 @@ "status": "not_run", "source": { "path": "tests/test_open_work_bindings.py", - "sha256": "645628f66ceddab3ebc92c5260f3289aa4c7bea19a165c135d337417e9857f59" + "sha256": "3af47733e7e47425d5c6ec79986033433c6b27a54f8eb88d1f1cc8023d28727e" }, "fixtures": [ { "path": "tests/test_open_work_bindings.py", - "sha256": "645628f66ceddab3ebc92c5260f3289aa4c7bea19a165c135d337417e9857f59" + "sha256": "3af47733e7e47425d5c6ec79986033433c6b27a54f8eb88d1f1cc8023d28727e" } ], "fixture_description": "Reviewed existing J06 test: temporary Git checkout parsed by actual J04 Node/tree-sitter, J02 fact, J05 logical binding, J06 obligation; file move then confirmed removal or malformed-source uncertainty.", @@ -1663,12 +1663,12 @@ "kind": "public_api", "source": { "path": "tests/test_preflight.py", - "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -1696,12 +1696,12 @@ "kind": "public_api", "source": { "path": "tests/test_preflight.py", - "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -1729,12 +1729,12 @@ "kind": "real_storage", "source": { "path": "tests/test_preflight.py", - "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -1744,12 +1744,12 @@ "kind": "real_storage", "source": { "path": "tests/test_preflight.py", - "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -1759,12 +1759,12 @@ "kind": "real_storage", "source": { "path": "tests/test_preflight.py", - "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -1774,12 +1774,12 @@ "kind": "real_storage", "source": { "path": "tests/test_preflight.py", - "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -3353,12 +3353,12 @@ "kind": "public_api", "source": { "path": "tests/test_preflight.py", - "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "4eb8a94daca6498c7c0914e7baf76818372583ecf485ffabd1a1dcf3b3ffd350" + "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." diff --git a/docs/engineering/acceptance-supplement.json b/docs/engineering/acceptance-supplement.json index 6c1cc44..c10f0c3 100644 --- a/docs/engineering/acceptance-supplement.json +++ b/docs/engineering/acceptance-supplement.json @@ -574,12 +574,12 @@ "status": "not_run", "source": { "path": "tests/test_open_work_bindings.py", - "sha256": "645628f66ceddab3ebc92c5260f3289aa4c7bea19a165c135d337417e9857f59" + "sha256": "3af47733e7e47425d5c6ec79986033433c6b27a54f8eb88d1f1cc8023d28727e" }, "fixtures": [ { "path": "tests/test_open_work_bindings.py", - "sha256": "645628f66ceddab3ebc92c5260f3289aa4c7bea19a165c135d337417e9857f59" + "sha256": "3af47733e7e47425d5c6ec79986033433c6b27a54f8eb88d1f1cc8023d28727e" } ], "fixture_description": "Reviewed existing J06 test: temporary Git checkout parsed by actual J04 Node/tree-sitter, J02 fact, J05 logical binding, J06 obligation; file move then confirmed removal or malformed-source uncertainty.", @@ -673,12 +673,12 @@ "status": "not_run", "source": { "path": "tests/test_open_work_bindings.py", - "sha256": "645628f66ceddab3ebc92c5260f3289aa4c7bea19a165c135d337417e9857f59" + "sha256": "3af47733e7e47425d5c6ec79986033433c6b27a54f8eb88d1f1cc8023d28727e" }, "fixtures": [ { "path": "tests/test_open_work_bindings.py", - "sha256": "645628f66ceddab3ebc92c5260f3289aa4c7bea19a165c135d337417e9857f59" + "sha256": "3af47733e7e47425d5c6ec79986033433c6b27a54f8eb88d1f1cc8023d28727e" } ], "fixture_description": "Reviewed existing J06 test: temporary Git checkout parsed by actual J04 Node/tree-sitter, J02 fact, J05 logical binding, J06 obligation; file move then confirmed removal or malformed-source uncertainty.", From c6e340aa59ab1535b119752c0c594a0ec26ec152 Mon Sep 17 00:00:00 2001 From: Divyam Talwar Date: Tue, 29 Sep 2026 01:42:34 +0530 Subject: [PATCH 4/8] test(preflight): isolate functional fixtures from latency measurements --- docs/open-work-preflight.md | 7 +++++++ tests/test_open_work_bindings.py | 11 ++++++++--- tests/test_preflight.py | 7 +++++-- tests/test_preflight_review.py | 3 +++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/docs/open-work-preflight.md b/docs/open-work-preflight.md index 7b567da..c5e067e 100644 --- a/docs/open-work-preflight.md +++ b/docs/open-work-preflight.md @@ -591,3 +591,10 @@ both just-before and exactly-at expiry, avoiding a scheduler-dependent 10 ms session setup. Binding-invalidation fixtures likewise use a separate functional three-second policy; production and explicit deadline/blocked-call tests retain the original 150 ms deadline. No runtime behavior is relaxed by these fixtures. + +Functional fixtures use a separately configured bounded three-second policy. +Independent-process contention and candidate-selection timing fixtures explicitly +restore PreflightPolicy() before measuring. The deadline-exhaustion fixture keeps +its one-millisecond injected budget, and the default-value regression requires +0.15 seconds. Every original state, payload and elapsed-time assertion remains. +No production runtime behavior changes with this test separation. diff --git a/tests/test_open_work_bindings.py b/tests/test_open_work_bindings.py index e17d509..af48f5f 100644 --- a/tests/test_open_work_bindings.py +++ b/tests/test_open_work_bindings.py @@ -17,7 +17,7 @@ ProposedAction, ) from jitmind.code_memory.open_work import OpenWorkService -from jitmind.code_memory.preflight import PreflightService +from jitmind.code_memory.preflight import PreflightPolicy, PreflightService from jitmind.code_memory.work_storage import WorkDatabase from jitmind.scope import ScopeAuthority from jitmind.storage import IngestRequest, Proposal, SQLiteDurableStore @@ -142,7 +142,9 @@ def build(): source_revision=fact.revision, body="private lesson body", ) - preflight = PreflightService(projection) + preflight = PreflightService( + projection, policy=PreflightPolicy(deadline_seconds=3.0) + ) request_scope = scope() session = preflight.start_session(request_scope, repo) assert preflight.deliver(request_scope, session, target).state == "nothing_relevant" @@ -262,7 +264,7 @@ def build(): binding_id="logical", binding_revision=binding.revision, ) - service = PreflightService(projection) + service = PreflightService(projection, policy=PreflightPolicy(deadline_seconds=3.0)) session = service.start_session(scope, repo) work = OpenWorkService(database, authority) item = work.create( @@ -425,6 +427,9 @@ def test_binding_authority_independent_process_contention(bound_host, mode): process.start() try: assert ready.wait(5) + h[ + "service" + ].policy = PreflightPolicy() # measure the unchanged production budget started = time.monotonic() result = h["service"].deliver(h["scope"], h["session"], h["target"]) elapsed = time.monotonic() - started diff --git a/tests/test_preflight.py b/tests/test_preflight.py index d6f462e..99a33c2 100644 --- a/tests/test_preflight.py +++ b/tests/test_preflight.py @@ -63,7 +63,7 @@ def setup(tmp_path): DurableFactAuthority(facts, authority), can_author=lambda s, repo: s.principal_id == "alice", ) - service = PreflightService(projection) + service = PreflightService(projection, policy=PreflightPolicy(deadline_seconds=3.0)) session = service.start_session(scope, REPO) target = ProposedAction(REPO, "src/service.py", "process") return authority, scope, facts, database, projection, service, session, target @@ -190,7 +190,9 @@ def test_explicit_unvalidated_policy_labels_and_normal_no_match(setup): add(setup, "hypothesis", tier="hypothesis", source_verified=False) service = PreflightService( projection, - policy=PreflightPolicy(allow_unvalidated=True, allow_hypotheses=True), + policy=PreflightPolicy( + allow_unvalidated=True, allow_hypotheses=True, deadline_seconds=3.0 + ), ) session = service.start_session(scope, REPO) assert ( @@ -355,6 +357,7 @@ def _hold_lock(path, mode, ready, release): @pytest.mark.parametrize("which", ["work", "facts"]) def test_independent_process_lock_bounded_deferred_and_release(setup, mode, which): _, scope, facts, database, _, service, session, target = setup + service.policy = PreflightPolicy() # keep the real 150 ms production budget add(setup) ctx = multiprocessing.get_context("spawn") ready, release = ctx.Event(), ctx.Event() diff --git a/tests/test_preflight_review.py b/tests/test_preflight_review.py index 7650f52..e465478 100644 --- a/tests/test_preflight_review.py +++ b/tests/test_preflight_review.py @@ -204,6 +204,9 @@ def test_twenty_plus_rows_cannot_starve_repository_instruction(setup, prefix): valid_until=time.time() - 1 if prefix == "expired" else None, ) assert author(projection, scope, ProposedAction(REPO, "*"), fact, "z-policy") + from jitmind.code_memory.preflight import PreflightPolicy + + service.policy = PreflightPolicy() # preserve the candidate-selection timing oracle started = time.monotonic() result = service.deliver(scope, session, target) elapsed = time.monotonic() - started From 521682291029b1248afc2b0ca877664c428dac20 Mon Sep 17 00:00:00 2001 From: Divyam Talwar Date: Tue, 29 Sep 2026 01:46:45 +0530 Subject: [PATCH 5/8] test(release): preserve native capacity evidence on Python 3.10 --- docs/engineering/acceptance-map.json | 84 ++++++++++----------- docs/engineering/acceptance-supplement.json | 56 +++++++------- docs/engineering/qualification-review.md | 9 +++ tests/test_acceptance_edges.py | 13 +++- 4 files changed, 90 insertions(+), 72 deletions(-) diff --git a/docs/engineering/acceptance-map.json b/docs/engineering/acceptance-map.json index ca2f632..b79525b 100644 --- a/docs/engineering/acceptance-map.json +++ b/docs/engineering/acceptance-map.json @@ -88,12 +88,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Five real legacy store classes in temporary directories; successful initial append, ENOSPC from os.replace after temporary bytes are fsynced, then successful append after fault removal.", @@ -143,12 +143,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Five real legacy store classes in temporary directories; successful initial append, ENOSPC from os.replace after temporary bytes are fsynced, then successful append after fault removal.", @@ -198,12 +198,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Five real legacy store classes in temporary directories; successful initial append, ENOSPC from os.replace after temporary bytes are fsynced, then successful append after fault removal.", @@ -253,12 +253,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Five real legacy store classes in temporary directories; successful initial append, ENOSPC from os.replace after temporary bytes are fsynced, then successful append after fault removal.", @@ -308,12 +308,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Five real legacy store classes in temporary directories; successful initial append, ENOSPC from os.replace after temporary bytes are fsynced, then successful append after fault removal.", @@ -594,12 +594,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Real temporary SQLite DB; each ingest connection capped to current page_count; 100000-character allowed input triggers native SQLITE_FULL, then cap removed for same-key successful commit.", @@ -1399,12 +1399,12 @@ "status": "not_run", "source": { "path": "tests/test_open_work_bindings.py", - "sha256": "3af47733e7e47425d5c6ec79986033433c6b27a54f8eb88d1f1cc8023d28727e" + "sha256": "80f876c3cb1f671b41ecbd68c4f969da5f820c6189d4b1b22d6ac4f164fe87e7" }, "fixtures": [ { "path": "tests/test_open_work_bindings.py", - "sha256": "3af47733e7e47425d5c6ec79986033433c6b27a54f8eb88d1f1cc8023d28727e" + "sha256": "80f876c3cb1f671b41ecbd68c4f969da5f820c6189d4b1b22d6ac4f164fe87e7" } ], "fixture_description": "Reviewed existing J06 test: temporary Git checkout parsed by actual J04 Node/tree-sitter, J02 fact, J05 logical binding, J06 obligation; file move then confirmed removal or malformed-source uncertainty.", @@ -1498,12 +1498,12 @@ "status": "not_run", "source": { "path": "tests/test_open_work_bindings.py", - "sha256": "3af47733e7e47425d5c6ec79986033433c6b27a54f8eb88d1f1cc8023d28727e" + "sha256": "80f876c3cb1f671b41ecbd68c4f969da5f820c6189d4b1b22d6ac4f164fe87e7" }, "fixtures": [ { "path": "tests/test_open_work_bindings.py", - "sha256": "3af47733e7e47425d5c6ec79986033433c6b27a54f8eb88d1f1cc8023d28727e" + "sha256": "80f876c3cb1f671b41ecbd68c4f969da5f820c6189d4b1b22d6ac4f164fe87e7" } ], "fixture_description": "Reviewed existing J06 test: temporary Git checkout parsed by actual J04 Node/tree-sitter, J02 fact, J05 logical binding, J06 obligation; file move then confirmed removal or malformed-source uncertainty.", @@ -1663,12 +1663,12 @@ "kind": "public_api", "source": { "path": "tests/test_preflight.py", - "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" + "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" + "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -1696,12 +1696,12 @@ "kind": "public_api", "source": { "path": "tests/test_preflight.py", - "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" + "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" + "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -1729,12 +1729,12 @@ "kind": "real_storage", "source": { "path": "tests/test_preflight.py", - "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" + "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" + "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -1744,12 +1744,12 @@ "kind": "real_storage", "source": { "path": "tests/test_preflight.py", - "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" + "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" + "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -1759,12 +1759,12 @@ "kind": "real_storage", "source": { "path": "tests/test_preflight.py", - "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" + "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" + "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -1774,12 +1774,12 @@ "kind": "real_storage", "source": { "path": "tests/test_preflight.py", - "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" + "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" + "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -2465,12 +2465,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Existing truncated/duplicate-key/NaN legacy-source rejection and three exception rollback nodes; new real child exit(73) after import pages or before import commit; source JSON byte snapshots and clean retry.", @@ -2517,12 +2517,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Existing truncated/duplicate-key/NaN legacy-source rejection and three exception rollback nodes; new real child exit(73) after import pages or before import commit; source JSON byte snapshots and clean retry.", @@ -2800,12 +2800,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Temporary unversioned checkout, actual J04 parser, J02 add/NOOP/delete, J05 binding and file move, J06 projected lesson/preflight/open task. Two schedules: primary projection already populated or original add event pending until after delete.", @@ -2904,12 +2904,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Temporary unversioned checkout, actual J04 parser, J02 add/NOOP/delete, J05 binding and file move, J06 projected lesson/preflight/open task. Two schedules: primary projection already populated or original add event pending until after delete.", @@ -3120,12 +3120,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Same two actual composed parser chains as J29; memory-only sentinel first positively delivered from bound lesson and memory, then primary forget with deletion projection delayed.", @@ -3223,12 +3223,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Same two actual composed parser chains as J29; memory-only sentinel first positively delivered from bound lesson and memory, then primary forget with deletion projection delayed.", @@ -3353,12 +3353,12 @@ "kind": "public_api", "source": { "path": "tests/test_preflight.py", - "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" + "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "8fff347a29ed0a669ce9cbdb714441810688055c9e1a2672efcd920bb7464b4a" + "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." diff --git a/docs/engineering/acceptance-supplement.json b/docs/engineering/acceptance-supplement.json index c10f0c3..4ac9410 100644 --- a/docs/engineering/acceptance-supplement.json +++ b/docs/engineering/acceptance-supplement.json @@ -36,12 +36,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Five real legacy store classes in temporary directories; successful initial append, ENOSPC from os.replace after temporary bytes are fsynced, then successful append after fault removal.", @@ -91,12 +91,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Five real legacy store classes in temporary directories; successful initial append, ENOSPC from os.replace after temporary bytes are fsynced, then successful append after fault removal.", @@ -146,12 +146,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Five real legacy store classes in temporary directories; successful initial append, ENOSPC from os.replace after temporary bytes are fsynced, then successful append after fault removal.", @@ -201,12 +201,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Five real legacy store classes in temporary directories; successful initial append, ENOSPC from os.replace after temporary bytes are fsynced, then successful append after fault removal.", @@ -256,12 +256,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Five real legacy store classes in temporary directories; successful initial append, ENOSPC from os.replace after temporary bytes are fsynced, then successful append after fault removal.", @@ -317,12 +317,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Real temporary SQLite DB; each ingest connection capped to current page_count; 100000-character allowed input triggers native SQLITE_FULL, then cap removed for same-key successful commit.", @@ -574,12 +574,12 @@ "status": "not_run", "source": { "path": "tests/test_open_work_bindings.py", - "sha256": "3af47733e7e47425d5c6ec79986033433c6b27a54f8eb88d1f1cc8023d28727e" + "sha256": "80f876c3cb1f671b41ecbd68c4f969da5f820c6189d4b1b22d6ac4f164fe87e7" }, "fixtures": [ { "path": "tests/test_open_work_bindings.py", - "sha256": "3af47733e7e47425d5c6ec79986033433c6b27a54f8eb88d1f1cc8023d28727e" + "sha256": "80f876c3cb1f671b41ecbd68c4f969da5f820c6189d4b1b22d6ac4f164fe87e7" } ], "fixture_description": "Reviewed existing J06 test: temporary Git checkout parsed by actual J04 Node/tree-sitter, J02 fact, J05 logical binding, J06 obligation; file move then confirmed removal or malformed-source uncertainty.", @@ -673,12 +673,12 @@ "status": "not_run", "source": { "path": "tests/test_open_work_bindings.py", - "sha256": "3af47733e7e47425d5c6ec79986033433c6b27a54f8eb88d1f1cc8023d28727e" + "sha256": "80f876c3cb1f671b41ecbd68c4f969da5f820c6189d4b1b22d6ac4f164fe87e7" }, "fixtures": [ { "path": "tests/test_open_work_bindings.py", - "sha256": "3af47733e7e47425d5c6ec79986033433c6b27a54f8eb88d1f1cc8023d28727e" + "sha256": "80f876c3cb1f671b41ecbd68c4f969da5f820c6189d4b1b22d6ac4f164fe87e7" } ], "fixture_description": "Reviewed existing J06 test: temporary Git checkout parsed by actual J04 Node/tree-sitter, J02 fact, J05 logical binding, J06 obligation; file move then confirmed removal or malformed-source uncertainty.", @@ -1223,12 +1223,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Existing truncated/duplicate-key/NaN legacy-source rejection and three exception rollback nodes; new real child exit(73) after import pages or before import commit; source JSON byte snapshots and clean retry.", @@ -1275,12 +1275,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Existing truncated/duplicate-key/NaN legacy-source rejection and three exception rollback nodes; new real child exit(73) after import pages or before import commit; source JSON byte snapshots and clean retry.", @@ -1341,12 +1341,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Temporary unversioned checkout, actual J04 parser, J02 add/NOOP/delete, J05 binding and file move, J06 projected lesson/preflight/open task. Two schedules: primary projection already populated or original add event pending until after delete.", @@ -1445,12 +1445,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Temporary unversioned checkout, actual J04 parser, J02 add/NOOP/delete, J05 binding and file move, J06 projected lesson/preflight/open task. Two schedules: primary projection already populated or original add event pending until after delete.", @@ -1563,12 +1563,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Same two actual composed parser chains as J29; memory-only sentinel first positively delivered from bound lesson and memory, then primary forget with deletion projection delayed.", @@ -1666,12 +1666,12 @@ "status": "not_run", "source": { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" }, "fixtures": [ { "path": "tests/test_acceptance_edges.py", - "sha256": "56d9b088e205f017c9559f05e45f86d6cbbaeb732312cb453308ae327f62a344" + "sha256": "266b393756709ea254eea591001880639c14f1a7e5a967e832db3ebd23f540d8" } ], "fixture_description": "Same two actual composed parser chains as J29; memory-only sentinel first positively delivered from bound lesson and memory, then primary forget with deletion projection delayed.", diff --git a/docs/engineering/qualification-review.md b/docs/engineering/qualification-review.md index d594888..7188cfe 100644 --- a/docs/engineering/qualification-review.md +++ b/docs/engineering/qualification-review.md @@ -25,3 +25,12 @@ The missing-node smoke now requires the actual typed `Unavailable` exception wit and attribute errors, unrelated typed failures and the obsolete generic code. The real installed smoke still runs outside the checkout with Node and optional provider packages absent; checkout helper tests cannot substitute for it. + + +## Native SQLite capacity evidence on Python 3.10 + +The real max_page_count exhaustion fixture now records numeric SQLite error +metadata when exposed and otherwise requires the exact native OperationalError +message. Both paths still require a real SQLite capacity limit, zero committed +effects, a clean integrity check, and successful same-request retry after raising +the limit. No error injection substitutes for the real engine capacity failure. diff --git a/tests/test_acceptance_edges.py b/tests/test_acceptance_edges.py index fa26498..5b933a3 100644 --- a/tests/test_acceptance_edges.py +++ b/tests/test_acceptance_edges.py @@ -144,7 +144,9 @@ def capped(**kwargs): try: yield connection except sqlite3.Error as exc: - native_errors.append(exc.sqlite_errorcode) + native_errors.append( + (getattr(exc, "sqlite_errorcode", None), type(exc), str(exc)) + ) raise # Below the public 131072-character input bound; comfortably larger than @@ -154,7 +156,14 @@ def capped(**kwargs): fault.setattr(store, "_connection", capped) with pytest.raises(StorageFailure, match="^storage_failure$"): store.ingest(request, lambda _: _proposal("bounded capacity fact")) - assert native_errors == [sqlite3.SQLITE_FULL] + assert len(native_errors) == 1 + code, error_type, message = native_errors[0] + if code is None: + # Python 3.10 omits result metadata; retain exact native-engine evidence. + assert error_type is sqlite3.OperationalError + assert message == "database or disk is full" + else: + assert type(code) is int and code & 255 == 13 # SQLite primary SQLITE_FULL assert capacities and all(count == cap for count, cap in capacities) fresh = SQLiteDurableStore(store.path) assert fresh.status("tenant") == { From e91b0f2a1753bc0ce66cfe8767e0388148927501 Mon Sep 17 00:00:00 2001 From: Divyam Talwar Date: Tue, 29 Sep 2026 04:48:57 +0530 Subject: [PATCH 6/8] test(release): refresh evidence identities after reviewed fixture corrections --- docs/engineering/acceptance-map.json | 36 ++++++++++++------------ docs/engineering/qualification-review.md | 11 ++++++++ 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/docs/engineering/acceptance-map.json b/docs/engineering/acceptance-map.json index b79525b..8e7fcef 100644 --- a/docs/engineering/acceptance-map.json +++ b/docs/engineering/acceptance-map.json @@ -1399,12 +1399,12 @@ "status": "not_run", "source": { "path": "tests/test_open_work_bindings.py", - "sha256": "80f876c3cb1f671b41ecbd68c4f969da5f820c6189d4b1b22d6ac4f164fe87e7" + "sha256": "78c0d4fc7465734165d2de960acd5a9815e624ae96856d024c2e65bf9e12a65d" }, "fixtures": [ { "path": "tests/test_open_work_bindings.py", - "sha256": "80f876c3cb1f671b41ecbd68c4f969da5f820c6189d4b1b22d6ac4f164fe87e7" + "sha256": "78c0d4fc7465734165d2de960acd5a9815e624ae96856d024c2e65bf9e12a65d" } ], "fixture_description": "Reviewed existing J06 test: temporary Git checkout parsed by actual J04 Node/tree-sitter, J02 fact, J05 logical binding, J06 obligation; file move then confirmed removal or malformed-source uncertainty.", @@ -1498,12 +1498,12 @@ "status": "not_run", "source": { "path": "tests/test_open_work_bindings.py", - "sha256": "80f876c3cb1f671b41ecbd68c4f969da5f820c6189d4b1b22d6ac4f164fe87e7" + "sha256": "78c0d4fc7465734165d2de960acd5a9815e624ae96856d024c2e65bf9e12a65d" }, "fixtures": [ { "path": "tests/test_open_work_bindings.py", - "sha256": "80f876c3cb1f671b41ecbd68c4f969da5f820c6189d4b1b22d6ac4f164fe87e7" + "sha256": "78c0d4fc7465734165d2de960acd5a9815e624ae96856d024c2e65bf9e12a65d" } ], "fixture_description": "Reviewed existing J06 test: temporary Git checkout parsed by actual J04 Node/tree-sitter, J02 fact, J05 logical binding, J06 obligation; file move then confirmed removal or malformed-source uncertainty.", @@ -1663,12 +1663,12 @@ "kind": "public_api", "source": { "path": "tests/test_preflight.py", - "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" + "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" + "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -1696,12 +1696,12 @@ "kind": "public_api", "source": { "path": "tests/test_preflight.py", - "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" + "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" + "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -1729,12 +1729,12 @@ "kind": "real_storage", "source": { "path": "tests/test_preflight.py", - "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" + "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" + "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -1744,12 +1744,12 @@ "kind": "real_storage", "source": { "path": "tests/test_preflight.py", - "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" + "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" + "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -1759,12 +1759,12 @@ "kind": "real_storage", "source": { "path": "tests/test_preflight.py", - "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" + "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" + "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -1774,12 +1774,12 @@ "kind": "real_storage", "source": { "path": "tests/test_preflight.py", - "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" + "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" + "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -3353,12 +3353,12 @@ "kind": "public_api", "source": { "path": "tests/test_preflight.py", - "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" + "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "6ab4269f8cad06c546006b3a40de3cf5b3f85753c2f3d455a5ea423f5ca3f394" + "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." diff --git a/docs/engineering/qualification-review.md b/docs/engineering/qualification-review.md index 7188cfe..e9d396c 100644 --- a/docs/engineering/qualification-review.md +++ b/docs/engineering/qualification-review.md @@ -34,3 +34,14 @@ metadata when exposed and otherwise requires the exact native OperationalError message. Both paths still require a real SQLite capacity limit, zero committed effects, a clean integrity check, and successful same-request retry after raising the limit. No error injection substitutes for the real engine capacity failure. + +## Reviewed CI fixture corrections + +The quota fixture seeds 256 receipt rows in one bounded transaction instead of +256 autocommit fsyncs. The binding IMMEDIATE-lock compatibility control uses a +functional deadline but retains its delivered result and 300 ms assertion. The +EXCLUSIVE control retains the production deadline and deferred-result assertion. +No production source or existing assertion was changed. The acceptance map +refreshes only the two affected fixture file identities; all 32 cases, 41 stages, +node identities and not-run specification statuses remain unchanged. New +qualification evidence must be generated against this committed snapshot. From f36701047837e8789d34723f3c2d394492a39e5b Mon Sep 17 00:00:00 2001 From: Divyam Talwar Date: Tue, 29 Sep 2026 04:58:10 +0530 Subject: [PATCH 7/8] test(release): require explicit default-deadline boundary evidence --- docs/engineering/acceptance-map.json | 76 +++++++++++++++++++----- docs/engineering/qualification-review.md | 17 +++++- docs/release-qualification.md | 4 +- 3 files changed, 79 insertions(+), 18 deletions(-) diff --git a/docs/engineering/acceptance-map.json b/docs/engineering/acceptance-map.json index 8e7fcef..2df2a9f 100644 --- a/docs/engineering/acceptance-map.json +++ b/docs/engineering/acceptance-map.json @@ -1663,12 +1663,12 @@ "kind": "public_api", "source": { "path": "tests/test_preflight.py", - "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" + "sha256": "b468672ced29b13192e8ec6b03ff4c09ac1d0df6bc872b570a4ffd1d1424690c" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" + "sha256": "b468672ced29b13192e8ec6b03ff4c09ac1d0df6bc872b570a4ffd1d1424690c" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -1696,12 +1696,12 @@ "kind": "public_api", "source": { "path": "tests/test_preflight.py", - "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" + "sha256": "b468672ced29b13192e8ec6b03ff4c09ac1d0df6bc872b570a4ffd1d1424690c" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" + "sha256": "b468672ced29b13192e8ec6b03ff4c09ac1d0df6bc872b570a4ffd1d1424690c" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -1729,12 +1729,12 @@ "kind": "real_storage", "source": { "path": "tests/test_preflight.py", - "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" + "sha256": "b468672ced29b13192e8ec6b03ff4c09ac1d0df6bc872b570a4ffd1d1424690c" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" + "sha256": "b468672ced29b13192e8ec6b03ff4c09ac1d0df6bc872b570a4ffd1d1424690c" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -1744,12 +1744,12 @@ "kind": "real_storage", "source": { "path": "tests/test_preflight.py", - "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" + "sha256": "b468672ced29b13192e8ec6b03ff4c09ac1d0df6bc872b570a4ffd1d1424690c" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" + "sha256": "b468672ced29b13192e8ec6b03ff4c09ac1d0df6bc872b570a4ffd1d1424690c" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -1759,12 +1759,12 @@ "kind": "real_storage", "source": { "path": "tests/test_preflight.py", - "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" + "sha256": "b468672ced29b13192e8ec6b03ff4c09ac1d0df6bc872b570a4ffd1d1424690c" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" + "sha256": "b468672ced29b13192e8ec6b03ff4c09ac1d0df6bc872b570a4ffd1d1424690c" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." @@ -1774,15 +1774,63 @@ "kind": "real_storage", "source": { "path": "tests/test_preflight.py", - "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" + "sha256": "b468672ced29b13192e8ec6b03ff4c09ac1d0df6bc872b570a4ffd1d1424690c" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" + "sha256": "b468672ced29b13192e8ec6b03ff4c09ac1d0df6bc872b570a4ffd1d1424690c" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." + }, + { + "node_id": "tests/test_preflight.py::test_default_deadline_boundary_with_real_storage[before]", + "kind": "real_storage", + "source": { + "path": "tests/test_preflight.py", + "sha256": "b468672ced29b13192e8ec6b03ff4c09ac1d0df6bc872b570a4ffd1d1424690c" + }, + "fixtures": [ + { + "path": "tests/test_preflight.py", + "sha256": "b468672ced29b13192e8ec6b03ff4c09ac1d0df6bc872b570a4ffd1d1424690c" + } + ], + "fixture_description": "Actual SQLite and default 150 ms policy with only the monotonic deadline clock advanced to before the cutoff. Checks response content and receipt count; not a wall-clock benchmark.", + "status": "not_run" + }, + { + "node_id": "tests/test_preflight.py::test_default_deadline_boundary_with_real_storage[at]", + "kind": "real_storage", + "source": { + "path": "tests/test_preflight.py", + "sha256": "b468672ced29b13192e8ec6b03ff4c09ac1d0df6bc872b570a4ffd1d1424690c" + }, + "fixtures": [ + { + "path": "tests/test_preflight.py", + "sha256": "b468672ced29b13192e8ec6b03ff4c09ac1d0df6bc872b570a4ffd1d1424690c" + } + ], + "fixture_description": "Actual SQLite and default 150 ms policy with only the monotonic deadline clock advanced to at the cutoff. Checks response content and receipt count; not a wall-clock benchmark.", + "status": "not_run" + }, + { + "node_id": "tests/test_preflight.py::test_default_deadline_boundary_with_real_storage[after]", + "kind": "real_storage", + "source": { + "path": "tests/test_preflight.py", + "sha256": "b468672ced29b13192e8ec6b03ff4c09ac1d0df6bc872b570a4ffd1d1424690c" + }, + "fixtures": [ + { + "path": "tests/test_preflight.py", + "sha256": "b468672ced29b13192e8ec6b03ff4c09ac1d0df6bc872b570a4ffd1d1424690c" + } + ], + "fixture_description": "Actual SQLite and default 150 ms policy with only the monotonic deadline clock advanced to after the cutoff. Checks response content and receipt count; not a wall-clock benchmark.", + "status": "not_run" } ] } @@ -3353,12 +3401,12 @@ "kind": "public_api", "source": { "path": "tests/test_preflight.py", - "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" + "sha256": "b468672ced29b13192e8ec6b03ff4c09ac1d0df6bc872b570a4ffd1d1424690c" }, "fixtures": [ { "path": "tests/test_preflight.py", - "sha256": "2bd9f76c201f5417ed9855b6947b7c92a959688e556502e299dc354933328937" + "sha256": "b468672ced29b13192e8ec6b03ff4c09ac1d0df6bc872b570a4ffd1d1424690c" } ], "fixture_description": "Deterministic fixture constructed in this test source; not full original handoff fixtures." diff --git a/docs/engineering/qualification-review.md b/docs/engineering/qualification-review.md index e9d396c..c68db9d 100644 --- a/docs/engineering/qualification-review.md +++ b/docs/engineering/qualification-review.md @@ -5,8 +5,8 @@ runner records actual results separately against a committed candidate and wheel ## Preserved requirements -The map retains 32 cases, all 41 required stages, 100 stage-node associations and -94 unique identities (93 pytest nodes and one separately executed installed smoke). +The map retains 32 cases, all 41 required stages, 103 stage-node associations and +97 unique identities (96 pytest nodes and one separately executed installed smoke). Case text, node identities, parameter variants, fixture assertions and original handoff/oracle hashes are unchanged. Source-controlled statuses remain `not_run`. @@ -45,3 +45,16 @@ No production source or existing assertion was changed. The acceptance map refreshes only the two affected fixture file identities; all 32 cases, 41 stages, node identities and not-run specification statuses remain unchanged. New qualification evidence must be generated against this committed snapshot. + +## Explicit primary-read deadline oracle correction + +The facts/IMMEDIATE positive lock control now tests delivered content with a +bounded functional budget rather than claiming successful fsync delivery inside +150 ms on shared CI. The three incompatible-lock controls still use the original +production policy and 150 ms ceiling, with empty deferred payloads. Three new +real-storage cases verify before/at/after the default deadline using a controlled +monotonic clock. All original node identities and stages remain, and J20 now +requires the three additional boundary identities. The resulting inventory is +103 stage-node associations and 97 unique identities (96 pytest plus installed +smoke). This is a reviewed test-oracle correction, not unchanged assertions or a +production latency benchmark. Production code is unchanged. diff --git a/docs/release-qualification.md b/docs/release-qualification.md index 594afa8..6dddb1e 100644 --- a/docs/release-qualification.md +++ b/docs/release-qualification.md @@ -171,8 +171,8 @@ not inherited peer pass reports. Changing a test source requires reviewing its assertions and refreshing its hash. `nodes: []` or `additional_mapping_required: true` still blocks a stage. All eight previous mapping gaps now have the exact J10 supplement nodes, retaining parameters, -fixture intent, kinds and `not_run` status. The map has 100 stage-node associations -and 94 unique identities: 93 pytest nodes and the distinct installed smoke. +fixture intent, kinds and `not_run` status. The map has 103 stage-node associations +and 97 unique identities: 96 pytest nodes and the distinct installed smoke. Every original mapped node remains, with 14 additional atomic durability checks using J07's legitimate v2 checkpoint adaptation. The temporal oracle is unchanged. From 48a2a72a4637298f46bce79d7bd045efcc30d58c Mon Sep 17 00:00:00 2001 From: Divyam Talwar Date: Tue, 29 Sep 2026 04:58:31 +0530 Subject: [PATCH 8/8] docs(release): distinguish preserved cases from revised timing assertions --- docs/engineering/qualification-review.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/engineering/qualification-review.md b/docs/engineering/qualification-review.md index c68db9d..a53299f 100644 --- a/docs/engineering/qualification-review.md +++ b/docs/engineering/qualification-review.md @@ -7,8 +7,10 @@ runner records actual results separately against a committed candidate and wheel The map retains 32 cases, all 41 required stages, 103 stage-node associations and 97 unique identities (96 pytest nodes and one separately executed installed smoke). -Case text, node identities, parameter variants, fixture assertions and original -handoff/oracle hashes are unchanged. Source-controlled statuses remain `not_run`. +Original case text, node identities, parameter variants and handoff/oracle hashes +remain. The timing-oracle corrections and three added boundary nodes are recorded +below; they are not described as unchanged assertions. Source-controlled statuses +remain `not_run`. ## Metadata correction