Repository navigation
Conversation
…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>
|
§13.11 rung 1 — quorum shadow verdict Shadow mode: this records a verdict and merges nothing. A refusal |
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>
…MAT-3610-vacuous-shapes
|
Disclosure first, because the exemption depends on it: I did not run 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
|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
Closing keyword:
|
| 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.
|
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
|
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
Cross-inspection of
|
| 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).
…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
|
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
|
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
}
]
} |
…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
Cross-inspection of
|
| 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.
… 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
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>
|
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>
|
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 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. |
armed_shapesis the tool's claim about what it measured. It named shapes that graded nothing, and the aggregate saidPass. Draft per the lane rule.The defect, reproduced before anything was changed
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-emptyonorigin/main:by_shapehad carriedempty-shape=0all 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
declinesNoFocusPass["empty-shape"]— reported, not swallowedPass[]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
declineslist 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
armed_shapes✅ — excluded from the report. Checked first that this is safe for the arming ratchet:check_monotonecompareslint-baseline.jsondeclarations, not this report's list. They are put indeclines, notnot_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.declines:list ✅--gate shapesrefuses when an armed shape graded nothing ✅ exit 2Both 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_directoryandthe_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
jsonlextractor, 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