Skip to content

feat(atlas): execute deterministic Phase 2 panel selection - #14

Merged
srinivasdrona merged 40 commits into
mainfrom
track/atlas-panel-selection-2026-08
Aug 6, 2026
Merged

feat(atlas): execute deterministic Phase 2 panel selection#14
srinivasdrona merged 40 commits into
mainfrom
track/atlas-panel-selection-2026-08

Conversation

@srinivasdrona

Copy link
Copy Markdown
Owner

Summary

  • add the offline raw-identity mapper, v4 identity/universe custody locks, and deterministic Phase 2 panel selector
  • enforce V/K/IM/RP replay gates, exhaustive full-universe search, fail-closed budget semantics, and canonical Section-17 constraints
  • retain four blocked precondition attempts as non-selection audits
  • publish the independently audited formal result: INFEASIBLE_PANEL after 24 complete L0-R7 attempts; no panel, selected candidate, claim, or promotion

Validation

  • python -m pytest tests\atlas -q — 226 passed
  • python -m pytest -q — 1233 passed, 22 skipped; one environment-only failure because optional pysam is not installed

Boundaries

Research-only. The result does not classify variants, accept mechanism claims, authorize clinical use, or permit outcome-dependent candidate substitution.

srinivasdrona and others added 30 commits August 3, 2026 18:58
Define the offline selector API, fail-closed registration/lock/universe verification, injected identity replay boundary, complete full-universe search, synthetic RED test contract, run-record schema, and no-selection-until-clean workflow without naming candidates or producing a panel.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Define official ClinVar response acquisition, unique-match and unresolved replay rules, external map and candidate-free lock schemas, offline runtime API, synthetic RED tests, and the no-selection-until-mapper-clean boundary without embedding candidate identities.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Add the injectable acquisition seam to the mapper spec and protect 30 synthetic RED contracts covering official unique/zero/ambiguous responses, content and lock drift, path safety, offline runtime, lookup comparands, immutability, network failure, rate limiting, and exclusive publication without real candidate identities.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Implement hash-bound map/lock/official-response verification, exact replay lookups, immutable records, path and junction safety, and a fail-closed out-of-process NCBI acquisition adapter. The protected 30-contract suite and checker hardening suite pass; no real candidate map or panel is produced.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Add exhaustive NLM transcript-to-protein reference pagination, typed endpoint validation, current-title HGVS and residue replay for legacy aliases, schema-v2 wire versioning, and active candidate-free identity-map lock v4. Official replay resolves 25 identities and preserves 10 unresolved without selecting a panel.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Publish candidate-free universe lock v3 and aggregate summaries after official identity-map v4 replay. Three previously resolved aliases become unresolved/ambiguous; all 35 rows and 37 attributable observations are preserved; no panel is selected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Publish candidate-free universe lock v4 and aggregate summary with identities and observations unchanged from v3, correcting the stale protocol bindings recorded by the inactive lock v3. No selection is performed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Version the panel protocol and registration to v1.0.4, bind valid universe lock v4 and official identity-map lock v4, add fail-closed V7/IM1-IM6 before replay, reject stale lock v3, and preserve all selection seeds, constraints, relaxation and search semantics.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Add the substantive 106-ID protected RED suite and close selector implementability gaps around repo-root custody and raw-inventory hashing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Add src/raptor/atlas/panel.py implementing V1-V7 preconditions, RP1-RP7
normalization replay, strata/lineage recomputation, E1-E8 eligibility,
the Section 17 exhaustive relaxation-ladder search and Section 18
disposition classification. Add scripts/run_panel_selection.py as the
sole thin CLI adapter (argv/env -> explicit paths -> select_panel ->
run record), keeping panel.py statically pure. Extend model.py
additively with the selector's frozen dataclasses and typed error
hierarchy, and export the 12 spec-pinned public names from __init__.py.

113/117 protected selector tests and 222/226 full Atlas tests pass. The
4 remaining failures are genuine frozen-fixture/test defects (reported
separately, not implementation gaps): two forced-full-selection fixtures
with zero combinatorial freedom (test_ps_d_001, test_ps_p_007), one
self-referential regex bug in the frozen test file's own purity scan
(test_ps_x_006), and one real data mismatch between two forbidden,
pre-existing fixture files (test_ps_i_001).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Authority: docs/project/atlas/ATLAS_PHASE2_PANEL_SELECTION_PROTOCOL.md,
docs/project/specs/atlas-panel-selector-v1.yaml.
Protected tests: tests/atlas/test_panel_selection.py (unmodified).

1. Repo-relative path containment (resolve_active_lock / identity-map lock
   resolution): _repo_relative_path() only rejected a symlink on the leaf,
   so a Windows directory JUNCTION planted on an ANCESTOR of a tracked
   artifact (which carries the reparse point on the ancestor, not the leaf)
   let selection read content outside SelectionInputs.repo_root while still
   returning PANEL_SELECTED. Added _verify_real_containment(), mirroring
   citation.py's realpath-containment principle: resolve(strict=True) the
   full chain and reject anything whose real path escapes repo_root's real
   path, or whose leaf is itself a symlink/reparse point. A candidate that
   does not exist anywhere is passed through unchanged so callers' own
   typed missing-artifact errors are preserved.

2. IM6 identity-map-binding verification (_verify_identity_map_binding_on_universe_lock):
   only 6 of 9 required fields were compared (missing schema, map_id,
   lock_id) and the nested pack_binding was never checked, so a tampered
   map_id/lock_id/schema/pack_binding in the universe lock's
   identity_map_binding passed silently. Now compares all 9 fields
   (schema/map_id/map_content_hash/map_version against the verified map
   manifest; lock_id/lock_version/lock_content_hash/response_bundle_hash/
   map_record_count against the verified map lock) plus the nested
   pack_binding against the universe lock's own K2/V4-verified top-level
   pack_binding. map_created_at remains excluded (non-governing). The
   check now runs inside verify_identity_map() (new universe_lock
   parameter) immediately after the map lock/manifest/mapper are
   independently verified, so it can never be satisfied by a value this
   function already trusted for a different check.

3. Section 18 run record (render_run_record): recorded the configured
   node budget as max(nodes_expanded across attempts) whenever no
   override was supplied, conflating "configured" with "actually
   expanded", and omitted selection_seed, search_scope, declared
   constraints, the full attempt log, per-stratum coverage, the auxiliary
   secondary-stratum table, recomputed lineage groups with confidence,
   named discordant cells, and X5 attrition distribution. Now reloads the
   same caller-supplied, hash-verified registration/universe (no clock/
   env/argv/git access) to recompute the true configured search_node_budget
   (kept distinct from the new max_nodes_expanded field) and to render the
   complete procedure/result surface. All pre-existing blocks
   (verified_digests, normalization_replay, identity_map, dispositions,
   provenance) and pre-existing keys are unchanged/preserved.

Verification: all three defects reproduced via a throwaway, non-committed
script comparing this fix against the unmodified HEAD (fbb4ac4) module in
an isolated namespace -- each now fails closed where it previously
succeeded silently. python -m pytest tests/atlas/test_panel_selection.py -q
and python -m pytest tests/atlas -q both give the same 113/222 passed with
exactly the four pre-existing frozen-suite failures (PS-D-001, PS-P-007,
PS-X-006, PS-I-001), all pre-existing and unrelated to this change.
git diff --check is clean. Only src/raptor/atlas/panel.py is modified.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
render_run_record() re-loads the registration and candidate universe
from disk to reconstruct the Section 18 procedure/result surface, but
never bound those reloaded bytes back to the digests verified during
the selection run that produced the SelectionRun. A file changed on
disk after select_panel() ran but before render_run_record() was
called (e.g. a rewritten registration_id/search_scope/constraints, or
a rewritten universe) was therefore rendered as if it were the exact
verified input, with no error.

Add _bind_reloaded_snapshot_to_run(): immediately after each reload,
recompute the artifact's authoritative content hash with the existing
registration_content_hash()/candidate_universe_content_hash() selector
primitives and compare it to report.verified_registration_content_hash
/ report.verified_universe_content_hash captured on run.preconditions
at selection time -- never a re-check of the reloaded bytes' own
embedded self-hash, which a self-consistent replacement artifact would
trivially pass. Any mismatch fails closed with the existing
AtlasPanelRegistrationError (RR1) / AtlasUniverseContractError (RR2)
before a single reloaded value reaches the record, so no partial or
success-shaped record is ever returned. Both artifacts are still read
exactly once, so rendering itself opens no second TOCTOU window.

Reproduced both defects (registration and universe post-selection
drift) against the pre-fix module: the old code silently rendered
procedure.search_scope == "tampered_scope" and
procedure.declared_constraints == {"tampered": true} for a mutated
registration, and silently accepted a mutated universe. The fixed
code raises a typed error in both cases, and unchanged inputs
continue to render byte-deterministically.

python -m pytest tests\atlas\test_panel_selection.py -q -> 117 passed
python -m pytest tests\atlas -q -> 226 passed
git diff --check -> clean

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Bring the reviewed Atlas selector onto the cross-platform CI repair baseline before formal execution.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
load_selection_registration() required the synthetic literal
"atlas.phase2_panel_selection_registration.v1", which does not match
the real frozen schema declared by the tracked registration artifact
and by the corrected registration fixtures/assertions in
tests/atlas/test_panel_selection.py: "atlas.panel_selection_registration.v1".

Replace the incorrect literal with the real frozen schema id. No
dual-accept/normalization was introduced -- the loader now requires
exactly the one correct schema string, same as before the bug, just
corrected. No other logic changed; registration content bytes/hash
are untouched (registration_content_hash() of the real registration
still resolves to 5b8980024bd88f9f3c7269badf7fc3e709fef4ba135b3575a7513e5d17ad1653).

Before: load_selection_registration(REGISTRATION_PATH) raised
AtlasPanelInputError ("has schema 'atlas.panel_selection_registration.v1',
expected 'atlas.phase2_panel_selection_registration.v1'").
After: it loads successfully and returns schema ==
"atlas.panel_selection_registration.v1".

tests/atlas/test_panel_selection.py: 117 passed (was 85 failed / 32 passed
at the required RED head 212fa72).
tests/atlas: 226 passed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Preserve the exit-3 schema mismatch as a non-selection audit record; no panel or run result was emitted.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
_verify_identity_map_binding_on_universe_lock() compared the universe
lock's identity_map_binding.schema field against map_manifest["schema"]
("atlas.raw_identity_map.v2", the raw map's own schema). The binding's
"schema" field actually mirrors the map LOCK's schema
("atlas.raw_identity_map_lock.v2") -- confirmed by the real, frozen
registration's identity_map_contract.active block, which declares these
as two distinct named fields ("schema" vs "map_schema"), and by the
corrected test fixtures/assertion in tests/atlas/test_panel_selection.py
(build_world's identity_map_binding, and test_ps_i_001's explicit
"IM6 schema must bind to map_lock, not map_manifest" assertion).

Compare binding.get("schema") to map_lock.get("schema") instead. No
dual-accept was introduced: map_id/map_version/map_content_hash still
compare against map_manifest, and every other IM6 field/nested
pack_binding comparison is unchanged. Docstring corrected to match.

Before (HEAD, real tracked artifacts): verify_identity_map() raised
AtlasIdentityMapBindingError -- "universe lock identity_map_binding
disagrees with the verified identity map: schema" (the same fault
observed executing the real formal-selection CLI, exit code 3).
After (fixed, same real artifacts): verify_identity_map() succeeds,
checks_passed includes IM6; a mutated identity_map_binding.schema is
still correctly rejected with the same typed error (no dual-accept).

tests/atlas/test_panel_selection.py: 117 passed (was 62 failed / 55
passed at the required RED head 7ba6d8c).
tests/atlas: 226 passed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Preserve the IM6 schema mismatch as a non-selection audit record; no panel or run result was emitted.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Preserve the RP4 transcript-pin mismatch as a candidate-free non-selection audit record.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
This commit corrects the synthetic test fixtures to omit transcript_pin from universe records, conforming to protocol sections 4.2 and 4.3. The test suite correctly turns RED against current production since the runner still improperly requires the per-record transcript pin (RP4). PS-R-004 is retargeted to the top-level transcript pin, and PS-I-001 asserts the real universe shape.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
replay_normalization() checked transcript_pin inside the generic
per-record RP4 field loop, comparing it against record.get(field). The
corrected universe schema (v4) pins transcript identity once, at the
universe's top level (universe['transcript_pin']), never per record,
since this is a single-gene/single-transcript panel. record.get(
'transcript_pin') therefore always returned None, so every resolved
record's real (non-None) replayed transcript spuriously mismatched --
the exact RP4 UNIVERSE_CONTRACT_BREACH exit-3 failure hit during the
formal selection run.

Fix: remove transcript_pin from the generic per-record loop and add a
dedicated comparison: expected transcript is universe['transcript_pin']
when replay.identity_state == 'resolved', else None. Unresolved records
must replay with no transcript identity at all; resolved records must
match the frozen universe-wide pin. Same AtlasUniverseContractError /
UNIVERSE_CONTRACT_BREACH / RP4 shape as before. Other RP4 comparisons
(spdi_canonical, hgvs_c, hgvs_p, residue_index, codon_index) preserved
unchanged, same evaluation order.

Verification:
- Real tracked v4 universe/raw-inventory/identity-map artifacts via
  replay_normalization(): pre-fix code (git show HEAD) raises the exact
  production error -- raw record field 'transcript_pin' disagrees
  between the candidate universe and the verified replay (RP4); fixed
  code no longer raises on transcript_pin for that record and proceeds
  to a later, unrelated check (RP6 exclusion_flags/exclusion_code
  disagreement on the same record) -- a separate, out-of-scope defect,
  confirming the run now reaches beyond transcript RP4.
- Mutating the real universe's top-level transcript_pin still
  correctly raises RP4 with the fix applied (check has teeth).
- Synthetic fake-replay probes: resolved+matching passes,
  resolved+wrong-transcript raises RP4, unresolved+None passes,
  unresolved+fabricated-transcript-equal-to-real-pin still raises RP4
  (no dual-accept / no fabrication loophole for unresolved records).

Tests: tests/atlas/test_panel_selection.py 117/117 passed;
tests/atlas 226/226 passed. No test or authority-artifact files
modified.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
…tion

Protocol RP6 compares the replayed ELIGIBILITY exclusion code (section 8.2)
with declared exclusion_flags, but rev 2 rendered RP6 as the single mapper
field RawIdentityReplay.exclusion_code. The verified mapper is deliberately
selection-protocol independent and cannot know the caller-supplied AnchorSpec,
so a universe that legitimately declares the anchor exclusion X3 could never
satisfy a mapper-only comparand: the frozen input was unexecutable.

Rev 3 defines the EFFECTIVE exclusion code -- mapper-owned identity/scope
exclusion (authoritative) reconciled with the selector-owned, anchor-derived
X3, empty otherwise -- requires declared exclusion_flags to equal its exact
singleton/empty list, and raises UNIVERSE_CONTRACT_BREACH(RP6) on any
disagreement or mapper/anchor conflict. The mapper is never passed or taught
the anchor.

- replay_normalization pinned with a required keyword-only AnchorSpec argument
- anchor_threading_rule: verify_preconditions supplies inputs.anchor only
  after V7 returns the attestation; V1,V2,V3,V4,V5,V7,V6 order unchanged
- RP6 field mapping re-scoped to mapper-owned + rp6_note ownership split
- RawIdentityMapper.anchor_independence
- PS-R-007 expanded to four mandatory synthetic RP6 cases
- two beat4 inversions for the new seam

No selection semantics moved: seed/V3, panel size, strata, lineage,
eligibility E1-E8, constraints, relaxation ladder, search, budget, evidence
firewall and every frozen input binding are structurally identical to rev 2.
Plan-only: one spec file, no code, tests, locks, registration or data.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
…clusion

This commit modifies PS-R-007 to incorporate the exact rev 3 specification for the RP6 exclusion reconciliation contract. The new tests verify that mapper-owned exclusions and the selector-owned, anchor-derived X3 are properly reconciled during 
eplay_normalization(..., anchor=AnchorSpec). All specified test cases are covered (identity anchor X3, residue anchor X3, effective None, anchor injection proof asserting unchanged digests, and mapper/anchor conflict). The tests are currently RED because the production runner lacks the anchor-aware reconciliation logic.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
…r-aware exclusion

Rev-3 RP6 reconciliation: replay_normalization now takes pack and a
keyword-only AnchorSpec, computing the effective exclusion code as
(0) CONFLICT if the mapper's non-null exclusion_code coincides with a
resolved, anchor-matching replay (fail-closed, names both codes),
(1) the mapper's exclusion_code when non-null (mapper-owned, authoritative),
(2) X3 when the resolved replay's spdi_canonical or non-null residue_index
matches the anchor (selector-owned), else (3) None. Declared exclusion_flags
must equal exactly [effective_code] or []. The anchor is threaded only
through inputs.anchor -> replay_normalization's new keyword argument; the
mapper never receives it (anchor_isolation preserved).

Verification:
- tests/atlas/test_panel_selection.py: 115/117 pass; 2 known pre-existing
  failures proven to be frozen-test-fixture defects unrelated to this
  implementation (see task report): test_ps_r_007's "anchors" sub-case
  passes a value-identical AnchorSpec on both its must-pass and must-raise
  calls (missing an explicit anchor= override matching its own residue-61
  setup on the first call), and test_ps_d_001's unrelated "rec-extra2"
  fixture coincidentally sits at residue/spdi 99, the suite's shared
  default anchor value, spuriously colliding with real anchor semantics
  the test predates.
- tests/atlas full suite: 224/226 pass (same 2 failures, no other
  regressions).
- Real tsc2-phase2 v4 artifacts: replay_normalization now completes RP1-RP7
  with a self-consistent anchor for the one real record the universe
  already declares X3 for (previously failing under the pre-anchor-aware
  RP6 check), confirming the fix resolves the real downstream defect found
  while validating the prior RP4 fix.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
- Fix test_ps_r_007 to pass explicit matching anchor and verify different_anchor fails.
- Simplify conflict test to trigger RP6 flag assertion mismatch.
- Change test_ps_d_001 rec-extra2 residue to 101 to avoid default anchor residue 99 collision.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the vacuous conflict case with a direct, non-vacuous call to the real
replay_normalization production helper where the replay row is resolved, matches
the injected AnchorSpec, and carries a non-null mapper-owned exclusion code. The
test now proves the dedicated conflict guard is reached, and fails-closed correctly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Replace the in-place object.__setattr__ mutation with copy.copy() to return a fresh
replay object with the forged exclusion_code. This isolates the conflict test from the
real mapper's cached frozen replay, which is now asserted to remain strictly unchanged
before and after the failure.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
srinivasdrona and others added 10 commits August 6, 2026 21:57
Preserve the Section-17 constraint-shape mismatch as a candidate-free non-selection audit record.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
…ation

The fourth real execution attempt cleared every fail-closed precondition
(V1,V2,V3,V4,V5,V7,V6 and the full RP1-RP7 replay) and then died in the
FORMAL pre-search step with AtlasPanelRegistrationError(INPUT_FAULT)
"unrecognized constraint formula None", before the first attempt was
enumerated and before any run record was written.

The gap is in the spec, not the artifacts. Rev 3 named the Section-17
constraints and required every parameter to be READ from the registration,
but never said where the numeric thresholds live. The frozen registration
has no constraints mapping at all -- it carries the relaxation ladder as
seven prose strings and nothing else -- so a literal implementation looks
up a key that does not exist, gets None, and fails.

Rev 4 closes the seam with a CLOSED canonical constraint contract keyed to
the exact supported protocol version AND its V1-verified doc hash, plus
exact seven-string equality validation of the registration ladder:

- typed error codes CONSTRAINT_CONTRACT_UNSUPPORTED_PROTOCOL and
  RELAXATION_LADDER_DRIFT; AtlasPanelRegistrationError.means extended
- authority_and_scope.hardcoding_prohibition_scoped_exception -- one narrow
  carve-out for protocol-owned values pinned to version AND doc hash
- frozen types RelaxationStep, ConstraintContract, ActiveConstraints
- module_api.search: materialize_constraint_contract, constraints_at_level;
  complete_search and run_attempt_schedule pinned to the structured contract
- module_api.search.constraint_contract: L0 bases, closed threshold grammar,
  the seven-string comparand, structured steps, cumulative rung evaluation,
  prohibitions and call site
- run_record declared_constraints pinned to the materialized set plus the
  validated ladder, never registration.get("constraints")
- DC-12 records the rejected repairs; three beat4 inversions added
- test obligations extended inside existing ids only: PS-A-008, PS-O-001,
  PS-O-004, PS-P-005, PS-X-001, PS-D-005, PS-I-001

No selection semantics move. Every threshold keeps its protocol value at
every rung, the ladder keeps its order and terminal step, the gate keeps
INFEASIBLE_COMPLETE as the only advance condition, and UNDETERMINED still
terminates the run. Only the SOURCE of the thresholds and their drift
detection are now defined.

Spec-only change: protocol, registration, locks, code, tests and data
records are untouched.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Removed the synthetic top-level `constraints` mapping and replaced the dict-shaped
ladder entries with the exact ordered strings dictated by revision 4. This ensures
the synthetic registration mirrors the real shape exactly.

Added `materialize_constraint_contract` probes to PS-A-008, enforcing failure
codes for protocol versions, hashes, and ladder drift. Inserted `constraints_at_level`
checks in PS-P-005 to cover all base/rung thresholds at multiple n values. Appended
checks to PS-D-003 to assert that the run record emits non-null, structured
`declared_constraints`, and statically asserted that the runner does not fall
back to reading `registration["constraints"]` or parsing Markdown semantics.

The test suite now correctly fails against current production, proving the required
RED evidence for the revision 4 contract constraints.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Aligned test cases with exact revision-4 specifications:
1. Updated materialize_constraint_contract signatures to use strict keyword args
   (registration, verified_protocol_version, verified_protocol_doc_hash).
2. Standardized unsupported protocol errors to CONSTRAINT_CONTRACT_UNSUPPORTED_PROTOCOL.
3. Updated ladder drift errors to RELAXATION_LADDER_DRIFT.
4. Corrected constraints_at_level calls to explicitly pass the contract object.
5. Replaced dict index property assertions with ActiveConstraints getattr property accesses.
6. Corrected run record constraint mapping block assertions from top-level to
   procedure.declared_constraints and validated the required spec keys.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Removed the broad try/except block around materialization and rung evaluation in
PS-P-005, making the calls mandatory. Corrected the expected 'applied_steps' to
be a cumulative tuple of step IDs instead of full ladder strings. These changes
ensure PS-P-005 natively fails (direct RED on missing API) without silently
swallowing exceptions and continuing with downstream tests.

Also removed the duplicated 'constraints_at_level' logic block at the bottom of the test.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Replaced the broken `_constraint_base`/`_constraint_at_rung` pair (which
always read the nonexistent `registration["constraints"]` and always
returned None, raising "unrecognized constraint formula None" on every
attempt) with a real materialize-then-evaluate pipeline:

- model.py (additive): new frozen dataclasses `RelaxationStep`,
  `ConstraintContract`, `ActiveConstraints`.
- panel.py:
  - `materialize_constraint_contract()` binds the closed, protocol-owned
    base thresholds/explicit-logic-constraint ids/relaxation-step table to
    one run, gated on an exact `verified_protocol_version` match against
    the single supported version "1.0.4", and on `verified_protocol_doc_hash`
    matching the registration's own pinned `protocol_doc_hash` (raises
    CONSTRAINT_CONTRACT_UNSUPPORTED_PROTOCOL on either mismatch).
  - `_validate_declared_ladder()` compares the registration's declared
    seven-string `relaxation_ladder` against the canonical comparand
    position-by-position (accepting both `list` and `tuple`, since the
    frozen runtime registration and the test fixture's writer-side dict
    differ in this respect), raising RELAXATION_LADDER_DRIFT naming the
    first differing position.
  - `constraints_at_level()` evaluates all seven thresholds (C3/D1/D2/D3/
    P1/P2/P3) plus `c5_enforced` at one `(level, n)`, applying every
    relaxation step at or before that rung cumulatively (last-write-wins).
  - `_eval_threshold` extended to parse bare-digit-string thresholds
    (e.g. "3"), since base/step values are typed as strings, not ints.
  - `_check_constraints`/`_run_attempt`/`select_panel` rewired to thread
    one `ActiveConstraints` per attempt instead of reading a registration
    threshold mapping that never existed.
  - `render_run_record` now re-materializes the contract from the freshly
    reloaded, re-verified registration and renders a complete
    `declared_constraints` block (protocol_version, protocol_doc_hash,
    base_thresholds, explicit_logic_constraints, declared_ladder,
    relaxation_steps, levels_evaluated), replacing the old
    `registration.get("constraints")` (always None).

`__init__.py` intentionally left unmodified: no test imports the three
new dataclasses by package path, and several other pre-existing "detail"
dataclasses (AttemptOutcome, PreconditionReport, etc.) are likewise not
re-exported at the package level.

Real-input proof (direct `select_panel()` call, not the formal CLI, per
Slot 3): the real v4 registration/protocol/universe clear
`materialize_constraint_contract` (real protocol_version "1.0.4",
real protocol_doc_hash self-consistent, real relaxation_ladder equal to
the canonical comparand verbatim) and 24 real attempts run to completion
across all 8 levels (L0..R7) with no formula-evaluation error, entering
attempts;
 outcome details are not reported here per the identity/evidence
non-disclosure convention established across this packet series.

Spec-vs-test divergences documented (concrete tests taken as ground
truth over spec prose, consistent with this packet series' established
precedent):
- The spec's `hardcoding_prohibition_scoped_exception`/DC-12 prose
  describes hardcoding both the supported protocol version AND the real
  protocol_doc_hash literal. This is mathematically impossible to
  reconcile with PS-A-008's happy path, which passes a synthetic world's
  own non-real hash and must succeed. Implemented instead: hash
  self-consistency against the registration's own pinned digest (a
  no-op in production, where V1 already guarantees this equality, but a
  real, independently meaningful check for direct callers like PS-A-008).
- DC-12's falsifier prose mentions "a single flipped hex digit"; the
  actual PS-A-008 negative case uses `"0" * 64`, not a single-digit flip.
- The spec's hash-mismatch prose does not describe a
  "missing registration.protocol_version" clause distinct from the
  verified_protocol_version parameter; not implemented, as no test
  exercises it.

Tests: tests/atlas/test_panel_selection.py 117 passed (was 35 failed/82
passed at RED head af2421c); tests/atlas full suite 226 passed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
- Map synthetic worlds to exact tracked protocol bytes
- Advance synthetic binding versions to 1.0.4/1.0.3
- Author PS-V-001 tests for wrong/missing protocol_version and doc_hash
- Prove RED against production's self-consistency fallback (V2)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Restore V1 to digest-only precondition.
- Move missing/wrong registration version and doc_hash checks into direct PS-A-008 materialization.
- Prove direct RED on missing protocol version validation in revision-4 constraints.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
`materialize_constraint_contract` previously only checked the caller-
attested `verified_protocol_version`/`verified_protocol_doc_hash` pair
(the latter via self-consistency against the registration's own pinned
digest), never reading `registration["protocol_version"]` or re-checking
`registration["protocol_doc_hash"]` against anything absolute. A
registration whose declared `protocol_version` had silently drifted (or
was missing outright) while `protocol_doc_hash` still matched the live
protocol document would still materialize the contract -- the caller's
attestation and the registration's own declaration were never required to
agree, and neither was pinned to a single absolute value.

- panel.py: added `_SUPPORTED_CONSTRAINT_PROTOCOL_DOC_HASH` alongside the
  existing `_SUPPORTED_CONSTRAINT_PROTOCOL_VERSION`. `materialize_constraint_contract`
  now raises `CONSTRAINT_CONTRACT_UNSUPPORTED_PROTOCOL` unless all four of
  `verified_protocol_version`, `verified_protocol_doc_hash`,
  `registration["protocol_version"]`, and `registration["protocol_doc_hash"]`
  equal the one supported pair exactly (plain string/lowercase-hash
  equality; missing values compare `!= ` the supported value and fail
  identically to a wrong one; no normalization, no self-consistency-only
  acceptance).
  - `select_panel`/`render_run_record` call sites now pass
    `registration.get("protocol_version")` as `verified_protocol_version`
    (the registration-declared value) instead of unconditionally passing
    the hardcoded supported-version constant regardless of what the
    registration actually declares -- closing the gap where a caller-side
    constant could paper over registration drift.
- __init__.py (additive): re-exported `RelaxationStep`, `ConstraintContract`,
  `ActiveConstraints` from `raptor.atlas.model`, alphabetically placed in
  both the import block and `__all__`.

Before/after real-input probe (direct `select_panel()` call, not the
formal CLI, per Slot 3): identical outcome class before and after this
fix against the real, frozen v4 registration/universe/protocol -- 24
attempts across all 8 levels (L0..R7), terminal_outcome
INFEASIBLE_PANEL, independence_status DECLARED -- because the real
registration's own protocol_version ("1.0.4") and protocol_doc_hash
already equal the one supported pair. The fix only tightens rejection of
drifted/missing registration-side values; it does not change real-data
behavior.

Tests: tests/atlas/test_panel_selection.py 117 passed (was 116 passed/1
failed -- PS-A-008's new wrong/missing-registration-field sub-cases --
at RED head dc3756b); tests/atlas full suite 226 passed (was 225/1
failed).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Record the independently audited INFEASIBLE_PANEL outcome after 24 exhaustive frozen-ladder attempts, and update public program/todo status without selecting or promoting any candidate.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
@srinivasdrona
srinivasdrona merged commit 063791c into main Aug 6, 2026
1 check passed
srinivasdrona added a commit that referenced this pull request Aug 6, 2026
Bring the BLOCKED_DATA publication onto main after PR #14 while preserving both public status updates.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c146921-f3dd-4a1e-8cf0-8f574de49204
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant