Skip to content

PMAT-3704 / ONT-4c3: pc_extract draws one planted defect per implemented extractor — parity-receipt, json and pv-contract gain their controls, and the set is tied to Σ - #3706

Merged
noahgift merged 4 commits into
mainfrom
PMAT-3704-ont-4c3-pc-extract
Sep 21, 2026

Conversation

@noahgift

@noahgift noahgift commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

Closes #3704. Refs #3577 (ONT-4c3), #3624.

The defect. pv lint contracts/ --gate shapes reported pc_extract = {apr-model, code, gguf, lean} while Σ (contracts/ontology.yaml) marks seven entity types implemented. parity_receipt::positive_control (#3600) had one caller — a unit test — so the gate never drew it, and json (#3516) and pv-contract had no control at all. ONT-001 R-3 requires "pc_extract (one planted defect per registered extractor, every run)", and the infra ONT-4c3 probe asks .pc_extract["parity-receipt"]=="fired": the row was RED on main whatever the ledger said. extract_controls() is byte-identical on #3600's head, the #3669 squash and 225b2a9ab — never wired, not dropped.

The fix is the tie, not the missing entry. A lib test makes extract_controls()'s key set EQUAL Σ's implemented entity types (a non-empty set, every value fired), so the next extractor cannot ship without its control. Then the three controls it demands:

  • parity-receipt — the existing control, drawn on control_sample() (a minimal v2 record; fails closed to Null);
  • json — in memory through extract_text(), the post-read path extract_into now shares: a mapped nested key extracts typed by its class, an unmapped one is refused naming the key;
  • pv-contractmetadata.kind and a depends_on relation come out as ont:kind and the edge; the copy without metadata carries no ont:kind.

Measured (pv from this tree, aprender contracts/): verdict=Pass, pc_extract 7/7 fired, by_entity_type["parity-receipt"]=7 — the probe's gate conjunct rc 0 (rc 1 on main). RED commit d542db3cd (4 keys vs 7; no parity key), GREEN 9f6b2e02c, both tests unedited.

Mutations, each RED: parity drops the comparator edge / json infers a class for an unmapped key / pv-contract defaults metadata.kind to kernel → the Σ-tie test fails AND the gate declines exit 2 naming exactly pc_extract.<that key>; dropping a control key → the Σ-tie test fails on its assertion. make gate rc 0; clippy -D warnings and fmt clean; all 11 tests/ont*.rs pass (95). Receipt: docs/audits/impl-PMAT-3704-receipt.md.

ont-delta: none — adds pc_extract positive controls for three already-implemented extractors (pv-contract, json, parity-receipt); no entity type, shape, relation or verdict reason is added or changed

keep-open: #3577 closes only when paiml/infra binds ONT-4c3 in the ONT-001 ledger from this PR's squash (the binding is infra's row, not a change here); #3624 is the by_entity_type sibling list, which this PR does not change.

🤖 Generated with Claude Code

noahgift and others added 3 commits September 21, 2026 16:21
…and the gate must report the parity-receipt control

Two tests, both red on main: the lib test ties extract_controls() to
contracts/ontology.yaml (4 controls vs 7 implemented types: json,
parity-receipt and pv-contract have none), and the CLI test asks the
same question ONT-001 v4.10's ONT-4c3 probe asks,
.pc_extract["parity-receipt"] == "fired", at the top level of the report.

Pmat-Ticket: PMAT-3704
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…d extractor, every run

extract_controls() was a hand-written array of four (gguf, apr-model,
code, lean) beside a Σ that implements seven. It now carries all seven,
keyed by entity type:

- parity-receipt: the control #3600 wrote and only a unit test called,
  drawn on control_sample() (a minimal apr-parity-receipt/v2 record;
  a sample that does not parse is Null and cannot fire);
- json: in memory, through the same post-read path extract_into now
  shares (extract_text) — a mapped nested key extracts typed by its
  class, and an unmapped one is refused naming the key;
- pv-contract: a contract with metadata.kind and a depends_on relation
  yields ont:kind and the edge, and the copy without metadata yields no
  ont:kind — nothing is inferred.

On aprender's contracts/: verdict Pass, pc_extract 7/7 fired,
by_entity_type["parity-receipt"] = 7 — the ONT-4c3 probe's gate
conjunct, rc 0. Both RED tests from the previous commit pass unedited.

Pmat-Ticket: PMAT-3704
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… the diff

docs/audits/impl-PMAT-3704-receipt.md: how the defect was found (the
ONT-4c3 ledger carrier's own first check), five whys, the verification
table, four mutants each RED with the gate declining by name, and the
two refused dispatches (paiml/paiml-implement#326).

Pmat-Ticket: PMAT-3704
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

§13.11 rung 1 — quorum shadow verdict

S13-SHADOW pr=3706 head=18108846f222382d69a6242a77066add2c688e6b verdict=REFUSE class=Q1 arm_rc=1

Shadow mode: this records a verdict and merges nothing. A refusal
to arm is not a block (§13 adds zero rows to §7) — the pull request is
exactly as green as it was.

@noahgift

Copy link
Copy Markdown
Contributor Author

quorum-review (AD-04): NOT agreed (auto_merge: checked=true was_armed=false disarmed=false)

{
 "ticket": "PMAT-3704",
 "head": "18108846f222382d69a6242a77066add2c688e6b",
 "width": 3,
 "executor": "agy",
 "agreed": false,
 "auto_merge": {
  "checked": true,
  "was_armed": false,
  "disarmed": false,
  "note": "auto-merge not armed"
 },
 "lanes": [
  {
   "lane": 1,
   "verdict": "PASS",
   "findings": 7
  },
  {
   "lane": 2,
   "verdict": "PASS",
   "findings": 9
  },
  {
   "lane": 3,
   "verdict": "NO-VERDICT",
   "findings": 0
  }
 ]
}

@noahgift

Copy link
Copy Markdown
Contributor Author

quorum-review (AD-04): NOT agreed (auto_merge: checked=true was_armed=false disarmed=false)

{
 "ticket": "PMAT-3704",
 "head": "18108846f222382d69a6242a77066add2c688e6b",
 "width": 3,
 "executor": "agy",
 "agreed": false,
 "auto_merge": {
  "checked": true,
  "was_armed": false,
  "disarmed": false,
  "note": "auto-merge not armed"
 },
 "lanes": [
  {
   "lane": 1,
   "verdict": "PASS",
   "findings": 0
  },
  {
   "lane": 2,
   "verdict": "NO-VERDICT",
   "findings": 0
  },
  {
   "lane": 3,
   "verdict": "PASS",
   "findings": 0
  }
 ]
}

@noahgift

Copy link
Copy Markdown
Contributor Author

quorum-review (AD-04): three PASS — agreed (auto_merge: checked=true was_armed=false disarmed=false)

{
 "ticket": "PMAT-3704",
 "head": "18108846f222382d69a6242a77066add2c688e6b",
 "width": 3,
 "executor": "agy",
 "agreed": true,
 "auto_merge": {
  "checked": true,
  "was_armed": false,
  "disarmed": false,
  "note": "auto-merge not armed"
 },
 "lanes": [
  {
   "lane": 1,
   "verdict": "PASS",
   "findings": 0
  },
  {
   "lane": 2,
   "verdict": "PASS",
   "findings": 0
  },
  {
   "lane": 3,
   "verdict": "PASS",
   "findings": 0
  }
 ]
}

gemini-3.1-pro-high / gemini-3.1-pro-low / gemini-3.6-flash-low, three
distinct measured models, partial:false. Rounds 1 and 2 were NOT AGREED
on a NO-VERDICT lane each (gemini-3.7-flash-high, then 3.8-flash-high:
status SUCCESS, no verdict object), both other lanes PASS in each.

Pmat-Ticket: PMAT-3704
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@noahgift
noahgift enabled auto-merge September 21, 2026 15:08
@noahgift
noahgift added this pull request to the merge queue Sep 21, 2026
Merged via the queue into main with commit 52f43da Sep 21, 2026
23 of 26 checks passed
@noahgift
noahgift deleted the PMAT-3704-ont-4c3-pc-extract branch September 21, 2026 16:17
noahgift added a commit that referenced this pull request Sep 21, 2026
…d as the union

The only conflict was docs/roadmaps/roadmap.yaml: PMAT-3696 (batch-1) and
PMAT-3704 (#3706) were inserted at the same spot. Both entries are kept whole,
in id order. check_roadmap_sorted / ids_unique / diff_additive all PASS; the
merge adds 21 lines relative to batch-1's head, all of them the PMAT-3704 entry.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
noahgift added a commit that referenced this pull request Sep 21, 2026
…ved batch branch

release/0.70-batch-1 has since merged main (#3706, PMAT-3704); taking its
roadmap.yaml brought an entry whose fragment this tree does not have.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
noahgift added a commit that referenced this pull request Sep 21, 2026
…ease-evidence gets its own control

The one real conflict (the extract import in shapes_gate.rs) is textual; the semantic one is #3706's
every_implemented_entity_type_in_sigma_has_an_extract_control_and_it_fires: release-evidence was implemented in
Σ with no pc_extract control, so the merged tree would have gone RED.

release_evidence::positive_control(), drawn every gate run with no release subject and no file: a sample cell
with one fresh Pass row and a planted cell with none go through the real build(); it fires iff the planted cell
is still a release:Cell node with ZERO rows (absence materialized for minCount 1). extract() is now file reading
plus a pure build(Inputs). Mutant measured: emit only cells that have rows -> pv lint --gate shapes exit 2,
'positive control pc_extract.release-evidence did not fire'. Also moves receipts.rs's strings() helper above
the test module (clippy items_after_test_module).

Refs #3715, #3704

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

ONT-4c3: pc_extract never carries parity-receipt — the positive control is written, unit-tested, and never drawn by the gate

1 participant