Skip to content

Defined terms: every use linked to its entry; Harness renamed Rule harness - #24

Open
LTSCommerce wants to merge 144 commits into
nextfrom
editor/defined-terms
Open

LTSCommerce wants to merge 144 commits into
nextfrom
editor/defined-terms

Conversation

@LTSCommerce

@LTSCommerce LTSCommerce commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

What this change does

Every use of a defined term in the three documents is linked to its terminology entry; the entries themselves are unchanged in substance. In the detector specification the term Harness is renamed Rule harness, and its entry says it is not the environment an agent runs in. In the tooling specification the section 2 table and clause 4.1 follow the rename, the section 3 table's correct-construction row says the project supplies the remediation docs content, and clause 4.5's uses of "remediation" link to the method's term. In the method specification, section 1 gains a paragraph on the terms the other two documents borrow, and clause 3.5 glosses Bundled defence.

Prompted by a review that found "harness" read as the environment an agent runs in and found terms used before they were defined.

Acceptance

Runs 32 to 52 (seven per document) were made under the acceptance rules this repository had then and failed, each on passages the change had not touched or on a rewording made after the run before; those rewordings were withdrawn when the rules changed, and the passages are listed in acceptance/ROUTED.md.

Under the process of pull request 22 (merged into this branch):

  • Method specification: runs 53, 56, 59 and 61 failed; run 64 passed.
  • Detector specification: runs 54, 69 and 75 failed; run 80 passed.
  • Tooling specification: run 55 failed on passages the toolchain contradictions change (pull request 25) rewrites; with that change merged here after it passed, run 87 passed.

This branch carries pull request 25 (the toolchain contradictions) as well; its text is graded there.

Each run's record is under acceptance/runs/, and its answer sheets are posted below.

This branch carries pull request 23 (the detector route rule); its text is graded there.

🤖 Generated with Claude Code

LTSCommerce and others added 30 commits October 10, 2026 14:49
….1: Remediation defined, Harness renamed Rule harness

Clarity edit, no obligation changed. Remediation is used throughout the
method specification, section 7 among others, and was never defined; it is
now a term in section 1 and every use links to it. The detector
specification's Harness is now Rule harness, in every document that uses
it, so that it cannot be read as the environment an agent runs in. The
clause 4.2 heading is unchanged, so its anchor and every link to it hold.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The two section 7 sentences the 2c key quotes now link Remediation as a
defined term, so their flattened text reads "A Remediation Conforms" and
"A verdict on a Remediation"; the quotations carry the new wording verbatim.
No question, threshold or fixture changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Five cold Haiku readers per document at 35f42bf, marked by a delegated marker. Run 31
(SPEC.md) fails on 2a, a traceable 3.3 miss and two clause 3.1 passages; run 32
(DETECTOR-SPEC.md) on 5.3, 6.1 and the 6.1 Message sentence; run 33 (TOOLING-SPEC.md) on 4.2,
4.3 and four passages. No failure traces to text the change touched. Committed as the failed
runs they are, before the text is changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Clarity, no obligation changed. Section 2 gives section 3's steps in order, after two readers
answered 2a leaving out the class or the proof and sweep, quoting the section 2 sentence that
names none of them. Clause 3.1 says its two bounds compare wider and narrower rules for the same
kind of code and that the level of abstraction is a separate question, after three readers
could not tell what "Both bounds measure breadth within one level" meant; its lower bound no
longer calls a rule drawn to the instance "the same Narrowing", which two readers took against
the term's definition, and says why the rejected wider rule is tested as a Narrowing is. Clause
3.3 Part B says an ignore placed on one instance is a call-site suppression under clause 3.4,
not an exclusion from the rule's scope, after a reader failed the fixture under both clauses.
Every MUST sentence keeps its keywords and its requirement.

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

Clarity, no obligation changed. The section 2 table glosses Message, after four readers could
not read clause 6.1's sentence on a documentation path in the message without its definition.
Clause 5.3 keeps its MUST word for word and says the remainder is any finding the summary
leaves out, so a summary printing every finding has none, after all five readers took the
remainder for extra detail about findings already printed, against the key's Yes. Clause 6.1
says it asks for the mechanism and that a bundled identifier with no page fails clause 6.3, as
6.3 already says every such identifier must resolve, after three readers failed 6.1 for the
two undocumented rules; clause 6.4's Why names 6.3 to match.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…de clearer

Clarity, no obligation changed. Section 1 says the section 2 table glosses every term the
document borrows, and it glossed eleven of twenty-seven: it now glosses all of them,
Remediation and Remediation docs among them, each from its defining entry, and says that a
blocking rule with missing documentation is not yet a defence but is still reached by clauses
4.2, 5.1 and 8.1, after three readers set the Defence row against those clauses. Clause 4.2
says one identifier that does not resolve fails it, as clause 4.1's table already shows, and
names the acceptable forms of lookup, after two readers graded it as met in part. Clause 4.3's
heading names disabling as well as a defence of its own, as its body and the key's restatement
do, after four readers set heading against body. Clause 9.1 says the artefact grade counts what
the shipped toolchain supplies and grades the mechanism, not a consumer's content. Clause 9.2
keeps "The declaration is optional." and says the gap record binds a project that declares,
with a gap method clause 3.2 requires recorded either way.

The 4.3 heading's anchor changed, so the ten links to it are re-pointed: one in the
toolchain QUESTIONS.md, two in its KEY.md, one in CHANGELOG.md and six in the register pages.
Only the link target changed; no word of a question or a key answer did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…oject record

Clarity, no obligation changed. The sentence added to clause 9.2 sent a reader who has only
this document to "where that clause says" in the method specification; it now names the
project record, which is where method clause 3.2 puts a gap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Clarity, no obligation changed. Clause 3.3 Part B now opens by saying it judges the rule's own
scope, what the rule is written or configured not to match, and that an ignore placed on one
instance is not judged there but is a call-site suppression under clause 3.4 and section 4; the
paragraph that said so after the decision rows is moved up, after a reader applied the Part B
test to the ignore and failed it under both 3.3 and 3.4. Section 4's item on the next wider rule
replaces "This does not reopen a Class ... and it reaches no further than the one wider Rule"
with sentences naming the rule and the rejection the item reaches, after two readers could not
tell what "This" and "it" limited. Every MUST sentence is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Clarity, no obligation changed. Clause 5.3's remainder sentences are two plain ones: the
remainder is the findings the summary does not print, and where every finding is printed there is
none and a file that only adds detail need not be named; three readers found the previous pair
hard to parse. Clause 7.1 says a Rule in the Detector itself is one that reports each use of the
route, written in the Detector's own rule format and run by it, as a bespoke rule under 4.1 is;
three readers set the phrase against 4.1. Clause 8.1 says the duty to record a gap falls on a
Detector that has a declaration, since the gap is recorded alongside the declared version; two
readers could not tell whether an undeclared Detector is bound. Every MUST sentence is unchanged,
so the key's 7.1 quotation stands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Clarity, no obligation changed. Clause 4.3 says the routes it covers are the ones each Detector
offers, so a Detector whose only route is an ignore comment meets it once that comment is
disabled or caught by a blocking defence; two readers graded it Partial because the fixture did
not rule out other routes, citing "every route". Clause 9.2 says, beside its gap MUST, that the
duty falls on a project or artefact that has a declaration, and replaces "one that declares none
makes no claim for a gap record to qualify", which three readers could not parse, with a plain
sentence after "The declaration is optional.", which stays verbatim. Section 2's "These are
additional." names the three terms it introduces, after two readers could not tell which entries
it meant. Every MUST sentence is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Section 2 names two independent attempts at writing the rule, with clause
3.1's independence test, instead of "techniques tried at expressing the
Rule, in the vocabulary clause 3.1 uses for a search". Clause 3.1's lower
bound says what the rejection of the next wider rule needs on the record and
that without it the decision is the owner's. Section 4's item on the next
wider rule is restated as that one test. Single-reader passages: clause 3.1's
level sentence, section 2's "the first from the second" and clause 3.6's
"no Rule build of their own". No obligation changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Clause 7.1 says plainly that the rule detecting an inline suppression route
is written by the project, in the detector's own rule language, and run by
the detector as any bespoke rule under clause 4.1; the keyed MUST sentence is
unchanged. Clause 8.1's sentence on whom the gap duty falls is shorter and
names the duty it limits. No obligation changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Section 2 says clauses 4.2, 5.1 and 8.1 apply to an undocumented blocking
rule as if it were a defence, so it belongs in the 5.1 listing, instead of
"still reach it". Clause 4.1 says every MUST of the detector specification's
sections 4 to 7 applies and the six are a summary. Clause 9.2 names the
declaration's gap duty, which binds only a declarer, and method clause 3.2's
duty, which applies either way, as two duties. The keyed 9.1 and 9.2
sentences are unchanged. No obligation changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Clause 3.3 says before its Parts that an ignore placed on one instance
counts against none of them; Part B no longer classifies it. The Owner
entry says the default owner takes section 4's decisions. Clause 3.4's
baseline MAY names the owner and drops "tremendous". No obligation
changed and no keyed sentence touched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Clause 8.1's gap MUST takes a detector that declares a version as its
subject, and the sentence narrowing the duty after it is cut. Clause
7.1 says the rule or the check reports each use of the route and that
the project writes the rule. The keyed 7.1 MUST sentence is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…on, made clearer

Section 2's sentence on an undocumented blocking rule is cut to say
that clauses 4.2, 5.1 and 8.1 include it where they say Defence. Clause
4.2's native-catalogue sentence says when the clause is met and failed.
Clause 9.1's section 8 sentence names the section 9 addition it limits.
The Project record entry is one place for every kind of judgement. No
obligation changed and no keyed sentence touched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Part C drops "and the enforced run does not report it", which a reader
took as a requirement the fixture's red run broke; Part B's reporting
MUST names both sides of its comparison.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The two sentences after the keyed MUST become one, in its own words:
the detector need not ship the detecting rule, it is enough that the
project can write it as a bespoke rule under clause 4.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Section 2 says only what Defence covers in clauses 4.2, 5.1 and 8.1;
the Project record entry and 9.1's section 8 sentence revert to the
base text, the entry ending "whichever it has made"; 4.1 says every
MUST applies, not only the six summarised.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Owner entry says that "whoever owns the codebase" means the Owner,
after two readers could not tell whether section 4's lead-in named the
same person as the entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7.1's sentence after the MUST says only that a rule "in the Detector
itself" is a bespoke rule under clause 4.1, dropping "need not ship";
6.1 says what the toolchain's lookup gives: identifier to documentation
on disk.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The sentence on an undocumented rule says it counts when its firing
fails the toolchain's run, where "runs as Blocking" left readers asking
whether a rule enabled in configuration is blocking.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eys that ask what the question asks

Keys list the required elements per part of each question, questions ask for exactly
those, a confusion finding is settled run by run and blocks only in text the change
wrote or altered (others go to acceptance/ROUTED.md), single misses count against the
document only where the key names the reading, and open marking points are settled in
the rules before the next run rather than invented per run.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
One route for each kind of change to the test (quotation and new item in the specification
pull request, everything else a process change); ROUTED.md and runs/ are records, not process
files; question 1 defined once; open points marked in a stated direction; quoting needs a
six-word run; a finding lies in the change's text when any sentence of its paragraph changed;
wrong readings stated as grade plus reasoning; keys ask only what their questions ask (detector
2a, toolchain 2c); the question 3 tables separate the condition from the explanation.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
LTSCommerce and others added 24 commits October 12, 2026 14:43
Every keyed item five of five. Two findings in text the change wrote or altered: clause 5.1's
sentence on an undocumented blocking rule, and clause 4.1's "a verdict already given".
Clause 6.2's last paragraph (two readers) routed to acceptance/ROUTED.md, on its open row.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ict it takes and the case without one

After run 82: clause 5.1 drops the sentence on a blocking rule whose documentation is missing,
section 2's closing paragraph being where that is said, and that paragraph ends the section;
clause 4.1 and section 1 name the verdict as one the detector already holds under the detector
specification's section 8, and say that without one the restated sentences are the test.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ng paragraph and clause 5.1

Every keyed item at threshold, one miss on clause 4.3 tolerated. Two findings in text the
change wrote or set against it: section 2's closing paragraph on an undocumented blocking
rule, and clause 5.1's first paragraph set against it, three readers asking whether such a
rule has to appear in the listing. Clause 6.2's first paragraph against clause 6.4's defaults
(two readers) routed to acceptance/ROUTED.md.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…, from run 83

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…he document asks of defences

After run 83: the closing paragraph says that nothing this document asks of defences, clause
5.1's listing included, is asked of a blocking rule whose documentation is missing, and that a
toolchain running one has failed clause 4.2 whether or not its listing shows it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ction 2's closing paragraph

Every keyed item five of five. Three findings in text the change wrote or altered: clause
4.1's first paragraph and its point 2, readers unable to tell which of two tests governs, and
section 2's closing paragraph. Section 2's Project record entry against clauses 6.1, 6.2 and
6.4 (two readers) routed to acceptance/ROUTED.md.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…es 6.1, 6.2 and 6.4

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…aragraph in plain sentences

After run 84: clause 4.1 holds the detector to every MUST of the detector specification's
sections 4 to 7 and says the restated sentences are where to look first and not the whole
test, a grader without that document checking only them and saying so; section 1 says the
same. Section 2's closing paragraph says clause 5.1 does not require an undocumented blocking
rule to be listed, and that clauses 4.2 and 8.1 reach it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ng paragraph against clause 8.1

Every keyed item five of five. Two findings in text the change wrote or altered: section 2's
closing paragraph, "Clauses 4.2 and 8.1 reach every Blocking Rule", and clause 8.1's first
paragraph set against it, whose exclusion of a third-party catalogue it contradicted. Clause
6.2's first paragraph against clause 6.4 (two readers) routed to acceptance/ROUTED.md.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… 6.4 again

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
After run 85: the paragraph on an undocumented blocking rule no longer says clause 8.1 reaches
every blocking rule a toolchain runs, which contradicted that clause's exclusion of a
third-party detector's native catalogue; clause 4.2 is the clause that reaches them all.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Every keyed item at threshold, one miss on clause 6.3 tolerated. No finding in text the change
wrote or altered. Four findings in untouched text routed to acceptance/ROUTED.md: clause 6.1's
first paragraph and section 2's Project record entry (two readers each), clause 6.2's first
paragraph against clause 6.4, and clause 6.4 itself. The changelog names the run.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…inst 6.2 new

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@LTSCommerce

Copy link
Copy Markdown
Member Author

Run 087: evidence under ACCEPTANCE.md, The record. Posted once; never edited, hidden or deleted.

Command and working directory

ccy-claude -p --model haiku --safe-mode --tools '' --setting-sources '' --strict-mcp-config --no-session-persistence --output-format json < prompt.txt, each reader in a fresh empty directory made by mktemp -d outside the repository

Model version each reader reported

reader 1: claude-haiku-5-5
reader 2: claude-haiku-5-5
reader 3: claude-haiku-5-5
reader 4: claude-haiku-5-5
reader 5: claude-haiku-5-5

The delegated marker's task prompt

MODE: mark

Worktree: <worktree> (branch `editor/defined-terms`). The readers read commit daa2512. Read, at that commit and in that worktree: ACCEPTANCE.md in full (it is the process as pull request 22 proposes it, merged into this branch; the run is made under that process change before it merges, at commit 568e323, named here before the readers started), acceptance/runs/README.md, acceptance/toolchain/QUESTIONS.md, acceptance/toolchain/KEY.md, acceptance/fixtures/zigpipe.md and TOOLING-SPEC.md. You may read acceptance/runs/086-toolchain-contradictions-run-14.md for the shape of a record only; ACCEPTANCE.md says a judgement an earlier run recorded is not a rule.

Run: 087. Document: TOOLING-SPEC.md. Change: defined terms, pull request 24 (every use of a defined term in the three documents linked to its terminology entry, with the entries themselves unchanged in substance; in this document the section 2 table and clause 4.1 say Rule harness where they said Harness, the section 3 table's correct-construction row says the project supplies the remediation docs content, and clause 4.5's uses of "remediation" link to the method's term). Run 55 of this document failed on passages the toolchain contradictions change (pull request 25) rewrites; that change passed its own cohort at run 86 and has since been merged into this branch at its commit c1ad65b, so this is a fresh run of this document. The paragraphs that change rewrote (section 1, section 2's closing paragraph, clauses 4.1, 4.2, 4.3, 8.1, 9.1, 9.2 and section 9, and the section 3 table's Remediation docs row) are that change's text, and this change's text is what the first diff below shows beyond them. Pull request: 24, https://github.com/Defence-Before-Fix/defence-before-fix.github.io/pull/24. Run within the pull request: 9 for this document (runs 33, 37, 40, 43, 46, 49 and 52 under the earlier process and run 55 under this one came before). Record file to write: <worktree>/acceptance/runs/087-defined-terms-toolchain-run-9.md. Do not commit it.

Sheets: <run-dir>/sheet-1.md to sheet-5.md, each the `result` of reader-N.json. Prompt the readers received: <run-dir>/prompt.txt; its sha256 is 32c7ea2c954a34c0fff11518b39705d732d7014286118b53c959effe121f4c16, and it is byte for byte the question set, TOOLING-SPEC.md and the fixture at daa2512, each after one `===== FILE: <name> =====` line, one blank line between files. Model: every reader reported claude-haiku-5-5 (<run-dir>/models.txt); the cohort's model named for the run is claude-haiku-5-5. Every reader's JSON has is_error false and subtype success; no reader is set aside.

Facts the editor supplies for the record: cohort of five readers, none reused from any earlier run; each a separate `claude -p` process started through the `ccy-claude` wrapper (which only reattaches the session's credential) in a fresh empty directory made by `mktemp -d` outside any repository, with the packet on standard input, command `ccy-claude -p --model haiku --safe-mode --tools '' --setting-sources '' --strict-mcp-config --no-session-persistence --output-format json < prompt.txt`; no tools, no settings, no project context, no saved session; the machine applies no managed settings; the editor attests the rest of the isolation. Marked by a delegated marker, a fresh `dbf-spec-editor` agent (Claude Opus) given this instruction and its agent definition, having seen neither the drafting nor the review.

Text the change wrote or altered, for "Where a finding lies": the output of `git -C <worktree> diff c1ad65b daa2512 -- TOOLING-SPEC.md`, which is this change's text over and above the merged toolchain change at its commit c1ad65b (the merge base with `next` is 9e914fe; `git -C <worktree> diff 9e914fe daa2512 -- TOOLING-SPEC.md` shows both changes together, and a paragraph only the toolchain change altered is not this change's text). Run both and read them. A finding in a paragraph the first diff adds, rewords, moves, deletes a sentence from, or changes a word, term or link in, a paragraph the change parts from what it refers to, or that a reader sets against such a paragraph, blocks; any other finding is routed to acceptance/ROUTED.md, and the record says so for each. This change links terms, so many paragraphs carry a changed link: read the diff rather than assuming a paragraph untouched.

Mark every sheet, keyed item by keyed item, by ACCEPTANCE.md's Marking section and the key alone. Write the record stating what acceptance/runs/README.md lists, in its order, with the marks table, each miss with the reader's reasoning in brief, every passage named under question 4 with its words or description, clause and readers, each finding and where it lies, any open point and the direction you marked it, the process-change commit 568e323, the verdict, and a placeholder line for the link to the posted sheets. Reply with the verdict and the findings only, under thirty lines.

The agent definition the marker ran under

---
name: dbf-spec-editor
description: Drafts, reviews, key-updates, marks or records a change to the Defence Before Fix specification, one mode per dispatch, following the specification repository's CONTRIBUTING.md, SCOPE.md and ACCEPTANCE.md exactly. Dispatched by the dbf-spec-change skill; it cannot run a cohort itself.
tools: Read, Write, Edit, Grep, Glob, Bash
model: opus
---

You work on one change to the Defence Before Fix specification, in the worktree path you are
given. The process is defined by that repository's `CONTRIBUTING.md`, `SCOPE.md`,
`ACCEPTANCE.md` and `acceptance/README.md`; read the ones your mode needs, in full, before you
act. You invent no steps. You never merge, push to `next` or `main`, release, tag or publish,
and you never change a question, threshold or fixture. Your prompt names one mode.

Write as the specification is written: British spelling, no em dashes, defined terms linked as
`spec-qa.py` requires, every clause or section number linked to its heading. Commit on the
worktree's branch.

## MODE: draft

1. Read `SCOPE.md`, `DECLINED.md`, and every clause the change touches, with the terminology
   entries they use.
2. Decide the kind. A change to the sentences carrying MUST, SHOULD or MAY in a numbered section
   or appendix is an obligation; anything else is a clarity edit.
3. For an obligation, answer the five SCOPE tests in a sentence or two each, and name the
   section the obligation extends. If a test fails, or an existing clause already covers it, say
   so and stop without editing.
4. Make the smallest edit that does the job, in the clause that owns the subject.
5. Add one line under `Unreleased` in `CHANGELOG.md`, saying what changed and why, with a
   placeholder `run NNN`. Change no version.
6. If Appendix A changed, run `python3 build-agent-surfaces.py` and commit its outputs.
7. Run `python3 spec-qa.py` and `python3 -m unittest discover -s tools -p 'test_*.py'`; both
   clean.
8. Reply with: kind, SCOPE answers, files changed, commit, QA result, and a filled
   `.github/PULL_REQUEST_TEMPLATE.md` body. Under forty lines.

## MODE: review

You have not seen the drafting. Read the whole changed document and the diff against
`origin/next`. Report, numbered, with clause numbers: contradictions with other clauses, terms
used outside their definition, a sentence a reader could take two ways, an obligation an owner
could not verify from the record. Do not edit.

## MODE: keys

Read `acceptance/README.md` and the `KEY.md` for each changed document. Update every quotation of
a changed sentence to the new wording, verbatim, in a new commit; run `python3 spec-qa.py` until
`key-quote-stale` is gone. If the change adds a load-bearing obligation no keyed question
covers, propose the question and its key in your reply; add it only if your prompt says the owner
has decided to.

## MODE: mark

You have not seen the drafting or the review. Read `ACCEPTANCE.md` in full, the `KEY.md` for the
document, the document at the commit named, and the sheets under `<run-dir>/`.

- Mark each sheet against the key, keyed item by keyed item, by the rules under "Marking" in
  `ACCEPTANCE.md` and nothing else: the key's required elements, accepted grades, conditions and
  wrong readings. Invent no judgement; where neither the rules nor the key settles a mark, mark
  it in the direction the open-point rule gives and record the point.
- A single miss under questions 1 and 3 counts against the document only where the key names
  that reading; say which.
- For question 4, record every passage named, with its words or description and its clause.
  Group the passages by paragraph, count the readers, and for each finding say whether it lies in
  text the change wrote or altered, read against the diff the prompt gives you, or is routed to
  `acceptance/ROUTED.md`. Ignore any suggestion a reader volunteers.
- Apply the pass criteria exactly.
- Write `acceptance/runs/NNN-<slug>-run-<k>.md` stating what `acceptance/runs/README.md` lists,
  in its order. Do not commit it. Reply with the verdict and the findings only.

## MODE: record

Commit the run record, replace the `run NNN` placeholder in `Unreleased` with a link to it, and
for an obligation set the document header to `<next version>-dev, unpublished` in the same
commit if it still names a published version. Run `python3 spec-qa.py` and
`python3 tools/changes.py --base origin/next`; both clean. Reply with the commit.

@LTSCommerce

Copy link
Copy Markdown
Member Author

Run 087: evidence under ACCEPTANCE.md, The record. Posted once; never edited, hidden or deleted.

Answer sheets, each reader's whole output as its process returned it

reader-1

{"duration_api_ms":53041,"stop_reason":"end_turn","session_id":"296fce99-a0f8-4702-ad6f-0de7aeb90ec1","total_cost_usd":0.00943713,"usage":{"input_tokens":2,"cache_creation_input_tokens":15017,"cache_read_input_tokens":2153,"output_tokens":12824,"output_tokens_details":{"thinking_tokens":10804},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":15017,"ephemeral_5m_input_tokens":0},"inference_geo":"global","iterations":[{"input_tokens":2,"output_tokens":12824,"cache_read_input_tokens":2153,"cache_creation_input_tokens":15017,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":15017},"type":"message"}],"speed":"standard","fallback_credit":null},"modelUsage":{"claude-haiku-5-5":{"inputTokens":2,"outputTokens":12824,"cacheReadInputTokens":2153,"cacheCreationInputTokens":15017,"webSearchRequests":0,"costUSD":0.00943713,"contextWindow":1000000,"maxOutputTokens":128000,"thinkingTokens":10804,"canonicalModel":"claude-haiku-5-5","provider":"firstParty","costBasis":"list"}},"permission_denials":[],"terminal_reason":"completed","fast_mode_state":"off","fast_mode_disabled_reason":"sdk_opt_in_required","subagent_stats":{"spawned":0,"requested":{"background":0,"foreground":0,"unset":0},"started_in_background":0,"max_depth":0,"spawned_by_subagents":0,"completed":0,"failed":0,"killed":{"parent":0,"user":0,"system":0},"refused":{"depth_limit":0,"concurrency_limit":0,"budget":0},"by_type":{}},"safety_stops":0,"is_error":false,"num_turns":1,"subtype":"success","api_error_status":null,"result":"# Answers to QUESTIONS.md\n\n## 1. Restatement\n\n- A project's toolchain is everything it assembles to run its checks, including detectors, runners, and the parts that route, list, record and resolve. Conformance is judged on that assembled whole.\n- Every defence routed through a detector must meet the detector specification, and every blocking rule the toolchain runs must resolve its identifier to on-disk documentation that states the correct construction.\n- Suppression routes that bypass the project record must be disabled or caught by a blocking defence. Exceptions go in the project record.\n- The toolchain's entry point must report every defence locally, including on a subset of files, print identifiers unaltered, and run detectors before runners, stopping on a detector failure.\n- The toolchain must list active defences without running them, derive that list from the loaded configuration, and list the project record the same way.\n- Agent-context summaries and automatic delivery are SHOULDs. A shipped toolchain also has self-audit MUSTs, and a shipping project has a separate artefact grade.\n\n## 2. Load-bearing statements\n\n**2a.** Conformance is measured at the project level, and the toolchain is whatever the project assembles to run its checks. The document says: \"**A [Toolchain] is measured at the project level.** It is whatever the project assembles to run its checks through: the [Detectors] and [Runners], and the parts around them that route, list, record and resolve.\" It adds: \"[Conformance] is a property of the assembled whole, because that is where it counts.\"\n\n**2b.** The assembly receives one conformance grade. The individual parts are evidence for that grade and do not earn grades of their own. The document says: \"Those parts may be third-party, first-party or project-level, in any combination.\" It also says: \"The project-level verdict is a single grade; which part of the [Toolchain] satisfied each clause is evidence for that grade, not a second grade.\"\n\n**2c.** The project has two grades, one for the project and one for the artefact it ships. Neither implies the other. The document says: \"The two verdicts MUST be graded and declared separately, and neither implies the other. The two levels are the project grade of section 9, which every project has, and the artefact grade, which only a project that ships has.\" It adds: \"a project that ships nothing has only the one.\"\n\n## 3. Application\n\nVerdicts are against the fixture alone. The detector specification was not provided, so the verdicts on 4.1 and 4.4 rest on the restated parts that clauses 4.1 and 4.4 carry. Those verdicts cover only what the restatement checks, as the document instructs.\n\n| Clause | Verdict | Reasoning |\n|---|---|---|\n| 4.1 | No | Lintomatic has two bundled rules with no documentation, and nothing in the project or zig-qa supplies it. The table's row \"Two [Bundled rules] have no documentation / Nothing for those two / Fails\" applies. |\n| 4.2 | No | The two undocumented blocking Lintomatic rules are enabled and `zig-qa list` prints their path as `(none)`. The document says \"One [Identifier] that does not resolve fails this clause, however many others do.\" |\n| 4.3 | Yes | `ignore_comments = false` disables the inline ignore project-wide, and exceptions are kept in `quality-exceptions.toml`. The fixture mentions no other suppression route. |\n| 4.4 | Yes | `zig-qa run` runs locally with no service, takes `<path>` for a subset, and prints Lintomatic's output unchanged, so identifiers are printed unaltered. |\n| 4.5 | Yes | `zig-qa run` runs Lintomatic first and \"stops when Lintomatic fails\", and CI runs it. |\n| 5.1 | Yes | `zig-qa list` reads `lintomatic.toml` without running anything and prints identifier, one-line summary and documentation path for each rule. |\n| 5.2 | Yes | The listing is read from the same `lintomatic.toml` that `zig-qa run` uses, not from a hand-kept file. |\n| 5.3 | Yes | The listing includes the six `zq.*` rules and the four `proj.*` rules alongside Lintomatic's bundled rules. |\n| 6.1 | Yes | The project record is `quality-exceptions.toml`, and `zig-qa run` loads it itself. |\n| 6.2 | No | The only check is that `reason` is non-empty, which the document says \"does not satisfy this clause\". The toolchain does not reject generic phrasing, and does not check for a named hazard or scope. |\n| 6.3 | Yes | `zig-qa list --exceptions` prints entries in the same format as the rule listing. |\n\n**Section 9, project conformance.** No. The project fails 4.1, 4.2 and 6.2, so it does not conform. Partial conformance cannot be described as conformance.\n\n**Conformance with agent support.** No. Section 7 is not met. The fixture says Zigpipe publishes no agent summary and has no `AGENTS.md`. This is moot, since the project does not conform.\n\n**Section 8.** It does not apply to Zigpipe's project grade. Zigpipe \"does not ship any tooling to other projects\", and section 8 bears only on a shipped artefact. The company's zig-qa package is shipped, so section 8 would bear on that package's own artefact grade if one is produced, but that is not a grade of Zigpipe.\n\n**Effect of the missing declaration.** None. Section 9.2 makes the declaration optional, and \"a verdict on any [Toolchain], declared or not, rests on that exercise and not on the claim.\" The duty to record a known gap in a declaration falls only on projects that declare, but a gap found by a Practitioner is recorded under method clause 3.2 whether or not the project declares.\n\n## 4. Confusion\n\nClause 6.2. The heading and the first body sentence require the justification to \"name the Hazard being accepted and the scope of the Exception\", but the only enforcement the clause specifies is a documented check for pasteable generic phrases. On my reading, I could not tell which check, if any, would verify that the hazard and scope are named.","ttft_ms":45796,"type":"result","duration_ms":53470,"uuid":"33550e35-2bb1-4392-8ed1-cfccc07e40eb","ttft_stream_ms":1015,"time_to_request_ms":430,"first_content_frame_ms":1015,"queued_turn_count":0,"result_index":0}

reader-2

{"duration_api_ms":52367,"stop_reason":"end_turn","session_id":"cf25e1a9-69ff-4c2c-a604-3e2994ee93cd","total_cost_usd":0.009404429999999998,"usage":{"input_tokens":2,"cache_creation_input_tokens":15016,"cache_read_input_tokens":2153,"output_tokens":12759,"output_tokens_details":{"thinking_tokens":10548},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":15016,"ephemeral_5m_input_tokens":0},"inference_geo":"global","iterations":[{"input_tokens":2,"output_tokens":12759,"cache_read_input_tokens":2153,"cache_creation_input_tokens":15016,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":15016},"type":"message"}],"speed":"standard","fallback_credit":null},"modelUsage":{"claude-haiku-5-5":{"inputTokens":2,"outputTokens":12759,"cacheReadInputTokens":2153,"cacheCreationInputTokens":15016,"webSearchRequests":0,"costUSD":0.009404429999999998,"contextWindow":1000000,"maxOutputTokens":128000,"thinkingTokens":10548,"canonicalModel":"claude-haiku-5-5","provider":"firstParty","costBasis":"list"}},"permission_denials":[],"terminal_reason":"completed","fast_mode_state":"off","fast_mode_disabled_reason":"sdk_opt_in_required","subagent_stats":{"spawned":0,"requested":{"background":0,"foreground":0,"unset":0},"started_in_background":0,"max_depth":0,"spawned_by_subagents":0,"completed":0,"failed":0,"killed":{"parent":0,"user":0,"system":0},"refused":{"depth_limit":0,"concurrency_limit":0,"budget":0},"by_type":{}},"safety_stops":0,"is_error":false,"num_turns":1,"subtype":"success","api_error_status":null,"result":"## 1. Restatement\n\n- A project's toolchain must make the method's mechanisms available without the project building them itself. Wrapping a third-party detector is allowed, and the wrapped pair is what gets judged.\n- Every detector the toolchain routes a defence through must conform to the detector specification, and the toolchain must not route defences through a detector that does not.\n- Every identifier a blocking rule can print must resolve to on-disk documentation, offline, for the project's own rules as well as the bundled ones.\n- Suppression routes that bypass the project record must be disabled or guarded by a blocking defence, and irreducible cases go to the project record with a justification.\n- The entry point runs detectors before runners and stops on a detector failure. Its output reports every defence and identifier locally, over a subset down to one file.\n- The listing of active defences is derived from the loaded configuration and includes the project's own defences. The project record has a defined location, requires a specific justification for each exception, and can be listed the same way as the defences.\n\n## 2. Load-bearing statements\n\n**2a.** Conformance is measured at the project level, and the toolchain is whatever the project assembles to run its checks. The document says: \"**A [Toolchain] is measured at the project level.** It is whatever the project assembles to run its checks through: the [Detectors] and [Runners], and the parts around them that route, list, record and resolve.\" It also says \"[Conformance] is a property of the assembled whole.\"\n\n**2b.** The assembly receives one conformance grade. The individual parts are evidence for that grade and are not graded separately. The document says: \"The project-level verdict is a single grade; which part of the [Toolchain] satisfied each clause is evidence for that grade, not a second grade.\" If the project also ships an artefact, that artefact gets its own separate grade under clause 9.1, but the assembly itself has one grade.\n\n**2c.** The project has two grades: a project grade under section 9 and an artefact grade for the published package under clause 9.1. One does not imply the other. The document says: \"The two verdicts MUST be graded and declared separately, and neither implies the other. The two levels are the project grade of section 9, which every project has, and the artefact grade, which only a project that ships has.\"\n\n## 3. Application\n\nI could only check the points the document restates from the detector specification (4.1 and 4.4). I did not have that document, so the verdicts on those clauses cover the restated points only.\n\nI read the two undocumented Lintomatic rules as blocking. The fixture says `zig-qa run` stops when Lintomatic fails, and that they are enabled, but it does not state their severity directly.\n\n| Clause | Verdict | Reasoning |\n| --- | --- | --- |\n| 4.1 | No | Lintomatic is the detector, and it hosts bespoke rules, prints identifiers, runs locally, and has its ignore comment disabled. It fails on offline resolution: two of its forty bundled rules have no documentation, and the document says \"Nothing for those two\" fails. Neither the project nor zig-qa supplies it. |\n| 4.2 | No | Two enabled bundled rules print identifiers that resolve to nothing, and the document says \"One [Identifier] that does not resolve fails this clause, however many others do.\" The places for documentation exist (`docs/defences/`, `docs/rules/`), but correct construction is evidenced only for the `proj.*` pages. |\n| 4.3 | Yes | `ignore_comments = false` disables the inline route, and exceptions go to `quality-exceptions.toml`, which is the project record. The fixture describes no other suppression route, and I have not inferred one. |\n| 4.4 | Yes | `zig-qa run` runs locally with no service, takes a path argument, and prints Lintomatic's output unchanged, so identifiers appear as printed. |\n| 4.5 | Yes | `zig-qa run` runs Lintomatic before the test suite and stops when Lintomatic fails. CI runs it. |\n| 5.1 | Yes | `zig-qa list` reads the configuration without running any rule and prints identifier, summary and documentation path. The two undocumented rules show `(none)`. They are not defences under section 2, so the listing does not need to route to documentation for them. |\n| 5.2 | Yes | The listing is produced from `lintomatic.toml`, which is the configuration that `zig-qa run` also uses, so it is derived and not hand-maintained. |\n| 5.3 | Yes | The four `proj.*` rules and the six `zq.*` rules all appear in `zig-qa list`. |\n| 6.1 | Yes | The location is `quality-exceptions.toml`, and `zig-qa run` loads it. |\n| 6.2 | No | The only check is that `reason` is non-empty, and the document says \"A field that is merely present and non-empty does not satisfy this clause.\" There is no check that the justification names the hazard and scope, and no check against generic phrases. |\n| 6.3 | Yes | `zig-qa list --exceptions` prints exceptions in the same format as the rule listing. |\n\n**Section 9.** Zigpipe does not conform. Clauses 4.1, 4.2 and 6.2 fail, and the document says \"Partial [Conformance] MUST NOT be described as [Conformance].\"\n\n**Agent support.** Zigpipe does not conform with agent support. That requires conformance first, and the fixture also shows no agent summary (7.1) and no delivery into a file the agents load (7.2).\n\n**Section 8.** Section 8 does not apply to Zigpipe's grade. The fixture says Zigpipe \"does not ship any tooling to other projects,\" and the document says a project that assembles without shipping \"this section does not bear on its [Conformance].\" `zig-qa` is a separate company package, so its own artefact grade would be a separate verdict that this grading does not cover.\n\n**Absence of a declaration.** The absence does not affect the verdict. Clause 9.2 says \"The declaration is optional,\" and \"A verdict on any [Toolchain], declared or not, rests on that exercise and not on the claim.\" The duty to record known gaps in a declaration falls only on projects that have one, but method clause 3.2 still applies to any gap a practitioner finds.\n\n## 4. Confusion\n\n- **Section 2, \"Bundled defence\", and clause 8.1.** Section 2 defines a bundled defence as \"one with its documentation, [Blocking], and routed through the [Toolchain]'s own entry point,\" which means it already has documentation. Clause 8.1 is titled \"A shipped toolchain MUST fail its own release if a bundled defence lacks resolvable documentation,\" and its body refers to \"a missing page.\" The two passages read as if they describe a bundled defence differently.","ttft_ms":44437,"type":"result","duration_ms":52833,"uuid":"ccc8ffe1-fcb8-443d-9eda-1124a9972d75","ttft_stream_ms":1011,"time_to_request_ms":465,"first_content_frame_ms":1013,"queued_turn_count":0,"result_index":0}

reader-3

{"duration_api_ms":70701,"stop_reason":"end_turn","session_id":"e236b5cc-6215-49ba-8f02-ca3730993fbd","total_cost_usd":0.008699189999999999,"usage":{"input_tokens":2,"cache_creation_input_tokens":341,"cache_read_input_tokens":16829,"output_tokens":16925,"output_tokens_details":{"thinking_tokens":14823},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":341,"ephemeral_5m_input_tokens":0},"inference_geo":"global","iterations":[{"input_tokens":2,"output_tokens":16925,"cache_read_input_tokens":16829,"cache_creation_input_tokens":341,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":341},"type":"message"}],"speed":"standard","fallback_credit":null},"modelUsage":{"claude-haiku-5-5":{"inputTokens":2,"outputTokens":16925,"cacheReadInputTokens":16829,"cacheCreationInputTokens":341,"webSearchRequests":0,"costUSD":0.008699189999999999,"contextWindow":1000000,"maxOutputTokens":128000,"thinkingTokens":14823,"canonicalModel":"claude-haiku-5-5","provider":"firstParty","costBasis":"list"}},"permission_denials":[],"terminal_reason":"completed","fast_mode_state":"off","fast_mode_disabled_reason":"sdk_opt_in_required","subagent_stats":{"spawned":0,"requested":{"background":0,"foreground":0,"unset":0},"started_in_background":0,"max_depth":0,"spawned_by_subagents":0,"completed":0,"failed":0,"killed":{"parent":0,"user":0,"system":0},"refused":{"depth_limit":0,"concurrency_limit":0,"budget":0},"by_type":{}},"safety_stops":0,"is_error":false,"num_turns":1,"subtype":"success","api_error_status":null,"result":"## 1. Restatement\n\n- A project's toolchain, the whole assembled set of detectors, runners and glue, must make each defence governable, not just runnable.\n- Every defence must go through a detector that conforms to the detector specification, and every blocking rule's identifier must resolve offline to documentation that states the correct construction.\n- Bypasses such as inline ignores and silent baselines must be disabled or made to fail, and irreducible cases must go in a project record the toolchain reads.\n- Every exception needs a specific written justification that names the hazard and scope, and generic justifications must be rejected.\n- The toolchain must list active defences and the project record from the live configuration without running anything, including the project's own rules, and the two listings must work the same way.\n- The entry point must run detectors before runners, stop on detector failure, and work locally on a subset down to one file. Shipped toolchains must also self-audit their documentation and run their own rules on their own source.\n\n## 2. Load-bearing statements\n\n**2a.** Conformance is measured at the project level, and the toolchain is everything the project assembles to run its checks. The document says: \"A [Toolchain] is measured at the project level. It is whatever the project assembles to run its checks through: the [Detectors] and [Runners], and the parts around them that route, list, record and resolve.\"\n\n**2b.** The assembly receives one conformance grade. The individual parts are evidence for that grade and are not graded separately: \"The project-level verdict is a single grade; which part of the [Toolchain] satisfied each clause is evidence for that grade, not a second grade.\" The document also says the parts \"may be third-party, first-party or project-level, in any combination.\"\n\n**2c.** The project has two grades: a project grade, which every project has, and an artefact grade, which a project that ships has. Neither implies the other: \"The two verdicts MUST be graded and declared separately, and neither implies the other. The two levels are the project grade of section 9, which every project has, and the artefact grade, which only a project that ships has.\"\n\n## 3. Application\n\n| Clause | Verdict | Reasoning |\n|---|---|---|\n| 4.1 | No | Lintomatic's two undocumented bundled rules get nothing from the project or zig-qa. The document's own wrapping table says \"Two [Bundled rules] have no documentation \\| Nothing for those two \\| Fails.\" I could check only the restated points, and I say so here. |\n| 4.2 | No | Two enabled Lintomatic bundled rules print identifiers whose documentation path is `(none)`, and nothing supplies documentation for them. One identifier that doesn't resolve fails the clause. This assumes the two rules are blocking, which the fixture does not state. |\n| 4.3 | Yes | `ignore_comments = false` disables the inline `// lintomatic-ignore` route, and exceptions are routed to `quality-exceptions.toml`. The fixture does not describe any other Lintomatic suppression route, such as a baseline, so this covers the one described. |\n| 4.4 | Yes | `zig-qa run` runs locally with no service, `zig-qa run <path>` narrows to a single file, it prints Lintomatic's output unchanged, and CI runs it. |\n| 4.5 | Yes | `zig-qa run` runs Lintomatic before the test suite and \"stops when Lintomatic fails,\" and CI runs it. |\n| 5.1 | Yes | `zig-qa list` reads `lintomatic.toml` and prints each active rule's identifier, one-line summary and documentation path, without running any rule. |\n| 5.2 | Yes | The listing is generated from `lintomatic.toml`, the configuration Lintomatic loads, so a newly added rule appears without anyone editing the list. The fixture implies the two read the same configuration but does not say so outright. |\n| 5.3 | Yes | `zig-qa list` includes the four `proj.*` rules, whose documentation states what each forbids, why, and what to write instead, alongside the bundled `zq.*` rules. |\n| 6.1 | Yes | `quality-exceptions.toml` is the defined location, and `zig-qa run` loads it. The fixture describes only exceptions in that file, with no stated location for calibrations or conventions. |\n| 6.2 | No | `zig-qa run` refuses only an empty `reason`. The clause says a field that is \"merely present and non-empty does not satisfy this clause,\" and there is no documented check for generic text such as \"needed for now\" or \"TODO.\" The omission half is met and the generic-rejection half is not. |\n| 6.3 | Yes | `zig-qa list --exceptions` prints the exceptions file \"in the same format as the rule listing,\" from the same script. |\n\n**Conformance under section 9:** No. Clauses 4.1, 4.2 and 6.2 fail, and section 9 requires every MUST in sections 4 to 6 to hold across the assembled parts. The toolchain is not Conforming, and partial conformance may not be described as conformance.\n\n**Conformance with agent support:** No. Section 9 requires conformance first, and the project also does neither thing section 7 recommends. It publishes no defence summary for agents (7.1) and has no `AGENTS.md` or equivalent to deliver one into (7.2).\n\n**Whether section 8 applies:** No. Section 8 bears only on the artefact grade of a project that ships a detector or toolchain. The fixture says Zigpipe \"does not ship any tooling to other projects.\" zig-qa is published by the company, not by Zigpipe, so section 8 would apply to zig-qa's own artefact grade if that were being graded. It does not change Zigpipe's grade.\n\n**Whether the absence of a declaration affects the verdict:** No. Section 9.2 says the declaration is optional, and a toolchain \"MAY be graded Conforming on evidence by anyone who exercises the clauses above against it.\" The verdict rests on the evidence in the table, and the failures above are the reason for the grade, not the missing declaration.\n\n## 4. Confusion\n\n- Clause 4.1, the sentence beginning \"Behind the table is one question\": \"does the [Detector] meet every MUST of sections 4 to 7 of the [detector specification](DETECTOR-SPEC.md), exercised as its clause 8.1 describes?\" The document does not say what exercising clause 8.1 involves, and I could not check it without the detector specification.","ttft_ms":63771,"type":"result","duration_ms":71236,"uuid":"f0fa5d30-670d-4926-a140-0c3dc2d2d53c","ttft_stream_ms":1105,"time_to_request_ms":530,"first_content_frame_ms":1105,"queued_turn_count":0,"result_index":0}

reader-4

{"duration_api_ms":75874,"stop_reason":"end_turn","session_id":"81cf006b-8a18-42e3-9542-d39b637e7d91","total_cost_usd":0.012300930000000002,"usage":{"input_tokens":2,"cache_creation_input_tokens":15016,"cache_read_input_tokens":2153,"output_tokens":18552,"output_tokens_details":{"thinking_tokens":16205},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":15016,"ephemeral_5m_input_tokens":0},"inference_geo":"global","iterations":[{"input_tokens":2,"output_tokens":18552,"cache_read_input_tokens":2153,"cache_creation_input_tokens":15016,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":15016},"type":"message"}],"speed":"standard","fallback_credit":null},"modelUsage":{"claude-haiku-5-5":{"inputTokens":2,"outputTokens":18552,"cacheReadInputTokens":2153,"cacheCreationInputTokens":15016,"webSearchRequests":0,"costUSD":0.012300930000000002,"contextWindow":1000000,"maxOutputTokens":128000,"thinkingTokens":16205,"canonicalModel":"claude-haiku-5-5","provider":"firstParty","costBasis":"list"}},"permission_denials":[],"terminal_reason":"completed","fast_mode_state":"off","fast_mode_disabled_reason":"sdk_opt_in_required","subagent_stats":{"spawned":0,"requested":{"background":0,"foreground":0,"unset":0},"started_in_background":0,"max_depth":0,"spawned_by_subagents":0,"completed":0,"failed":0,"killed":{"parent":0,"user":0,"system":0},"refused":{"depth_limit":0,"concurrency_limit":0,"budget":0},"by_type":{}},"safety_stops":0,"is_error":false,"num_turns":1,"subtype":"success","api_error_status":null,"result":"## 1. Restatement\n\n- Every detector a project routes a defence through must conform to the detector specification. Wrapping can close a gap but cannot excuse one (4.1).\n- Every identifier a blocking rule prints must resolve offline, from files on disk, to documentation that states the correct construction (4.2).\n- Suppression routes that bypass the project record must be disabled or policed by a blocking defence. Exceptions need written justifications that name the hazard and scope, and generic ones must be rejected (4.3, 6.2).\n- The entry point runs detectors before runners and stops on a detector failure. It runs locally, supports subsets, and prints identifiers unaltered (4.4, 4.5).\n- Active defences must be listable without running them, derived from the active configuration, including the project's own (5.1 to 5.3).\n- The project record must be at a location the toolchain reads, and must be enumerable by the same means as the defences (6.1, 6.3).\n\n## 2. Load-bearing statements\n\n**2a.** Conformance is measured at the project level, and the toolchain is everything the project assembles to run its checks through. That includes the detectors, the runners, and the parts that route, list, record and resolve, from any mix of sources.\n\n> \"**A [Toolchain] is measured at the project level.** It is whatever the project assembles to run its checks through: the [Detectors] and [Runners], and the parts around them that route, list, record and resolve. Those parts may be third-party, first-party or project-level, in any combination.\"\n\n**2b.** The assembly receives one project grade. The individual parts are evidence for that grade, not grades of their own. A second, artefact grade arises only if the project ships something.\n\n> \"The project-level verdict is a single grade; which part of the [Toolchain] satisfied each clause is evidence for that grade, not a second grade.\"\n> \"A project's [Toolchain] [Conforms] if every MUST in sections 4 to 6 holds across the assembled parts, wherever each part came from\"\n\n**2c.** The project has two grades, graded and declared separately. Neither implies the other.\n\n> \"The two verdicts MUST be graded and declared separately, and neither implies the other. The two levels are the project grade of section 9, which every project has, and the artefact grade, which only a project that ships has.\"\n\n## 3. Application to Zigpipe\n\nI did not have `DETECTOR-SPEC.md`. For 4.1, 4.2 and 4.4 I checked only the restated parts and the fixture's description.\n\n| Clause | Verdict | Reasoning |\n|---|---|---|\n| 4.1 | **No** | The two undocumented Lintomatic bundled rules have no wrapping, and the 4.1 table marks \"Two [Bundled rules] have no documentation\" with nothing added as \"Fails\". Lintomatic's conformance to detector spec sections 4 to 7 beyond the restated parts is unverified. |\n| 4.2 | **No** | The two bundled rules are enabled and their identifiers resolve to `(none)`. The fixture does not say they are Blocking; I read them as Blocking because they are enabled in the gating run. The `zq.*` and `proj.*` documentation does resolve on disk. |\n| 4.3 | **Yes** | The only inline route described is `// lintomatic-ignore`, disabled by `ignore_comments = false`. Exceptions go through the file `zig-qa run` loads. The fixture describes no baseline or other route. |\n| 4.4 | **Yes** | `zig-qa run` runs locally with no service, accepts a path down to one file, and prints Lintomatic's output unchanged. Clauses 5.1 to 5.4 of the detector spec were checked only as restated here. |\n| 4.5 | **Yes** | `zig-qa run` runs Lintomatic, stops if it fails, and only then runs the tests. CI runs this command. |\n| 5.1 | **Yes** | `zig-qa list` reads `lintomatic.toml` without running anything and prints identifier, summary and documentation path. The two `(none)` rules are not Defences under section 2, so 5.1 does not require them to be listed. |\n| 5.2 | **Yes** | The listing is generated from `lintomatic.toml`, so a newly added rule appears without editing anything else. The fixture does not say whether `run` and `list` load identical effective config; I assume they do. |\n| 5.3 | **Yes** | The four `proj.*` rules appear in `zig-qa list` alongside the bundled and `zq.*` rules, with their documentation paths. |\n| 6.1 | **Partial** | `quality-exceptions.toml` is a defined location that `zig-qa run` loads. Section 2 defines the project record to include calibrations and conventions too, and the fixture gives neither a location nor a reader for those. If the exceptions file is the whole record, this becomes Yes. |\n| 6.2 | **No** | Only an empty `reason` is rejected. The clause says \"A field that is merely present and non-empty does not satisfy this clause.\" Nothing checks that the reason names the hazard and scope, and nothing rejects generic text such as \"TODO\". |\n| 6.3 | **Yes** | `zig-qa list --exceptions` is the same script and prints the same format as the rule listing. |\n\n**Conforms under section 9: No.** Clauses 4.1, 4.2 and 6.2 fail, and 6.1 is partial. Section 9 says \"Partial [Conformance] MUST NOT be described as [Conformance].\"\n\n**Conforms with agent support: No.** Agent support requires doing what section 7 recommends. The fixture says Zigpipe publishes no defence summary for agents and has no `AGENTS.md` or equivalent, so 7.1 and 7.2 are both unmet. The verdict would be No even if the section 4 to 6 failures were fixed.\n\n**Section 8 applies: No.** Section 8 bears only on the artefact grade, and the fixture says Zigpipe \"does not ship any tooling to other projects.\" The document says: \"A project that assembles its [Toolchain] without shipping it has no release and no [Consuming project], so this section does not bear on its [Conformance].\" The company does publish `zig-qa`, so section 8 would apply to that package's own artefact grade. That is a separate grade, and the fixture is not enough to make it.\n\n**Declaration absence: No effect on the verdict.** Clause 9.2 makes the declaration optional and says \"A verdict on any [Toolchain], declared or not, rests on that exercise and not on the claim.\" The gap-record duty only falls on a project that declares, and a gap a practitioner finds is recorded under method clause 3.2 either way.\n\n## 4. Confusion\n\n- **Section 2, \"Project record\", and clause 6.1.** The definition says the record holds \"[Calibrations], [Exceptions] and conventions,\" and clause 6.1 says \"The [Toolchain] MUST define where the [Project record] lives.\" It is unclear whether the record is one location or a set of them. \"Calibrations\" is linked to the method specification, which I did not have, so I could not check its meaning.","ttft_ms":68836,"type":"result","duration_ms":76353,"uuid":"805e0c70-7af6-4ca7-9a51-953653124fd8","ttft_stream_ms":1238,"time_to_request_ms":510,"first_content_frame_ms":1239,"queued_turn_count":0,"result_index":0}

reader-5

{"duration_api_ms":63126,"stop_reason":"end_turn","session_id":"bf9f531c-190a-4a42-a89d-fe5fc9e7ec04","total_cost_usd":0.00780249,"usage":{"input_tokens":2,"cache_creation_input_tokens":340,"cache_read_input_tokens":16829,"output_tokens":15132,"output_tokens_details":{"thinking_tokens":12771},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":340,"ephemeral_5m_input_tokens":0},"inference_geo":"global","iterations":[{"input_tokens":2,"output_tokens":15132,"cache_read_input_tokens":16829,"cache_creation_input_tokens":340,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":340},"type":"message"}],"speed":"standard","fallback_credit":null},"modelUsage":{"claude-haiku-5-5":{"inputTokens":2,"outputTokens":15132,"cacheReadInputTokens":16829,"cacheCreationInputTokens":340,"webSearchRequests":0,"costUSD":0.00780249,"contextWindow":1000000,"maxOutputTokens":128000,"thinkingTokens":12771,"canonicalModel":"claude-haiku-5-5","provider":"firstParty","costBasis":"list"}},"permission_denials":[],"terminal_reason":"completed","fast_mode_state":"off","fast_mode_disabled_reason":"sdk_opt_in_required","subagent_stats":{"spawned":0,"requested":{"background":0,"foreground":0,"unset":0},"started_in_background":0,"max_depth":0,"spawned_by_subagents":0,"completed":0,"failed":0,"killed":{"parent":0,"user":0,"system":0},"refused":{"depth_limit":0,"concurrency_limit":0,"budget":0},"by_type":{}},"safety_stops":0,"is_error":false,"num_turns":1,"subtype":"success","api_error_status":null,"result":"## 1. Restatement\n\n- A project's toolchain is measured as one assembled whole, whatever mix of third-party, first-party and project-written parts it uses.\n- Defences must be routed only through detectors that conform to the detector specification. Wrapping can fill a gap, but it cannot excuse one.\n- Every identifier a blocking rule can print must resolve to on-disk documentation that ships with the project, and the documentation must state the correct construction.\n- Suppression routes that bypass the project record must be disabled or made to fail a blocking defence. Exceptions need a written justification that names the hazard and the scope.\n- The entry point runs detectors before runners, stops on a detector failure, and prints identifiers unaltered.\n- Defences and the project record must be listable without running them, the listing must be derived from the active configuration, and the project's own defences must appear alongside bundled ones.\n\n## 2. Load-bearing statements\n\n**2a.** Conformance is measured at the project level, and the toolchain is whatever the project assembles to run its checks.\n> \"**A [Toolchain] is measured at the project level.** It is whatever the project assembles to run its checks through: the [Detectors] and [Runners], and the parts around them that route, list, record and resolve.\"\n> \"[Conformance] is a property of the assembled whole, because that is where it counts\"\n\n**2b.** The assembly receives one grade. The individual parts are evidence for that grade, not grades of their own.\n> \"The project-level verdict is a single grade; which part of the [Toolchain] satisfied each clause is evidence for that grade, not a second grade.\"\n> \"Those parts may be third-party, first-party or project-level, in any combination.\"\n\n**2c.** The company's project has two grades, one for the project and one for the artefact it ships, and neither implies the other.\n> \"The two verdicts MUST be graded and declared separately, and neither implies the other.\"\n> \"a project that ships nothing has only the one.\"\n\n## 3. Application to Zigpipe\n\n| Clause | Verdict | Reasoning |\n|---|---|---|\n| 4.1 | **No** | Lintomatic hosts bespoke rules, runs one rule on one file, prints identifiers, runs locally, and has its inline ignore disabled. But two of its forty bundled rules have no documentation, and nothing in the project or zig-qa provides any. The clause's own gap table says \"Two [Bundled rules] have no documentation / Nothing for those two / Fails.\" Caveat: I have only the restated sentences of the detector specification, so this verdict covers only those. |\n| 4.2 | **No** | \"One [Identifier] that does not resolve fails this clause, however many others do.\" Both undocumented bundled rules print identifiers that lead nowhere, and `zig-qa list` shows their path as `(none)`. Caveat: the fixture does not say whether these two rules are Blocking. If they are not, this clause would hold, though 4.1 still fails. Separately, the fixture does not say whether `lintomatic explain` resolves the `zq.*` identifiers, nor what their documentation says about construction. I have not counted either against the verdict. |\n| 4.3 | **Yes** | `ignore_comments = false` disables the inline comment, the only suppression route the fixture describes. Exceptions go through `quality-exceptions.toml`. Caveat: the fixture does not list every Lintomatic route, so this assumes the comment is the only one. |\n| 4.4 | **Yes** | `zig-qa run` runs Lintomatic locally with no service, `zig-qa run <path>` narrows it to a file or directory, and it prints Lintomatic's output unchanged, so identifiers appear as printed. Caveat: detector specification clauses 5.1 to 5.4 are not restated in full. |\n| 4.5 | **Yes** | `zig-qa run` runs Lintomatic, then the tests, and \"stops when Lintomatic fails\". The fixture says \"Both scripts ... are what CI runs.\" |\n| 5.1 | **Yes** | `zig-qa list` prints every active rule with its identifier, a summary and a documentation path, and does not run them. The two undocumented rules are not Defences under section 2, so 5.1 does not require their listing. |\n| 5.2 | **Yes** | `zig-qa list` reads `lintomatic.toml`, the configuration Lintomatic loads, and no hand-maintained list is described. Caveat: the fixture does not say the `zq.*` rules are registered in `lintomatic.toml`. I assumed they are, since they are listed. |\n| 5.3 | **Yes** | The four `proj.*` rules appear in the listing, each with its page in `docs/defences/`. |\n| 6.1 | **Yes** | `quality-exceptions.toml` is a defined location that `zig-qa run` loads. Caveat: the fixture describes only exceptions. It mentions no calibrations or conventions, which section 2 includes in the project record. |\n| 6.2 | **No** | The only check is that `reason` is non-empty, and the clause says \"A field that is merely present and non-empty does not satisfy this clause.\" The fixture describes no check for generic phrases such as \"needed for now\", \"legacy\" or \"TODO\", and no requirement that a reason name the hazard and scope. |\n| 6.3 | **Yes** | `zig-qa list --exceptions` prints the exceptions \"in the same format as the rule listing.\" |\n\n**Conformance under section 9:** No. Clauses 4.1, 4.2 and 6.2 fail on the evidence. Section 9 requires every MUST in sections 4 to 6 to hold. Clause 6.4 is a SHOULD, and the fixture is silent on defaults, but that does not affect this verdict.\n\n**Conformance with agent support:** No. Section 9 requires conformance first, and that already fails. The fixture also shows the section 7 recommendations are not met: \"Zigpipe does not publish a summary of its defences for an agent and has no `AGENTS.md`.\"\n\n**Whether section 8 applies:** No. The fixture says the project \"does not ship any tooling to other projects.\" Section 8 bears only on the artefact grade. Clause 8.2 also says: \"A project that assembles its [Toolchain] without shipping it has no release and no [Consuming project], so this section does not bear on its [Conformance].\" Zig-qa is the company's package, not something Zigpipe ships.\n\n**Whether the absence of a declaration affects the verdict:** No. Clause 9.2 says \"The declaration is optional,\" and \"A verdict on any [Toolchain], declared or not, rests on that exercise and not on the claim.\" Zigpipe carries no gap-record duty because it has no declaration. Any gap a practitioner finds is still recorded under method clause 3.2.\n\n## 4. Confusion\n\nClause 4.1: \"The sentences that follow restate the ones most often failed, so that a grader knows where to look first; they are not the whole test, and a grader without that document to hand can check only them, and says so in the verdict.\"\n\nThe clause does not say where in a Yes/Partial/No verdict that caveat belongs. I put it in the reasoning column above.","ttft_ms":55719,"type":"result","duration_ms":63724,"uuid":"fac13c1d-6614-48fa-a4fc-92fa3879e8c6","ttft_stream_ms":1133,"time_to_request_ms":603,"first_content_frame_ms":1133,"queued_turn_count":0,"result_index":0}

@LTSCommerce

Copy link
Copy Markdown
Member Author

Run 087: evidence under ACCEPTANCE.md, The record. Posted once; never edited, hidden or deleted.

The exact prompt every reader received, part 1 of 1

===== FILE: QUESTIONS.md =====
# Questions for a cold reader of TOOLING-SPEC.md

You have been given `TOOLING-SPEC.md` and the fixture `fixtures/zigpipe.md`, and nothing else.
Read the document once, then answer every question below in order. Quote the document where a
question asks for a quotation. Do not consult anything outside what you were given.

## 1. Restatement

In your own words and in at most six bullets, what does this document require of a project's
toolchain?

## 2. Load-bearing statements

Answer each part of each question in a sentence or two, then quote the sentence or sentences of
the document you are relying on.

- 2a. At what level is toolchain conformance measured, and what is the toolchain?
- 2b. A project's tooling is assembled from a third-party detector, a first-party package and
  the project's own rules. How many conformance grades does that assembly receive, and what is
  the role of the individual parts in reaching it?
- 2c. A company publishes a toolchain package and also uses it on the package's own repository.
  How many conformance grades does that project have, and does one imply the other?

## 3. Application

Grade the Zigpipe project's toolchain, as described in the fixture, against every MUST clause in
sections [4](../../TOOLING-SPEC.md#4-the-detectors-a-toolchain-routes-defences-through) to [6](../../TOOLING-SPEC.md#6-the-project-record): [4.1](../../TOOLING-SPEC.md#41-every-detector-the-toolchain-routes-a-defence-through-must-conform-to-the-detector-specification), [4.2](../../TOOLING-SPEC.md#42-the-toolchain-must-resolve-every-identifier-a-blocking-rule-it-routes-can-print-from-the-installed-copy-without-network-access), [4.3](../../TOOLING-SPEC.md#43-the-toolchain-must-forbid-every-suppression-route-that-bypasses-the-project-record-by-disabling-it-or-by-a-defence-of-its-own), [4.4](../../TOOLING-SPEC.md#44-the-toolchains-own-invocation-must-satisfy-the-detector-specifications-reporting-clauses-for-every-defence-it-routes), [4.5](../../TOOLING-SPEC.md#45-the-toolchains-entry-point-must-run-detectors-before-runners-and-must-stop-on-a-detector-failure), [5.1](../../TOOLING-SPEC.md#51-the-toolchain-must-be-able-to-list-the-defences-active-in-a-project-without-triggering-them), [5.2](../../TOOLING-SPEC.md#52-the-listing-must-be-derived-from-the-active-configuration), [5.3](../../TOOLING-SPEC.md#53-a-projects-own-defences-must-appear-in-the-listing-alongside-bundled-ones), [6.1](../../TOOLING-SPEC.md#61-the-toolchain-must-define-a-location-for-the-project-record-and-must-read-it-itself), [6.2](../../TOOLING-SPEC.md#62-every-exception-in-the-project-record-must-carry-a-written-justification-that-names-the-hazard-and-the-scope-and-the-toolchain-must-reject-a-generic-one), [6.3](../../TOOLING-SPEC.md#63-the-project-record-must-be-enumerable-by-the-same-means-as-the-defences). For each give Yes,
Partial or No and one line of reasoning. Then state whether the toolchain conforms under section
[9](../../TOOLING-SPEC.md#9-conformance) and why, whether it conforms with agent support and why, and whether section [8](../../TOOLING-SPEC.md#8-self-audit) applies to it
and why. Finally, state whether the absence of a declaration affects the verdict, and why.

## 4. Confusion

Quote any passage you found confusing on your one reading, with its clause number. Do not say what
would make it clearer and do not propose any change. Write "none" if there was none.

===== FILE: TOOLING-SPEC.md =====
# Defence Before Fix: Toolchain Specification

**Version**: 0.2.0, published 2026-09-08
**Companion to**: [the method specification](SPEC.md), version 1.1.0, and [the detector specification](DETECTOR-SPEC.md), version 1.0.0
**Author**: [Joseph Edmonds](https://ltscommerce.dev), [Edmonds Commerce](https://edmondscommerce.co.uk)
**Coined**: 22 February 2026, in [the original article](https://ltscommerce.dev/articles/defence-before-fix-static-analysis)

## 1. What this document is for

The key words MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT and MAY are to be interpreted as
described in RFC 2119.

[The method specification](SPEC.md) states what a [Practitioner] does when a [Defect] is found.
[The detector specification](DETECTOR-SPEC.md) states what each [Detector] must offer so that they
can write, prove, run and resolve a [Rule] in it. This document states what a project's
[Toolchain] must offer beyond that, so that the [Rules] become [Defences]
the project governs.

**A [Toolchain] is measured at the project level.** It is whatever the project assembles to
run its checks through: the [Detectors] and [Runners], and the parts around them
that route, list, record and resolve. Those parts may be third-party, first-party or project-level,
in any combination. A third-party [Toolchain] such as `php-qa-ci` can supply all of it. A project
can also meet this document with its own scripts around a bare [Detector]. [Conformance]
is a property of the assembled whole, because that is where it counts: a [Practitioner]
arriving at the project cannot tell which package a mechanism came from, and does not need to.

The three documents are separable because they fail separately, and all three failures have been
observed. A project can follow the method faithfully on a [Toolchain] that gives it nowhere to
record what it decided. A [Toolchain] can offer every mechanism the method needs whilst the
project using it writes no [Rules] at all. A [Detector] can be the best host for
a [Rule] in its language whilst shipping an inline ignore that the project has never decided
whether to allow. Conflating them produces a specification that blames a project for a gap in its
[Toolchain], credits a [Toolchain] for discipline the project supplied itself, or
fails a [Detector] for governance that was never its to decide.

**The governing principle**: where the method specification requires a [Practitioner] to do
something, a [Conforming] [Toolchain] MUST make that possible without the project
building the mechanism first. A [Toolchain] that leaves the project to construct the means has
moved the obligation rather than met it. Where the project builds the means itself, those scripts are
part of its [Toolchain] and are judged as such.

**How to read this document.** A [Toolchain] can be graded from this document alone, on the
evidence a project shows. Where a clause rests on the [detector specification](DETECTOR-SPEC.md),
as clauses 4.1, 4.2 and 4.4 do, it says what it holds the [Detector] to and restates the parts
most often failed; a grader without that document to hand checks what is restated and says so.
The
table in section 2 glosses every term it borrows. Each clause states its obligation in its heading
and first sentence, and the **Why** paragraph beneath is reasoning, not a further requirement. A
link is there for depth and is not a prerequisite for the sentence that carries it.

## 2. Terminology

Terms from the method specification and the [detector specification](DETECTOR-SPEC.md) carry over unchanged. Every
capitalised term links to its definition; the ones this document leans on most are, in short:

| Term               | In one line                                                                                         |
| ------------------ | --------------------------------------------------------------------------------------------------- |
| [Detector]         | A tool that reads code without executing it and reports what it finds                               |
| [Runner]           | A tool that executes code, a test suite or a compilation, and reports what happened                 |
| [Rule]             | One check a [Detector] evaluates                                                                    |
| [Defence]          | A [Rule] with its documentation, in force and [Blocking]                                            |
| [Identifier]       | The stable name printed with a finding that leads to its documentation                              |
| [Remediation docs] | The documentation an [Identifier] leads to: what the [Rule] is about, why, and how to fix a finding |
| [Blocking]         | Fails the run rather than issuing a [Warning]                                                       |
| [Exception]        | A recorded, justified decision to leave an [Instance] unfixed or a [Rule] unapplied                 |
| [Practitioner]     | Whoever is doing the work, a person or an [Agent]                                                   |
| [Owner]            | The human who decides what the codebase may keep                                                    |
| [Bundled rule]     | A [Rule] a [Detector] ships rather than one the project wrote                                       |
| [Rule harness]     | The route by which one [Rule] is run against supplied code on its own                               |

These are additional.

#### Consuming project

A codebase that installs a [Detector] or a [Toolchain] shipped by somebody else. The maintainer of what is installed does not control it and cannot inspect it.

#### Bundled defence

A [Defence] a shipped [Toolchain] carries and enables by default in every [Consuming project]. A [Bundled rule] is the [Detector]-level counterpart; a [Bundled defence] is one with its documentation, [Blocking], and routed through the [Toolchain]'s own entry point.

#### Project record

The place a project writes down the judgements the method specification delegates to it: [Calibrations], [Exceptions] and conventions.

The distinction between a [Bundled defence] and a project's own is significant throughout. A bundled
[Defence] is authored once and runs in codebases its author will never see, so everything a
[Practitioner] needs in order to act on it has to travel with it.

Throughout this document, a [Blocking] [Rule] whose documentation is missing is not yet a
[Defence]. Clause 5.1 does not require it to be listed, because that clause lists [Defences].
Clause 4.2 reaches every [Blocking] [Rule] a [Toolchain] runs, documented or not, and a
[Toolchain] that runs such a [Rule] fails clause 4.2.

## 3. The division of responsibility

Almost every requirement in section 8 of the method specification has two halves. Stating only one
of them is what produces a [Toolchain] that is *nearly* usable. The middle column says which
document states the mechanism half; the assembled [Toolchain] MUST provide every row, whichever
part of it does so.

| Requirement             | The mechanism, and where it is stated                                                                       | The project supplies                 |
| ----------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------ |
| Bespoke [Defences]      | The authoring and registration route, [detector specification](DETECTOR-SPEC.md) 4.1                        | The [Rules]                          |
| The red proof           | A [Rule harness], [detector specification](DETECTOR-SPEC.md) 4.2                                            | The [Fixture] and the red run        |
| Running the [Defence]   | A local invocation, including subsets, [detector specification](DETECTOR-SPEC.md) 5                         | Running it                           |
| [Identifier] resolution | The lookup, [detector specification](DETECTOR-SPEC.md) 6 for [Bundled rules], clause 4.2 here for the rest  | The documentation content            |
| Correct construction    | A place for it to live, clause 4.2 here                                                                     | The [Remediation docs] content       |
| Enumeration             | The listing, section 5 here                                                                                 | The [Defences] listed                |
| [Agent]-context summary | Generation and delivery, section 7 here                                                                     | The terse lines                      |
| Recorded decisions      | A location it reads itself, section 6 here                                                                  | The decisions                        |
| [Suppression]           | A route that can be forbidden, [detector specification](DETECTOR-SPEC.md) 7; forbidding it, clause 4.3 here | The decision, under method section 4 |

Read down the middle column and the shape of a [Conforming] [Toolchain] is already visible. Read across
any row and the failure mode is visible too: either half alone leaves the [Practitioner] stuck.

## 4. The detectors a toolchain routes defences through

### 4.1 Every detector the toolchain routes a defence through MUST conform to the [detector specification](DETECTOR-SPEC.md)

A [Toolchain] MUST NOT route a [Defence] through a [Detector] that does not
[Conform] to [the detector specification](DETECTOR-SPEC.md). That document's MUSTs are those of
its sections 4 to 7, and this clause holds the [Detector] to every one of them: a [Detector]
that fails any of them, after wrapping, fails this clause. The sentences that follow restate
the ones most often failed, so that a grader knows where to look first; they are not the whole
test, and a grader without that document to hand can check only them, and says so in the
verdict. The
[Detector] hosts bespoke [Rules]. It runs one [Rule] on its own against supplied
code. It prints a stable [Identifier] with every finding. It runs locally, down to one file, with
the result in the command's own output and nothing reportable only through a hosted service. It
resolves every [Identifier] a [Bundled rule] can print to documentation shipped with it, offline.
It makes any inline [Suppression] route detectable or disableable. Three points govern how that
is met.

1. **Wrapping is permitted.** The [Toolchain] MAY supply a mechanism the
   [Detector] lacks by wrapping it, with a [Rule harness] script or a
   resolver of its own. The [Detector] together with that wrapping is then what the
   [Practitioner] uses and what is judged.

2. **How the wrapped pair is judged.** Start from the gap, not from what the [Detector] does
   well:

   | The [Detector]'s gap                       | What the [Toolchain] adds                                     | This clause |
   | ------------------------------------------ | ------------------------------------------------------------- | ----------- |
   | Resolves none of its [Identifiers] offline | A resolver keyed on the [Identifier], covering all of them    | Holds       |
   | Two [Bundled rules] have no documentation  | Nothing for those two                                         | Fails       |
   | Two [Bundled rules] have no documentation  | Its own documentation for those two, resolved by [Identifier] | Holds       |

   Behind the table is one question. With the wrapping in place, does the [Detector]
   meet every MUST of sections 4 to 7 of the [detector specification](DETECTOR-SPEC.md),
   exercised as its clause 8.1 describes? If yes, this clause holds. If no, it fails, however
   much else the [Detector] does well, and whether or not a later clause of this document, such
   as clause 4.2 on resolution, names the same gap again. Wrapping can add a mechanism; it
   cannot excuse a gap. What this clause judges is the
   wrapped pair; the [Detector]'s own grade under that document, as an artefact on its own, is a
   separate verdict that the wrapping does not change. Satisfying most of that document is not
   [Conformance] to it, any more than satisfying most of this one is.

3. **What cannot be wrapped.** A [Detector] that cannot host a bespoke [Rule] at all
   cannot be wrapped into [Conformance], and no [Defence] is routed through it.
   It MAY still run as one of the [Toolchain]'s checks, as a formatter or a
   [Runner] does.

**Why**: the method's clauses 3.1 to 3.6 are carried out in a [Detector], and everything this
document adds presumes those clauses can be followed there. A [Toolchain] that lists, records
and resolves beautifully around a [Detector] in which no [Rule] can be written or proven
has governed nothing. The wrapping is permitted because a [Practitioner] cannot tell where a
mechanism lives, and the method does not care. It is bounded because a mechanism the [Detector]
does not offer and the [Toolchain] does not add is a gap the project writes down under method
clause 3.2. A gap recorded is not a gap closed.

### 4.2 The toolchain MUST resolve every identifier a blocking rule it routes can print, from the installed copy, without network access

The [Toolchain] MUST resolve every [Identifier] its [Blocking] [Rules] print to
[Remediation docs] on disk. That is every [Blocking] [Rule] the [Toolchain] runs, the project's
own and the bundled alike. One [Identifier] that does not resolve fails this clause, however
many others do.

The resolving mechanism is keyed on the [Identifier] exactly as printed. Those
[Remediation docs] MUST ship with the project, with the [Toolchain] or with the [Detector]
whose [Rule] they document, at a version tracked together. The
[Toolchain] MUST also give that documentation a place to live, so that a
[Rule author] adding a [Rule] knows where its documentation goes.
The documentation an [Identifier] resolves to MUST state the correct construction, not
only the prohibition, specifically enough to act on, as method clause 8.4 requires. The
[Toolchain] supplies the place and the [Rule author] the text.

This clause closes what the [detector specification](DETECTOR-SPEC.md) leaves open: that
document holds a [Detector] to on-disk resolution of its own [Bundled rules] and no further,
because it cannot know a project's documentation, and this clause reaches the project's own
[Rules] as well. An [Identifier] a third-party [Detector] resolves under that document's clause
6 meets this clause, and one that nothing resolves fails it.

**Why**: method specification clauses 3.6 and 8.3. The [Identifier] has to resolve for the
reader, which for an [Agent] means mechanically and on disk, and the project's own
[Rules] are the ones that carry its knowledge. A [Detector] that prints the
[Identifier] faithfully has done its half; a project in which that string then leads nowhere
has a [Message] that names a pattern without leading anywhere, which method clause 3.6 says
does not [Conform].

### 4.3 The toolchain MUST forbid every suppression route that bypasses the project record, by disabling it or by a defence of its own

A [Conforming] [Toolchain] MUST disable every [Suppression]
route that bypasses the [Project record], or MUST run a [Blocking]
[Defence] that fails on its use. A route bypasses the [Project record] when a finding can be
silenced through it without an entry appearing in the [Project record]: an inline
[Suppression] comment, a per-line ignore and a silently generated [Baseline] all do. The
obligation covers every such route in every [Detector] the [Toolchain] routes a
[Defence] through. The routes are the ones each [Detector] offers: where a [Detector]'s only
route is an ignore comment, this clause is met for that [Detector] once the comment is disabled
or a [Blocking] [Defence] fails on its use, and nothing is owed for a route it does not have.
Irreducible cases MUST be directed to the [Project record],
where clause 6.2 requires a justification.

The [detector specification](DETECTOR-SPEC.md) permits a [Detector] to ship such a route provided
it can be detected or disabled. This clause is where the project's decision is made and enforced,
and the decision is no. A [Baseline] an [Owner] has adopted under method section
4 is therefore kept in the [Project record], or read from a file the record names. It is
never a file the [Detector] generates unseen.

**Why**: a governance mechanism whose escape hatch is an unreviewed comment is not a governance
mechanism. This is the one place this document is stricter than the [Detectors] it assembles
are by default, and it is deliberate. The method specification's position is that
[Suppression] is an [Owner] decision, and an [Owner] cannot decide something
they are never shown. The [Detector] is not asked to forbid the route because the
[Detector] is not the project; the [Toolchain] is the project's, so it is.

The reference implementations both do this. `ts-qa-ci` bans every `eslint-disable` and
`@ts-expect-error` form outright; `php-qa-ci`'s `ForbidInlinePhpstanIgnoreRule` bans inline
`@phpstan-ignore` and directs irreducible cases to the configuration file, where they are visible.

### 4.4 The toolchain's own invocation MUST satisfy the detector specification's reporting clauses for every defence it routes

The [Toolchain]'s own entry point MUST meet clauses 5.1 to 5.4 of the
[detector specification](DETECTOR-SPEC.md) for every [Defence] it routes. That means invocable
locally with no infrastructure, over a subset down to one file, and with the result in the output of
the command the [Practitioner] ran. No [Defence] may be reportable only
through a mode they cannot run. The entry point MUST also print every [Identifier] its
[Detectors] print, unaltered, so that clause 4.3 of the
[detector specification](DETECTOR-SPEC.md) holds through the wrapping. The [Detector]'s verdict
under that clause is on its own output. The [Toolchain]'s is on what reaches the
[Practitioner].

**Why**: method clause 3.5 asks the [Practitioner] to demonstrate enforcement through the
project's own entry point, not through the [Detector] directly. A [Detector] that
[Conforms] on its own, wrapped in a command that runs only the whole codebase or only
elsewhere, has had its reporting clauses undone by the wrapping. The [Practitioner]
is then back to a loop that does not close.

### 4.5 The toolchain's entry point MUST run detectors before runners, and MUST stop on a detector failure

The invocation the project uses to accept changes MUST evaluate its [Detectors] before its
[Runners]. A [Blocking] failure at the [Detector] level MUST stop the
levels below it from being treated as meaningful, in the order method section 5 states. How the
project expresses that sequence, and where it runs, remain out of scope under method section 8.

**Why**: method section 5. A [Detector] is preventive and a test is diagnostic, and a failure
at the [Detector] level produces confusing results at every level above it. The method makes
the ordering a property of the project rather than of any one [Remediation], which is exactly the
kind of property that lives in the [Toolchain] and nowhere else.

## 5. Enumeration

### 5.1 The toolchain MUST be able to list the defences active in a project, without triggering them

The [Toolchain] MUST list every [Defence] active in the project without
running it. The listing MUST include each [Defence]'s [Identifier] and a terse
statement of what it forbids or requires. It MUST provide the route to each one's full documentation.

**Why**: method specification clause 8.5. An [Agent] arriving at a codebase has no colleague to ask.
Without a listing, a project's standards can only be learned by violating them one at a time.

### 5.2 The listing MUST be derived from the active configuration

The listing MUST be generated from the configuration the [Toolchain] actually loads. It
MUST NOT be a hand-maintained document that happens to describe the configuration. The test is
what happens when a [Rule] is added to the configuration and nobody edits anything else: a
derived listing shows it on the next run, and a hand-maintained one does not.

**Why**: a hand-maintained list drifts, and it drifts silently and in the dangerous direction. The
observed failure is a [Rule] that is registered, active, [Blocking], and absent from
the list of [Rules], whilst the list states its own count with confidence. A derived listing cannot
diverge from what is enforced, because the thing enforced is what produced it.

### 5.3 A project's own defences MUST appear in the listing alongside bundled ones

Every [Defence] the project has written itself MUST appear in the listing clause 5.1
requires, meeting its content requirements in full, alongside every [Bundled defence].

For a shipped [Toolchain], the case is the same and worth spelling out. Its
[Defences] against its own source, the ones only its contributors can trigger, are that
project's own [Defences] for this purpose. They MUST appear in the same listing clause 5.1
requires, meeting its content requirements in full, when the [Toolchain] is run on itself,
however they are enabled. Where such a [Defence] is not expressible in the [Toolchain]'s own
[Detectors], its entry MAY be sourced from wherever it is enabled, provided the listing stays derived
under clause 5.2 rather than hand-maintained.

**Why**: the [Practitioner] does not care which package a [Rule] came from. They care what defends the
code in front of them, and a listing that covers only what a shipped [Toolchain] carries describes somebody
else's project.

## 6. The project record

This section exists because of a gap found by cold readers of the method specification, repeatedly
and independently. The method delegates several judgements to project level, and a [Practitioner]
arriving at a project that has recorded none of them has no legal move. That is a [Toolchain]
obligation. The method specification cannot fix it, because the method specification does not own a
file in the project.

### 6.1 The toolchain MUST define a location for the project record, and MUST read it itself

The [Toolchain] MUST define where the [Project record] lives and MUST load it.
Not a documentation convention. A path the [Toolchain] loads.

**Why**: a [Project record] the [Toolchain] does not read can be wrong without anything noticing.
When the [Toolchain] reads it, the written decision and the enforced decision are the same object, and
neither can drift from the other.

### 6.2 Every exception in the project record MUST carry a written justification that names the hazard and the scope, and the toolchain MUST reject a generic one

The [Toolchain] MUST require a written justification on every [Exception].
It MUST NOT supply a default, and MUST reject an [Exception] that omits one. A field that is
merely present and non-empty does not satisfy this clause.

**Why**: an [Exception] without a reason is indistinguishable from an [Exception] nobody would defend,
and the person who could tell them apart is usually gone. Requiring the sentence is the whole
mechanism: it costs the author a minute at the moment they have the reason in mind, and it is the
only thing that makes an [Exception] reviewable later.

`ts-qa-ci`'s `tier-a-exemptions.json` is the reference implementation, and its own two entries
demonstrate the standard: both explain the scope limit as well as the reason.

The justification MUST name the [Hazard] being accepted and the scope of the [Exception].
The [Toolchain] MUST reject a justification that could be pasted onto any [Exception]
unchanged, by a check it documents: "needed for now", "legacy", "TODO" and their like. That check
cannot verify truth, and a [Toolchain]'s [Conformance] MUST NOT be read as having verified
it. Whether the sentence is true is the [Owner]'s judgement under section 4 of the method
specification. That is why clause 6.3 puts every justification in one listing, where a vacuous
one is seen next to its neighbours.

### 6.3 The project record MUST be enumerable by the same means as the defences

Listing the [Defences] and listing the [Project record] MUST be the same kind of operation.

**Why**: method specification clause 8.7. A decision nobody can find will be re-opened by every
[Practitioner] who arrives after it, which converts a settled question into a recurring one.

### 6.4 The toolchain SHOULD state its own defaults for anything the method leaves to the project

Where the method specification delegates a judgement and the project has recorded nothing, a
documented [Toolchain] default is what the [Practitioner] falls back to.

**Why**: this is the deadlock this section exists to break. "The project decides" combined with "the
project has decided nothing" leaves an [Agent] choosing between guessing and stopping. A default
turns the first project-level decision from a prerequisite into a refinement, and the project's
first day is exactly when it has recorded least and can afford the interruption least.

## 7. Agent context

### 7.1 The toolchain SHOULD generate a summary of the active defences suitable for an agent's context

One terse line per [Defence], phrased as a standing instruction rather than as a failure report, each
carrying its [Identifier] and the route to its documentation. Generated from the active configuration,
per clause 5.2.

### 7.2 The toolchain SHOULD deliver that summary into the project automatically

Into the file the project's [Agents] already load, refreshed on install and update, in a delimited
region marked as generated.

**Why**: 7.1 and 7.2 are separate clauses because they are separately missed, and the two reference
implementations miss opposite halves. `php-qa-ci` writes an auto-generated, auto-refreshed block
into every [Consuming project]'s [Agent] instructions and does not put a [Rule] table in it; `ts-qa-ci`
maintains an excellent [Rule] catalogue and has no mechanism to deliver it. Each has built the half
the other lacks. A summary that exists but is never loaded and a delivery channel carrying
everything except the [Rules] are the same outcome from opposite directions.

Together these are the only clauses in any of the three specifications that operate **before** the
mistake rather than after it, which is why they are worth stating even as SHOULDs.

## 8. Self-audit

### 8.1 A shipped toolchain MUST fail its own release if a bundled defence lacks resolvable documentation

The [Toolchain] MUST run an automated check that blocks its own release. The check covers
every [Identifier] printed by a [Rule] the [Toolchain] authors or bundles
as its own, whatever kind of [Detector] carries it, and a missing page is what the check exists
to find. Where a documentation
page covers a family of [Identifiers] by a pattern, as clause 6.5 of the
[detector specification](DETECTOR-SPEC.md) allows, this audit MUST apply the pattern to every
[Identifier] printed and confirm it lands on that page. A member added to the
[Rule] and not to the page then fails the release. A third-party [Detector]'s
native catalogue, which the [Toolchain] orchestrates without claiming as its own, is outside
this audit; whether that catalogue resolves is judged under the
[detector specification](DETECTOR-SPEC.md)'s clause 6, as clause 4.2 says. The [detector specification](DETECTOR-SPEC.md)'s
clause 6.3 names the dangling reference as the failure to guard against above all others. This is the
guard, and a [Toolchain] is not held to less than it holds its
[Practitioners] to.

**Why**: clause 4.2 is the clause most easily believed to be satisfied whilst being broken, because
the documentation is written by the same person who wrote the [Rule] and its absence is invisible from
the inside. A check that blocks the release is the difference between honouring the clause and asserting it.
It is also the method applied to the [Toolchain]: the [Class] of [Defect] is "a [Rule] that blocks without
explaining", and it is detectable mechanically.

### 8.2 A shipped toolchain MUST run its own bundled defences on its own source

Every [Rule] the [Toolchain] ships to [Consuming projects] MUST also be
active when the [Toolchain] analyses itself, and a [Toolchain] release MUST fail when
they are not.

**Why**: a mechanism that delivers [Rules] to installed packages and not to the root package
leaves the [Toolchain] as the one project in which its own [Defences] never run. A
[Defect] in a [Rule]'s own code then goes unseen by every [Rule] built to see it. A
self-check that reports clean is believed, by the [Rule author] and by anyone checking their
work, because nobody expects a clean run to have run nothing. This clause was found by an execution
test in which both the [Practitioner] and the reviewer cited exactly such a run as evidence.

A project that assembles its [Toolchain] without shipping it has no release and no
[Consuming project], so this section does not bear on its [Conformance]. Its
own [Defences] already run on its own source, because that is the only source there is.

## 9. Conformance

**A project's [Toolchain] [Conforms]** if every MUST in sections 4 to 6 holds across the
assembled parts, wherever each part came from; where the project also ships a [Detector] or a
[Toolchain], every MUST in section 8 bears on the artefact grade of clause 9.1 and not on this
project grade. The project-level verdict is a single grade; which part of the
[Toolchain] satisfied each clause is evidence for that grade, not a second grade. The artefact
a project ships is graded on its own, and that grade is the second level clause 9.1 names; a
project that ships nothing has only the one.

**A [Toolchain] [Conforms] with [Agent] support** if, in addition, it does each thing section 7
of this document recommends.

Partial [Conformance] MUST NOT be described as [Conformance]. A [Toolchain] that satisfies most of this
document is in a normal and respectable condition; it is not [Conforming], and describing it as such
removes the only value the word has.

### 9.1 A project that ships a detector or a toolchain has two levels of conformance, graded separately

As a project, it follows the method with its own assembled [Toolchain], like any other
project: that [Toolchain] is graded against this document, under section 9, and the project's
[Remediations](SPEC.md#remediation) against section 7 of the method specification, as any project's are. As an artefact, what it ships is graded for its consumers: a [Detector] against
[the detector specification](DETECTOR-SPEC.md), a [Toolchain] against this document, on what the
shipped [Toolchain] itself supplies once installed into a [Consuming project], counting nothing
the [Consuming project] adds around it. The two
verdicts MUST be graded and declared separately, and neither implies the other. The two levels
are the project grade of section 9, which every project has, and the artefact grade, which only
a project that ships has. Section 8 bears on the artefact grade only; clause 5.3 is its
project-level counterpart.

**Why**: the two questions have different readers. A contributor to the artefact wants to know
whether the project practises what it ships; a [Consuming project] wants to know what it
will get. A single grade answers neither, and the observed failure is a [Toolchain] whose own
source was the one place its [Bundled defences] never ran, which a consumer-facing grade
alone would never have shown.

### 9.2 The declaration is the claim and the known-gap record, not a condition of conformance

A project or a shipped artefact MAY declare, machine-readably in whatever form its ecosystem uses to
record dependencies, the version of the method specification it follows and the version of this
document or the [detector specification](DETECTOR-SPEC.md) it [Conforms] to. A project that ships an artefact
carries both levels of clause 9.1 in that declaration, each named separately.

The same declaration is where a gap is recorded once it is known. A project or artefact that
declares a version and has learnt that it fails a MUST of the document it declares against MUST
record that gap alongside that version, in the same file or one it names. It may learn that from
its own self-audit under section 8 or from a [Practitioner]'s report under the method's clause
3.2. A declaration with a non-empty gap record is a statement of where the project stands and is
not a claim of [Conformance]. A mechanism gap is by its nature one the [Toolchain] could not
detect for itself, so the record is the only place its [Owner] and its consumers can learn of it.

The declaration is optional, and so the duty above falls only on a project or artefact that has
one; a gap a [Practitioner] finds is recorded under the method's clause 3.2 in any case, whether
or not the project declares. A [Toolchain] assembled before this document existed, or by a
project that has never read it, MAY be graded [Conforming] on evidence by anyone who exercises
the clauses above against it. A verdict on any [Toolchain], declared or not, rests on that
exercise and not on the claim.

**Why**: a [Conformance] claim in a README is a sentence; a [Conformance] claim in a manifest is a fact
about a specific installed artefact, checkable by anyone, including mechanically. It also fixes what
"[Conforming]" meant at the point the claim was made, which a claim against a moving document cannot.
Making the claim a condition, though, would grade the maintainer's reading rather than the
[Toolchain], and would leave every project that met the method before hearing of it unable
to say so.

## 10. Relationship to the method and detector specifications

This document adds no obligations to a [Practitioner] and relaxes none. Every clause here exists to
make a clause of the method specification achievable.

Where this document and the method specification disagree, the method specification governs. It
describes the method, which is the thing being specified; this describes the equipment. Where this
document and the [detector specification](DETECTOR-SPEC.md) disagree about a [Detector], the [detector specification](DETECTOR-SPEC.md)
governs, because it is the document a [Detector]'s maintainer works from; what this document
asks of a [Detector] is that it [Conform] there.

Nothing here requires a project to use a [Conforming] [Toolchain] shipped by anyone. A project can [Conform] to the method
specification on a [Toolchain] that [Conforms] to none of this, at the cost of building the missing
mechanisms itself, and once built they are its [Toolchain] and are graded here. This document exists so that it
does not have to build them alone.

<!-- Term link definitions -->

[agent]: SPEC.md#agent
[agents]: SPEC.md#agent
[baseline]: SPEC.md#baseline
[blocking]: SPEC.md#blocking
[bundled defence]: #bundled-defence
[bundled defences]: #bundled-defence
[bundled rule]: DETECTOR-SPEC.md#bundled-rule
[bundled rules]: DETECTOR-SPEC.md#bundled-rule
[calibrations]: SPEC.md#calibration
[class]: SPEC.md#class
[conform]: SPEC.md#conform
[conformance]: SPEC.md#conform
[conforming]: SPEC.md#conform
[conforms]: SPEC.md#conform
[consuming project]: #consuming-project
[consuming projects]: #consuming-project
[defect]: SPEC.md#defect
[defence]: SPEC.md#defence
[defences]: SPEC.md#defence
[detector]: SPEC.md#detector
[detectors]: SPEC.md#detector
[exception]: SPEC.md#exception
[exceptions]: SPEC.md#exception
[fixture]: SPEC.md#fixture
[hazard]: SPEC.md#hazard
[identifier]: SPEC.md#identifier
[identifiers]: SPEC.md#identifier
[instance]: SPEC.md#instance
[message]: SPEC.md#message
[owner]: SPEC.md#owner
[practitioner]: SPEC.md#practitioner
[practitioners]: SPEC.md#practitioner
[project record]: #project-record
[remediation]: SPEC.md#remediation
[remediation docs]: SPEC.md#remediation-docs
[rule]: SPEC.md#rule
[rule author]: DETECTOR-SPEC.md#rule-author
[rule harness]: DETECTOR-SPEC.md#rule-harness
[rules]: SPEC.md#rule
[runner]: SPEC.md#runner
[runners]: SPEC.md#runner
[suppression]: SPEC.md#suppression
[toolchain]: SPEC.md#toolchain
[warning]: SPEC.md#warning

===== FILE: fixtures/zigpipe.md =====
# Fixture: the Zigpipe project

A fictional project and the tooling it has assembled, described only as far as its own
documentation and configuration would show. Grade the project's toolchain against the document
you were given. Where the description does not say, answer from what is written.

## What the project's documentation says

Zigpipe is a Zig service. Its quality checks are assembled from three sources:

- **Lintomatic 4.2**, a third-party detector. It hosts bespoke rules, runs a single rule against
  a single file, prints a stable identifier with every finding, resolves bundled identifiers
  offline with `lintomatic explain`, and its inline `// lintomatic-ignore` comment can be
  disabled project-wide. Two of its forty bundled rules currently have no documentation.
- **zig-qa**, a first-party package the company publishes for all its Zig projects. It ships six
  defences of its own as Lintomatic rules with identifiers `zq.*`, a script `zig-qa run` that
  runs Lintomatic and then the test suite in that order and stops when Lintomatic fails, and a
  script `zig-qa list` that reads `lintomatic.toml` and prints every active rule with its
  identifier, a one-line summary and the path to its documentation. The six `zq.*` rules'
  documentation ships in the package under `docs/rules/`. `zig-qa run` prints Lintomatic's
  output unchanged, one line per finding, and `zig-qa run <path>` limits the run to a directory or
  a single file. Both scripts run locally with no service and are what CI runs.
- **Project rules**, four Lintomatic rules the Zigpipe team wrote, identifiers `proj.*`,
  documented in `docs/defences/` in the repository, one page per identifier, each saying what
  the rule forbids, why, and what to write instead. `zig-qa list` includes them.

Zigpipe's `lintomatic.toml` sets `ignore_comments = false`. Exceptions are kept in
`quality-exceptions.toml`, which `zig-qa run` loads before it runs Lintomatic; each entry has an
identifier, a path and a free-text `reason` field. `zig-qa run` refuses to start when an entry's
`reason` is empty. `zig-qa list --exceptions` prints the file's entries in the same format as the
rule listing.

The two undocumented Lintomatic bundled rules are enabled in `lintomatic.toml`; nothing in the
project or in zig-qa provides documentation for them, and `zig-qa list` prints their
documentation path as `(none)`.

Zigpipe does not publish a summary of its defences for an agent and has no `AGENTS.md` or
equivalent. It does not ship any tooling to other projects. It has no machine-readable
declaration of which specification version it follows.

LTSCommerce and others added 2 commits October 12, 2026 15:15
Every keyed item five of five; no passage named by more than one reader. The changelog names
runs 55 and 87, and the record links the posted sheets.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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