Skip to content

#3610: a shapes gate reported Pass over ZERO focus nodes — the vacuity check was global, so a directory hid it - #3622

Closed
noahgift wants to merge 16 commits into
mainfrom
PMAT-3610-vacuous-shapes
Closed

noahgift wants to merge 16 commits into
mainfrom
PMAT-3610-vacuous-shapes

Conversation

@noahgift

@noahgift noahgift commented Sep 20, 2026 •

Copy link
Copy Markdown
Member

armed_shapes is the tool's claim about what it measured. It named shapes that graded nothing, and the aggregate said Pass. Draft per the lane rule.

The defect, reproduced before anything was changed

// crates/aprender-contracts/src/lint/shapes_gate.rs
if report.focus_nodes_n == 0 {
    return Some(ShapesOutcome::NoFocus { shapes_n });
}

The question is asked globally, so it is only ever true for a lone contract. In a directory the other shapes carry the total above zero and an empty shape is invisible. Fixture shapes-one-empty on origin/main:

verdict: Pass   violations: 0   focus_nodes_n: 1
by_shape:         ['empty-shape=0', 'tool-status=1']
armed_shapes:     ['empty-shape', 'tool-status']      <- the claim
not_armed_shapes: []

by_shape had carried empty-shape=0 all along and nothing read it — the same computed but unexposed class as #3597, and the first instance inside the gate that catches the class. The number that falsifies the claim was in the same JSON object as the claim, computed every run.

The shape generalises, and it is worth the next reader's time: asking the vacuity question globally is correct for the singular case and silently wrong for the plural. A lone contract is the empty case and declines properly; a directory is the full case and passes over the same hole. That is the placeholder-is-most-permissive inversion rotated ninety degrees — the same one as #3609, where a GGUF with no vocabulary gets a synthetic <unk> and works while one with a real vocabulary lacking <unk> is refused. The better-specified input fails and the degenerate one passes. Anything that tests a collection's total rather than each member has this available to it.

After

case verdict exit declines
armed shape at zero, in a directory decline NoFocus 2 named in stderr
unarmed shape at zero Pass 0 ["empty-shape"] — reported, not swallowed
every shape graded something Pass 0 []
lone contract that cannot extract decline ≠0 unchanged
shapes: 1 ARMED shape(s) graded ZERO focus nodes and cannot be counted as clean
        (2 shape(s), 1 focus node(s) in total): empty-shape

The unarmed row is why this is not "refuse whenever anything is empty"

An unarmed shape at zero did not affect the verdict, so it is reported rather than refused — and reported rather than swallowed, which is the half the original defect got wrong. A declines list that could only ever be empty would be decoration, which is the defect one layer up from this one; it carries the unarmed empties so the field is live.

Acceptance, against what shipped

  1. zero focus nodes never in armed_shapes ✅ — excluded from the report. Checked first that this is safe for the arming ratchet: check_monotone compares lint-baseline.json declarations, not this report's list. They are put in declines, not not_armed_shapes, because "not armed by policy" and "armed and measured nothing" are different facts and folding the second into the first would file a vacuity as a deliberate choice — which is how it hid.
  2. aggregate carries a declines: list ✅
  3. --gate shapes refuses when an armed shape graded nothing ✅ exit 2

Both venues, and the mutation

The lone-contract venue already declined correctly, so a fix proved only there proves nothing. The committed table covers both and RED-turns on the defect: disabling the per-shape check fails an_armed_shape_that_graded_nothing_refuses_in_a_directory and the_three_answers_remain_distinct; restoring gives 5/5.

The real corpus is unaffected

pv lint contracts --gate {sigma,relations,shapes} on aprender: Pass, 0 violations, every armed shape with focus nodes (ladder-measured=8, ladder-green=7, ont-shapes-v1=1734), declines: []. The fix refuses the vacuous case and nothing else.

Evidence: evidence/pv/3610/MEASUREMENT.md.

keep-open: #3610's arm 2 (a jsonl extractor, one row per line = one focus node) is NOT in this PR — this is arm 1, the vacuity refusal, which the issue calls "the one that matters" because with it the jsonl workaround is unnecessary. #3567 is the must-carry whose non-vacuity floor this makes real. #3597 is the audit class this is an instance of.

Refs #3610, #3567, #3597

🤖 Generated with Claude Code

…y check was global, so a directory hid it

`armed_shapes` is the tool's claim about what it MEASURED. It named shapes that
graded nothing, and the aggregate said Pass.

THE DEFECT. The vacuity check asked the question globally —
`report.focus_nodes_n == 0` — which is only ever true for a LONE contract. In a
directory the other shapes carry the total above zero, an empty shape contributes
no violations, and the aggregate passes while listing it as armed. Measured on pv
0.68.2 with a `type: jsonl` contract whose rows violate its own sh:pattern.

`by_shape` had carried `<shape>=0` all along and NOTHING READ IT — the same
computed-but-unexposed class as #3597, one layer down, inside the gate itself.

THE FIX is per-shape, before any verdict is formed: an ARMED shape with zero
focus nodes declines (`Unknown{NoFocus}`, exit 2) naming every such shape.

AND THE OTHER DIRECTION, which is what keeps it from being "refuse whenever
anything is empty": an UNARMED shape at zero did not affect the verdict, so it is
REPORTED in a new `declines:` list rather than refused — and reported rather than
swallowed, which is the half the original defect got wrong. A `declines` that
could only ever be empty would be decoration, which is the defect one layer up.

armed_shapes no longer carries a shape that graded nothing. Safe for the arming
ratchet: `check_monotone` compares lint-baseline.json declarations, not this
report's list — checked before moving anything.

BOTH VENUES, because the lone-contract case already declined correctly and a fix
proved only there proves nothing. 5 cases; RED-turns on the defect (disabling the
per-shape check fails the directory case and the three-answers case, restoring
gives 5/5).

THE REAL CORPUS IS UNAFFECTED: sigma/relations/shapes all Pass 0 violations,
every armed shape with focus nodes, `declines: []`.

Evidence: evidence/pv/3610/MEASUREMENT.md

Refs #3610, #3567, #3597

Pmat-Ticket: PMAT-3598

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Requirement from infra-c8, who runs SLK's gate on pv: slk-session-gate.sh and the
bridge self-test CAPTURE STDOUT AND PARSE IT REGARDLESS OF EXIT CODE, because pv
already exits non-zero on Fail. A refusal printing only a bare `decline:` line
reads to them as no-by_shape and scores UNMEASURED — indistinguishable from a
broken pv. The fix would have turned their gate grey on the same day it turned
ours red.

So the vacuity refusal now declines through the ORDINARY result path instead of
short-circuiting: stdout carries verdict Unknown(NoFocus), by_shape naming the
zero-focus shape, and declines; meet_exit turns Unknown into exit 2.

THE REFUSAL IS THE EXIT CODE; THE REPORT IS THE EVIDENCE. A refusal that
suppresses its own evidence is the same defect as a gate that swallows a decline,
from the other side.

A vacuous shape now appears in NEITHER armed_shapes NOR not_armed_shapes — only
in declines. armed_shapes is the claim about what was MEASURED; not_armed_shapes
means not armed by policy; filing a vacuity as a policy choice is how this hid.

The ShapesOutcome::VacuousArmedShape variant and its two consumer arms are
deleted rather than left dead.

Tests assert the exit-2 path emits a parseable report whose by_shape names the
zero-focus shape, and that all three answers print one. Still RED-turns: with the
declining verdict disabled, the directory case and the three-answers case fail.

Real corpus unchanged: sigma/relations/shapes Pass 0 violations, declines [].

Refs #3610, #3567

Pmat-Ticket: PMAT-3598

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@noahgift
noahgift marked this pull request as ready for review September 20, 2026 18:41
@github-actions

github-actions Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

§13.11 rung 1 — quorum shadow verdict

S13-SHADOW pr=3622 head=81460f001b3554af94d965e5ed06eec73b50629e 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 and others added 3 commits September 20, 2026 23:37
The registry is derived from the tree and drifts the moment a test that reads the
tree is added without listing it. Each of the three new tests failed this guard on
its OWN branch — not a shared commit, as first read.

Pmat-Ticket: PMAT-3598

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@noahgift
noahgift enabled auto-merge September 20, 2026 21:51
@noahgift
noahgift disabled auto-merge September 20, 2026 22:30
@noahgift

Copy link
Copy Markdown
Member Author

Disclosure first, because the exemption depends on it: I did not run paiml-implement Phase-1 routing on this PR. I authored it directly. So I cannot state that "Phase-1 routing fired no trigger" — there was no routing step to fire. Anything I said to that effect would be a decision reconstructed after the fact, which is exactly what the receipt exists to prevent.

What follows is a footprint measured now, from the PR's own file list, labelled as post-hoc.

#3622 — measured |M| = 2. I read Q1 as NOT firing, and I am not re-arming on my own say-so.

15 files, but 9 are tests/fixtures (data), and ci/explicit-test-commands.d, evidence/pv, scripts/tree_reader_tests.txt are wiring and evidence rather than owning modules. The code modules are:

  1. aprender-contracts::lint — mod.rs and shapes_gate.rs, one module, two files
  2. aprender-contracts-cli — one integration test target

|M| = 2, which is under the Q1 threshold. The "15 files, 2 crates" count that triggered the disarm is real, but files and crates are not what Q1 measures.

I am stating that as a reading, not acting on it. Your rule, your call — if you want the module count to be a crate count in practice, say so and I will run the lanes. I would rather re-run a quorum I did not need than set a precedent where the author'"s

… resolve it

`quorum-review.sh` refuses without `pmat work status <id>`, and `pmat work`
reads the aggregated roadmap rather than an id counter. This branch carried the
trailer while no such work item existed — a GitHub issue number is not a work
item until something mints it.

The id is DERIVED from the issue: `pmat work add --github-issue` calls that
"the path to prefer", because GitHub allocates centrally and `max(id)+1` cannot
promise two agents different ids. A fragment rather than a direct roadmap.yaml
edit — additive, one file, and it does not make every stacked branch dirty on
the same lines.

Acceptance hand-entered from the issue's done_when; `pmat work add` derives
neither `spec:` nor `acceptance_criteria:` (paiml-mcp-agent-toolkit#1414).

Guards: diff_additive, fragment_required, ids_unique, sorted,
completion_is_cited all exit 0; `make roadmap-aggregate-check` idempotent.

Refs #3610
Pmat-Ticket: PMAT-3610
@noahgift

Copy link
Copy Markdown
Member Author

Closing keyword: Refs #3610, not Closes — this PR is arm 1 of two

#3610 states two arms and this PR implements one:

arm this PR
1. Vacuity refusal — any contract whose target resolves to 0 focus nodes renders Unknown{NoFocusNodes} (exit 2), never Pass done — per-shape, both venues, with the unarmed direction reported in declines[] rather than refused
2. jsonl extractor — one row per line = one focus node not touched

The issue says "Arm 1 is the one that matters", and I agree — with it, the workaround is unnecessary because the gate says so on day one. But "the arm that matters" is not "the issue's criterion", and a closing keyword claims the latter. Arm 2 is what makes a type: jsonl contract actually gradeable; until it lands, the representative-json-entity workaround and the unmeasured: [jsonl-rows] annotations stay load-bearing.

So: Refs #3610, and the issue stays open on arm 2 after this merges.

@noahgift

Copy link
Copy Markdown
Member Author

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

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

…rum round 1, two lanes)

The criterion is that a vacuous shape appears in NEITHER `armed_shapes` NOR
`not_armed_shapes` — I wrote that sentence into this PR's own test header and
then filtered the partition by `vacuous_armed`, which holds only the ARMED
vacuities. So every UNARMED vacuity sailed through into `not_armed_shapes`,
filed as a deliberate policy choice. That is precisely how the original defect
hid, reproduced in the fix for it.

`gemini-3.1-pro-high` and `gemini-3.7-flash-high` found it independently, from
different line numbers.

Two sets now, because they answer two questions: `vacuous_armed` decides the
VERDICT (only an armed vacuity can refuse), `vacuous_any` decides the LISTS.

Also from the lanes:
- the test asserted only the `armed_shapes` half of the criterion, so it stayed
  green through the bug. It now asserts both.
- the `declines` doc comment said an armed vacuity "does not reach here at all —
  the run declines". False: nothing returns early at the verdict, both kinds
  reach the field. Rewritten to say what the two actually differ in, which is
  their effect on the verdict and not their listing.

Tests: aprender-contracts lib 1666/1666; shapes_vacuity 5/5.

Refs #3610
Pmat-Ticket: PMAT-3610
@noahgift

Copy link
Copy Markdown
Member Author

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

{
 "ticket": "PMAT-3610",
 "head": "1c554897efc605e7bff4bb4ed5a6363e2cc6f9d1",
 "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": 5
  },
  {
   "lane": 2,
   "verdict": "PASS",
   "findings": 5
  },
  {
   "lane": 3,
   "verdict": "PASS",
   "findings": 3
  }
 ]
}

gemini-3.1-pro-high = PASS, gemini-3.1-pro-low = PASS, gemini-3.6-flash-high = PASS.
Author measured as Opus 5 (claude); no lane in the author's family. Lane models
set per-invocation via PAIML_IMPLEMENT_CONFIG, never by editing the shared
config that other sessions were launching against.

This trio was chosen on measured odds after flash-class lanes returned
NO-VERDICT intermittently (3.7-flash 3/7, 3.6-flash 1/7, pro-high 0/7 across my
earlier runs). All 15 lanes voted in this batch.

Refs #3622
Pmat-Ticket: PMAT-3610
@noahgift

Copy link
Copy Markdown
Member Author

Cross-inspection of docs/audits/quorum-PMAT-3610.json lanes (non-author: aprender-04, 00:03Z)

lane conversation status verdict findings refs to sibling lanes / receipts / $WORK duration
lane 1 10b8b8f5 SUCCESS PASS (structured_output) 5 (5 cited, 0 with commands) 0 211 s
lane 2 81693b02 SUCCESS PASS (structured_output) 5 (5 cited, 0 with commands) 0 26 s
lane 3 22217a09 SUCCESS PASS (structured_output) 3 (2 cited, 1 with commands) 0 130 s

Distinct agy conversation ids: 3/3; no lane references a sibling lane, another receipt or $WORK. Read from /mnt/nvme-raid0/agent-wt/rel-3610/docs/audits/quorum-PMAT-3610.json.lanes on this box. Note: passes after repair — earlier rounds drew real FAILs that were fixed; trio pro-high / pro-low / 3.6-flash, no silences.

Verdict line: 3/3 PASS, independent. Arming (auto-merge waits for the head's checks).

@noahgift
noahgift enabled auto-merge September 21, 2026 00:04
…xtra::Shapes over the threshold

`origin/main` at 237fbc3 lints clean on `aprender-contracts`; this branch does
not. Adding `declines: Vec<String>` took `Shapes` from 280 to 304 bytes against an
88-byte second-largest and crossed `clippy::large_enum_variant`. Measured both
sides rather than assumed: the finding is this PR's, not inherited.

ALLOWED RATHER THAN BOXED, with the reason in the code. The lint is a cost
heuristic about copying and stack size, and a `GateExtra` is built once per gate
run, moved a few times, then serialised — there is no hot path for 216 bytes to
matter on.

Both alternatives are worse:
- boxing `pc_extract` as clippy suggests reclaims 16 bytes and does not clear the
  ratio, so it is churn that silences nothing;
- boxing the payload as `Shapes(Box<ShapesExtra>)` turns a struct variant into a
  newtype variant, which CHANGES THE SERDE REPRESENTATION of a
  `#[serde(tag = "type")]` enum that downstream parses — the SLK gate reads this
  JSON. Breaking a wire format to satisfy a stack-size heuristic is the wrong
  trade.

The allow names what would make it wrong: if `GateExtra` ever lands in a loop or
a large collection, revisit.

DIFF MOVEMENT, for the receipt: the judged diff DID change — this adds an
attribute and a comment block. No behaviour changed; `run_shapes_gate`, the
vacuity partition and every test are byte-identical to what the lanes read.
AD-04 re-review is the inspector's call, and I am not treating the receipt as
covering code the lanes never saw.

Refs #3610
Pmat-Ticket: PMAT-3610
@noahgift
noahgift disabled auto-merge September 21, 2026 01:39
@noahgift

Copy link
Copy Markdown
Member Author

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

{
 "ticket": "PMAT-3610",
 "head": "c3ed2e07da949d3b3d0056f48f0c2bdb721cd3ac",
 "width": 3,
 "executor": "agy",
 "agreed": false,
 "auto_merge": {
  "checked": true,
  "was_armed": false,
  "disarmed": false,
  "note": "auto-merge not armed"
 },
 "lanes": [
  {
   "lane": 1,
   "verdict": "FAIL",
   "findings": 3
  },
  {
   "lane": 2,
   "verdict": "PASS",
   "findings": 5
  },
  {
   "lane": 3,
   "verdict": "PASS",
   "findings": 6
  }
 ]
}

… checked the report requirement for one venue and not the other

Re-review finding (gemini-3.1-pro-high), correct: `decline()` still asks
`report.focus_nodes_n == 0` GLOBALLY and returns `ShapesOutcome::NoFocus` before
the result path runs. That renders through `skipped_gate(...)` with no `extra`,
so the LONE-contract venue declines with no `by_shape` and no `declines`, while
the DIRECTORY venue — the half this PR fixed — declines with the full report.

The lane's sharper point is about my tests, not the code:
`the_lone_contract_venue_still_declines_as_it_always_did` asserted only
`code != 0`, and `the_three_answers_remain_distinct` omitted `json-missing-ref`
from the loop that requires a parseable report. Together they asserted the
report requirement for one venue and quietly not the other — the half-checked
shape this PR is about, reproduced inside it.

Now asserted rather than unsaid, with the reason it is not fixed here: #3610's
arm 1 asks that a zero-focus contract render `Unknown{NoFocus}` and never Pass,
and the lone venue already does, at exit 2. What it lacks is the evidence
DOCUMENT, which needs the report built before `decline()` is consulted — a
restructure of the outcome path, not a line. The consumer that motivated the
requirement (infra's SLK gate) runs pv over a directory, which is the venue that
now carries it.

Filed as #3648 rather than folded in. The new test's failure message carries the
instruction for whoever lands it: when the lone venue gains a report, DELETE this
test and add the fixture to the three-answers loop — do not loosen the assertion
to keep it green.

shapes_vacuity: 6 passed, 0 failed.

Refs #3610, #3648
Pmat-Ticket: PMAT-3610
@noahgift

Copy link
Copy Markdown
Member Author

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

{
 "ticket": "PMAT-3610",
 "head": "3aab786b1b0cbf689449faac68b534e4df4d2f0e",
 "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": 5
  },
  {
   "lane": 2,
   "verdict": "PASS",
   "findings": 5
  },
  {
   "lane": 3,
   "verdict": "PASS",
   "findings": 5
  }
 ]
}

noahgift added a commit that referenced this pull request Sep 21, 2026
…ape, v1 is deliberately shapeless

Both pro lanes failed #3600 on item 1 as written ("parity-receipt-v1.yaml with
its shape") and they read it correctly. The ruling (cop, 2026-09-21 02:00Z) went
on the ISSUE, and this transcribes it verbatim.

The amendment's substance: item 1 predates the migration this PR made — all 7
records went to v2 in the same commit, so v1 has ZERO instances, and a shape over
a class nothing instantiates passes vacuously. That is the defect #3610 names and
#3622 makes the shapes gate DECLINE on. Following item 1 literally would add, in
one PR, the thing the other PR exists to refuse.

I could have made the lanes green by editing these notes when the finding landed.
I did not, and that is why the ruling exists in the issue: the spec of record
changes first, with its reason, and the fragment follows it. Editing the notes to
fit the code is editing the spec to fit the code — §6 1e exists because the notes
are what the lanes judge.

ONT-4c3's ledger binding is named as infra's row (ONT-001 v4.10, infra#831),
cited rather than done here, per the same amendment.

Guards: 5/5; aggregate-check idempotent; pmat work status resolves.

Refs #3577
Pmat-Ticket: PMAT-3577
…the lone-venue finding

gemini-3.1-pro-high / pro-low / 3.6-flash all PASS on the re-reviewed diff.

Refs #3622

Pmat-Ticket: PMAT-3610
@noahgift

Copy link
Copy Markdown
Member Author

Cross-inspection of docs/audits/quorum-PMAT-3610.json lanes, re-review (non-author: aprender-04, 02:03Z)

lane conversation status verdict findings refs to sibling lanes / $WORK duration
lane 1 40cc0669 SUCCESS PASS (structured_output) 5 (5 cited, 0 with commands) 0 18 s
lane 2 e1af8160 SUCCESS PASS (structured_output) 5 (5 cited, 0 with commands) 0 16 s
lane 3 f23681f7 SUCCESS PASS (structured_output) 5 (5 cited, 0 with commands) 0 91 s

Distinct agy conversation ids: 3/3; no lane references a sibling lane or $WORK. Read from /mnt/nvme-raid0/agent-wt/rel-3610/docs/audits/quorum-PMAT-3610.json.lanes on this box. Note: re-review after the large_enum_variant allow (wire-format reason) and the lone-venue assertion; #3648 split out with a self-deleting test.

Verdict line: 3/3 PASS, independent. Re-arming.

@noahgift
noahgift enabled auto-merge September 21, 2026 02:03
… set, not resolved to a side

#3650: #3631's PMAT-3627 entry rewrote the committed aggregate, so every branch
minting a fragment conflicts on that one file.

`docs/roadmaps/roadmap.yaml` is GENERATED. The conflict is in the artifact and
never in the inputs — `docs/roadmaps/entries/` merged with ZERO conflicts because
the fragments are separate files, and main's `PMAT-3627.yaml` arrived intact. So
the resolution is `make roadmap-aggregate` over the merged set; taking either
side whole would silently drop the other's entry, which is this file class's
failure mode.

Verified rather than assumed: PMAT-3610 and PMAT-3627 each appear exactly once in the
regenerated file, and `make roadmap-aggregate-check` reports it idempotent.

THE JUDGED DIFF IS UNCHANGED. A merge commit past the judged head touching one
generated file; no reviewed code, test or contract is altered, so this branch's
AD-04 receipt stays valid.

Refs #3650
Pmat-Ticket: PMAT-3610
@noahgift
noahgift added this pull request to the merge queue Sep 21, 2026
@noahgift
noahgift removed this pull request from the merge queue due to a manual request Sep 21, 2026
@noahgift

Copy link
Copy Markdown
Member Author

Folded into the 0.69 release batch #3669 (08:25Z) and taken out of the queue so it isn't built twice. Its receipt and closing references are carried in #3669.

noahgift added a commit that referenced this pull request Sep 21, 2026
The batch's CI went red on two guards, and both trace to single folded PRs:
check_no_pipe_into_grep_q (77 sites vs ceiling 74, all three new sites in
#3271's build_report.sh/check_build_report.sh) and check_complexity_ratchet
(run_shapes_gate over its threshold). #3271 (0.70) and #3622 are dropped
from this batch and go to the next one with the guard finding on each. The
complexity finding persists without #3622 and comes from #3600's own edits
to run_shapes_gate (cognitive 28); fix owed in the batch.

Regenerated: census, contracts.nt, shapes.ttl, README count, roadmap
aggregate (99 fragments). extract --check rc 0, readme --check rc 0.

Refs #3669

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@noahgift

Copy link
Copy Markdown
Member Author

Taken back out of release batch #3669 (08:45Z). The batch's CI traced a red guard to this PR: the complexity ratchet flagged `run_shapes_gate`. The finding persists without this PR (it comes from #3600), but this PR adds to the same function, so it goes to the next batch once #3600's refactor lands. The receipt stands. It rides the next batch once fixed. The owner's session is gone, so this is adoptable by selector.

… 2 (#3610 re-review)

All three lanes of the #3622 re-quorum (claude-sonnet-5, degraded: same-family)
cited shapes_gate.rs:246: the verdict checked `vacuous_armed` before `!passed`.
The two range over DISJOINT shapes, so an armed shape that graded nothing turned
a real Fail from a DIFFERENT armed shape into Unknown(NoFocus) / exit 2 — and a
consumer reading exit 2 as "unmeasured" never saw a Fail the gate measured.

- `!passed -> Fail` now comes first; the vacuity is still named in `declines`.
- New fixture shapes-one-empty-and-violating (shapes-one-empty's contracts +
  json-violation's data) and test
  a_real_violation_is_a_fail_even_beside_a_vacuous_armed_shape: exit 1, Fail,
  declines == ["empty-shape"].
- MUST-RED, measured: with the old order the new test FAILS (exit 2,
  "Unknown(NoFocus)"); with the reorder 7/7 pass.

Cop ruling (B) on #3622, 2026-09-23.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… doc and ticket match the precedence (#3622 re-review round 2)

The round-2 re-quorum of f663d39 (claude-sonnet-5, degraded: same-family)
came back 3/3 FAIL, on problems that predate the reorder. Each one was verified
by hand before fixing:

- The two "lone-contract venue" tests ran `json-missing-ref`. That fixture exits
  3 on an unreadable entity.ref, as ont_extract_json.rs:128 asserts, BEFORE
  decline() is consulted. So `code != 0` and "no report" held for the wrong
  reason. New fixture `shapes-all-empty` (the one shape, zero focus) reaches the
  real global NoFocus path. Measured with a pv snapshot built from f663d39:
  exit 2, `decline: NoFocus`, 0 bytes of stdout. MUST-RED: pointing the new test
  back at json-missing-ref FAILS it with exit 3.
- That path's missing report is REAL, and the test now records it against a
  filed issue, #4100. The old comment said "filed" and cited no number.
- evidence/pv/3610/MEASUREMENT.md quoted a stderr block naming the shape. No
  code emits it; it was removed in 69d7b79. The file also said "5/5" and had no
  row for the Fail precedence. All of it is corrected, and the correction is
  stated in the file.
- lint/mod.rs `declines` doc and the PMAT-3610 acceptance text now record the
  precedence from f663d39: a measured violation outranks a vacuity.

Not changed here: docs/audits/quorum-PMAT-3610.json still attests 3aab786.
The next agreed round replaces it. One lane claim is NOT reproduced (text-mode
lint shows ✓ on an armed vacuity; validation fails first on the fixture); it is
recorded in #4100, not acted on.

shapes_vacuity 7/7; aprender-contracts --lib 1666 passed; fmt clean;
roadmap aggregate --check clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@noahgift

Copy link
Copy Markdown
Member Author

Closed under the operator rule of 2026-09-24 ("no PR open over 1 day"), relayed by aprender-49 on the cop's (aprender-cf) instruction. The branch PMAT-3610-vacuous-shapes is kept (head f6ab946a6).

Why it cannot land today:

Path forward: the 0.70 fold (aprender-6c) can carry this branch once it is rebased and a quorum round agrees. Closed by aprender-98.

@noahgift noahgift closed this Sep 24, 2026
@noahgift
noahgift deleted the PMAT-3610-vacuous-shapes branch October 9, 2026 08:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind:code Work is a code change (derived rule, #4159)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant