audit: a citation must resolve on the ref the audit named, and both passes get checkpointed (0.2.0) - #34
Conversation
…asses get checkpointed (0.2.0) The two severity-1 defects from run 1 (#21). They are the same defect at two altitudes: the audit's own record claiming more than it can support. Defect 1 — reachability. doctrine §2 required `file:line`, a merged PR or a tag, and never that the cited thing be reachable from the ref the audit says it verified against. Run 1's headline finding cited a commit that is real, does touch the file, and exists only on an unmerged branch, while the report's header named `main` @ 2c3d624. The conclusion survived independent checking; the citation did not. §2 now states the requirement for every citation form, and phase 2 runs `git merge-base --is-ancestor <sha> <ref>` before tagging a commit. Off-ref evidence stays citable as the open PR it is, tagged [stated]/[inferred]. Defect 2 — the closed side was never checkpointed. `findings.md` held the 56 open issues; the 62 closed ones went straight to the catalog, leaving half of phase 2 outside the checkpoint and breaking the single-block resume rule shipped in 0.1.2, which would have re-verified all 62 from scratch while reporting itself complete. `findings.md` now carries `## Open` and `## Closed`, and the resume rule partitions `issues.json` by state and resumes each side independently. Minor rather than patch: both change what an operator does during a run. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR updates the audit plugin’s doctrine and /audit:issues runbook to (1) require that [verified] citations resolve on the baseline ref the audit names, and (2) ensure phase-2 checkpointing covers both the open and closed passes, with a corresponding minor version bump to 0.2.0.
Changes:
- Tighten evidence rules:
[verified]citations must be reachable from the audit’s named baseline ref (including commit-SHA reachability checks). - Update
/audit:issuescheckpoint/resume guidance sofindings.mdcheckpoints both open and closed passes separately. - Release the behavior/procedure change as
audit0.2.0and sync the marketplace entry.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
audit/skills/issues/SKILL.md |
Updates the runbook to checkpoint both passes and to require baseline-ref citation checks before tagging [verified]. |
audit/references/doctrine.md |
Extends evidence-class doctrine to make baseline-ref reachability a requirement for [verified] citations. |
audit/CHANGELOG.md |
Documents the 0.2.0 release and the two severity-1 procedural fixes. |
audit/.claude-plugin/plugin.json |
Bumps audit plugin version to 0.2.0. |
.claude-plugin/marketplace.json |
Updates the marketplace’s audit entry to version 0.2.0. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| An unqualified claim is a defect. `[inferred]` is legitimate and often the most valuable class — but it must never be dressed as `[verified]`, and a status change recommended on `[inferred]` alone should say so in the recommendation itself. |
There was a problem hiding this comment.
Good catch, and fixed in 27a5db6 — though at the other end than suggested. You are right that the two statements disagreed: §2's table had grown a fourth form and the reachability rule, while §1 rule 1 still read "Cite file:line, a PR, or a tag for each verified claim". A reader meets rule 1 first and gets the stale list.
The fix is to stop §1 enumerating rather than to add a clarification at §2. §2 already states it correctly, so a third statement of the accepted forms would be one more copy to drift — and duplicated lists drifting is exactly what produced this defect. Rule 1 now carries the requirement and points at §2 for the forms, which leaves one place where they are written down. That also matches the repo's single-source-of-truth rule (AGENTS.md), which this plugin's own doctrine is supposed to model.
…hability check read as an instruction Copilot's two comments on #34, both on text this PR introduced. doctrine §1 rule 1 still enumerated "file:line, a PR, or a tag" while §2's table had grown a fourth form and the reachability rule — the drift Copilot spotted. Fixed at the cause rather than by adding a third copy: rule 1 now points at §2, which is the only place the forms are stated. SKILL.md's check read "For a commit that is `git merge-base ...`; ... for a PR it is merged into it" — a missing comma and two unanchored pronouns, in what is meant to be an operator instruction. Now one bullet per citation type, each naming the action. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…f the citation list Copilot's three comments on #35, all on text this PR introduced. Step 4 said the closed pass "has never been checkpointed at all" two sentences before crediting #34 with checkpointing it. True of run 1, false of main. The point is that it has never been *exercised*, which is what it now says. The doctrine §2 link was hard-coded to blob/main while line 7 of the same file links doctrine relatively, and developing-skills says to keep relative links relative because CI checks they resolve. The AGENTS.md absolute-URL rule governs links out of a plugin directory, since an installed plugin ships alone and cannot resolve `../`; docs/ never ships alone, so relative is right here. Review check 3 enumerated citation forms and omitted tags. Rather than sync what had become the fourth copy of that list, the row no longer enumerates at all — the same fix applied to doctrine §1 on #34, and what line 7 means by "points, never restates". The list at line 79 is kept deliberately: it is the teaching sentence and it links to §2 in the same breath. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ually does (#35) * Docs: bring the audit tutorial and CATALOG up to what audit 0.2.0 actually does The tutorial is the procedure for run 2, and run 2 is the run that tests resume — so it was the one document that could not be left describing the pre-#34 behaviour. Step 4 taught the single-block resume rule that #34 replaced: read findings.md, resume at the lowest number with no entry. It now describes partitioning issues.json by state and resuming each side independently, and names the new failure mode — resuming the open set correctly while re-doing the closed set from scratch. The same step quoted the three-form citation list that doctrine §2 has outgrown, without the reachability rule that is the whole point of defect 1. Two review checks are strengthened where run 1 showed them to be weak. Check 3 passed a citation that pointed at an unmerged branch, so it now says to resolve each sampled citation on the ref the header names. Check 5 held in the report and broke in the checkpoint, so it now looks at findings.md as well as the output. CATALOG records the two severity-1 fixes. Its central caveat is unchanged and still true: resumability is untested, because run 1 was never interrupted. Repo-level files only — no plugin directory touched, so no version bump. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Docs: fix a contradiction, an absolute self-link, and a fourth copy of the citation list Copilot's three comments on #35, all on text this PR introduced. Step 4 said the closed pass "has never been checkpointed at all" two sentences before crediting #34 with checkpointing it. True of run 1, false of main. The point is that it has never been *exercised*, which is what it now says. The doctrine §2 link was hard-coded to blob/main while line 7 of the same file links doctrine relatively, and developing-skills says to keep relative links relative because CI checks they resolve. The AGENTS.md absolute-URL rule governs links out of a plugin directory, since an installed plugin ships alone and cannot resolve `../`; docs/ never ships alone, so relative is right here. Review check 3 enumerated citation forms and omitted tags. Rather than sync what had become the fourth copy of that list, the row no longer enumerates at all — the same fix applied to doctrine §1 on #34, and what line 7 means by "points, never restates". The list at line 79 is kept deliberately: it is the teaching sentence and it links to §2 in the same breath. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
The two severity-1 defects from run 1, filed as items 1 and 2 on #21 and sequenced there as one doctrine-level PR because they are the same defect at two altitudes: the audit's own record claiming more than it can support. Five of the seven defects on #21 remain open after this.
Defect 1 — a
[verified]citation that the reader cannot resolvedoctrine §2 required
file:line, a merged PR or a tag, and never that the cited thing be reachable from the ref the audit says it verified against. Run 1's headline finding cited commitb99b431as where a file's history ends — a commit that is real and does touch the file, but lives only on an unmerged branch, while the report's own header said "verified againstmain@2c3d624". The conclusion survived independent checking; the citation did not. A citation that resolves for its author and not for its reader is worse than an untagged claim, because the tag is what invited the trust.§2 now states the requirement for every citation form, not just commits. This is broader than #21 asked for, deliberately:
file:lineand PR citations are ref-relative too and fail the same way — a line number that is right in a dirty working tree and wrong on the ref, an open PR cited as though merged. So a commit must be an ancestor of the baseline ref, afile:linemust be that line on the ref rather than in the working tree, and a PR must be merged into it./audit:issuesphase 2 runs the mechanical case before tagging:Evidence that genuinely lives off-ref stays citable — as the open PR it is, tagged
[stated]or[inferred]. The rule removes a false-precision trap, not a class of evidence.Defect 2 — half of phase 2 sat outside the checkpoint
findings.mdheld the 56 open issues. The 62 closed ones were verified and written straight into the catalog, so the resume rule shipped in 0.1.2 — "resume at the lowest number inissues.jsonwith no entry" — would have re-verified all 62 from scratch while reporting itself complete. The checkpoint materialised, which is what #17 set out to prove; it just covered one of the two passes.findings.mdnow carries## Openand## Closedsections, and the resume rule partitionsissues.jsonby state and resumes each side independently at the lowest number with no entry under the matching heading. The skill also says explicitly not to infer progress from a single block or from the file's length.This is what makes run 2 worth running for its stated purpose. Run 2 exists to test resume, and testing a resume path against a checkpoint already known to cover half the phase would have wasted the most informative run in #16's matrix — the block-3-before-block-4 argument on #25.
Release
audit0.1.4 → 0.2.0, minor rather than patch. Both fixes change what an operator does during a run — one adds a check that can change how a finding is tagged, the other changes which files a run writes — which is the linedeveloping-skillsdraws between the two.scripts/validate.pypasses all three plugins andscripts/check-version-bump.pyreportsok audit — 0.1.4 → 0.2.0.🤖 Generated with Claude Code