Story-3469 · pramaan-functions · carve invoke payload

The index stops being evidence nobody delivers

Story-3442 shipped the parser. Story-3443 shipped the combiner that consumes it. Nothing joined them. analyse_index's only caller was a measurement script, so every carve ran with index_status="ABSENT" — no cardinality constraint, no location prior, no cover/index reconciliation — and said so in a carve log line that reads exactly like an honest no-index bundle. This change puts the evidence on the wire as RegistrarCarveInput.index.

The seam, and why the ORDER is the whole change

document_pages_v2 rows          (persisted — blocks[].cells intact)
   │
   ├─► carve_index_evidence(rows) ──► input.index   ← analysed HERE
   │      cardinality · identities · printed_range + pdf_range · anomalies
   │
   └─► wire_page(row) ─────────────► input.pages
          block_index · text · kind · confidence     ← cells DROPPED (Bug-3433)

wire_block drops cells by measurement (Bug-3433: keeping the full block record took the 432-page packet from +17% to +61%). The index tables live in exactly those cells, and analyse_index reads nothing else. Analysed one line later — after the strip rather than before it — the function returns UNAVAILABLE for every bundle that ever existed: no error, no exception, no failed test, and a log line a reviewer would read as correct. One list_card_pages read produces both outputs, so the spine and the index can never describe two different extractions.

UNAVAILABLE is a value, not an omission

Bundleinput.indexCombiner
Indexed paperbook status="AVAILABLE", cardinality, identities, both coordinate systems index_status=AVAILABLE; cardinality constraint and location prior active
No index page status="UNAVAILABLE" carrying the analyser's reason index_status=UNAVAILABLE; index_location_prior named as an unavailable detector

An empty identities list under AVAILABLE would tell the combiner this bundle HAS no annexures — a claim the broker is not entitled to make. The founder ruling on Spike-3447 holds throughout: the cover is authoritative for a member's IDENTITY, the index for CARDINALITY, and a disagreement is flagged in both directions, never silently resolved.

Proven against the brain, not against a mock

Byte-parity on tests/vendor/ proves the vendored copies match pramaan-agents; it does not prove the broker's output parses under them. Treating those as one claim is how every carve invoke since 2026-08-02 was refused while both repos stayed green (Bug-3491). So tests/unit/shared/context/test_carve_index_wire.py takes what build_carve_invoke_payload actually emits and pushes it through the REAL CarveIndexEvidence, the REAL AnchoredPage, and the REAL analyze_boundaries — asserting on the combiner's own index_status. Parsing is necessary and not sufficient: a payload can validate and still leave the combiner unconstrained.

agents/registrar/boundary.py is vendored for this and pinned byte-for-byte by the renamed Carve contract parity (pramaan-agents) job, which now guards both halves of one lane — the carve INPUT contract and the carve DROP contract — with per-file remediation, so a boundary drift no longer reports under a message about member numbering.

Red first — three planted negatives, three different failures

Planted defectWhat goes red
Drop "index": index from the payload 3 failed — the two round-trip cases and the combiner case
Analyse the wire pages instead of the persisted rows 1 failed — test_the_spine_loader_analyses_the_persisted_rows_not_the_wire
Report a missing index as an empty AVAILABLE 3 failed — including ..._never_an_empty_identity_list

What did not change

No migration, no route, no DTO, no new cloud capability, no IAM. The field is additive and optional brain-side, so a pre-wire runtime ignores it and a wired one constrains the combiner — a broker/brain deploy in either order is safe. The broker's own bundle_trigger.carve_invoked line now carries index_status and index_cardinality: read beside the combiner's report, a disagreement between the two is the only way to tell "no index in the bundle" from "the index never crossed the wire".