You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(claude-config): audit-pass specifies 1,547 lines of runtime mechanism and ships no scripts, so the lease, the partial, and the resume path are prose only #2280
audit-pass specifies sha256 state keys, sixty-second heartbeats, two-sided lease liveness,
compare-and-set owner_epoch fencing, append-only partials and a run manifest — across 1,547 lines of SKILL.md plus ten reference/*.md — and ships no scripts at all. It is the only audit skill in claude-config with no scripts/ directory. Three separately-observable defects are consequences of
that one gap: the lease the contract requires of every run was not written, the /doctor handoff's --resume closure depends on a partial the run is most likely to skip, and Phase 3 declines to bound
the one cost dimension that actually blew up while naming a mitigation that is not implemented.
Two smaller placeholder-semantics defects ride along in the same skill: the {id} derivation the
report path depends on is still unstated, and the default target is expressed as a condition over a
placeholder the reader cannot evaluate — the exact shape the sibling audit-prompting-postures now
forbids in writing after #2250.
Rows
F3 — plugins/claude-config/skills/audit-pass/ — 1,547 lines of machine-checkable contract across SKILL.md and ten reference/*.md, zero scripts, in a plugin whose four sibling audit skills all ship scripts/ with tests.
F5 — SKILL.md:125 and reference/run-state-and-resumability.md:76-100 — the lease is specified in full (path, two-sided liveness window, released tombstone, owner_epoch compare-and-set) as prose with no executable, and the observed run wrote none.
F12 — reference/report-location-and-schema.md:121 and SKILL.md:285 — Phase 4 marks the /doctor lane open, closable only by --resume; --resume reads the partial, not the report; no partial is written, so the report's instruction to the operator cannot work.
F13 — SKILL.md:258-262 — Phase 3 bounds lane count, explicitly declines to bound intra-lane fan-out, and mitigates with "let incremental persistence carry the rest" — the mechanism F5 shows absent. The observed failure was intra-lane.
wc -l over the skill at HEAD: SKILL.md 395 plus ten reference/*.md = 1,547 lines. git ls-tree -d origin/main plugins/claude-config/skills/*/scripts returns audit, audit-automation-gaps, audit-instructions, audit-permission-grants — audit-pass is the only
audit skill in the plugin with no scripts/ directory. For contrast, plugins/claude-memory/skills/audit/scripts/ ships ten files, five with .test.sh siblings.
Scope this precisely. The "no scripts" fact is verifiable from the repository and was verified. The
consequence the originating item leans on — "the run wrote no lease, no partial, no manifest" — rests
on one observed run reported by the session that performed it and is not reproducible from the
repository.
Deferred shape, from the item and concurred with: scripts/resolve-run-paths.sh (plugin data dir plus {id} mangling, state key across git/no-remote, the containment verdict report_path ⊆ target_root,
derived exclusion additions) and scripts/lease.sh (acquire/heartbeat/release/classify). Note
the ordering dependency: resolve-run-paths.sh would make the containment predicate that #2230 just
landed executable rather than prose, so it should follow the spec fixes rather than replace them.
So every active run, read-only included, maintains a **lease**, and `--resume` reads it before it
reads the manifest.
reference/run-state-and-resumability.md:76-100 (§ "The lease — how --resume tells a live run from
an abandoned one") specifies the path, the contents (run id, pid, ISO-8601 start, a heartbeat_at
the run rewrites in place, an owner_epoch integer starting at 1), the two-sided liveness window, the released tombstone, and the compare-and-set fencing — all prose, no executable.
Keep the attribution split the originating audit itself makes. The missing lease is audit-pass's own defect. The concurrent writer being undetectable at its destination is a
different defect, owned by the unkeyed report paths filed separately in this batch. They must not be
retired by the same change.
F12 — the resume path depends on the artifact the run skips
reference/report-location-and-schema.md:121:
**Resume reads the partial, not the report**, so completion state is derivable from the artifact
SKILL.md:285: "open is an assembly terminator, not a completion. … --resume therefore re-runs
it, which for a delegated lane means re-prompting rather than re-scanning."
This is the one place the F3/F5 mechanism gap reaches the operator as a false instruction in the
report rather than as a missing internal, which is why it is worth its own row rather than being
folded into F3.
F13 — the disclaimed dimension is the one that blew up
SKILL.md:258-262:
**The lane count is bounded by the delegated interfaces, not chosen here** — one per scope value the
instruction catalog accepts, plus one for the memory layer — so it is a handful, and a per-run
dispatch ceiling would never bind. What is *not* bounded here is the fan-out inside a lane: the
delegated catalogs spawn their own subagents. So cap concurrency at 3–5 lanes and let incremental
persistence carry the rest — it is what degrades a blown session ceiling into a resumed run.
The reasoning in the passage is correct; the mitigation it names is the one F5 shows absent. The
observed failure was intra-lane (instruction-scan.sh exceeding a 120-second timeout over 39
surfaces). The scanner and its cost belong to audit-instructions; only the disclaimer and the
unimplemented mitigation are this skill's.
F8 — placement, environment, and derivation
grep -rn CLAUDE_PLUGIN_DATA plugins/claude-config/skills/audit-pass/ at HEAD. One of the three
original facts is now fixed by #2229/#2230: the token does appear in SKILL.md (:105, :393), and reference/report-location-and-schema.md:19-23 now states the resolution and cites the source:
- The report goes under `${CLAUDE_PLUGIN_DATA}` at `runs/<state-key>/<run-id>/findings.json`, which
survives plugin updates. **State its location precisely, because a whole target class turns on it:**
that directory resolves to `~/.claude/plugins/data/{id}/`
([plugins reference](https://code.claude.com/docs/en/plugins-reference), verified 2026-08-11), and no
documented setting relocates it.
Two facts remain unstated. (1) The {id}mangling rule — "the plugin identifier with characters
outside a-z, A-Z, 0-9, _, and - replaced by -" (plugins reference, fetched 2026-08-11) —
appears nowhere in the skill; a wrong derivation produces a report the next run cannot find, which is
also how --resume loses a partial. (2) Nothing records that ${CLAUDE_PLUGIN_DATA} is not in the
Bash tool's environment. Plugins reference, fetched 2026-08-11: "All three are exported as environment
variables to hook processes and to MCP and LSP server subprocesses." The Bash tool is none of those, so
the variable is not expandable from a run's shell.
Explicitly unconfirmed, and it should stay that way here: whether "skill content" substitution
extends to bundled reference/*.md loaded on demand via Read is not stated by the docs. #1568 owns
the empirical check; resolve it there rather than re-litigating it in this skill.
F9 — a condition over a token the reader never sees
plugins/claude-config/skills/audit-pass/SKILL.md:42-43, unchanged at HEAD:
- **`target`** — the git repository to audit. Default: `${CLAUDE_PROJECT_DIR}` when set, else
`git rev-parse --show-toplevel`. Never the working directory — a run launched from a subdirectory
Plugins reference, fetched 2026-08-11: "Which fields substitute them inline depends on the plugin
component: | Skill and agent content | Anywhere the placeholder appears |". SKILL.md is unambiguously
skill content, so for this file the substitution premise is doc-confirmed and the "when set" test is
one the reader is asked to make about a token the harness has already resolved. (Note the cross-page
tension #1568 records — the skills page's own substitution table omits ${CLAUDE_PLUGIN_DATA} and ${CLAUDE_PLUGIN_ROOT} while listing ${CLAUDE_PROJECT_DIR} — so for ${CLAUDE_PROJECT_DIR}
specifically both pages agree it substitutes in skill content.)
This row is stronger at HEAD than when it was filed.#2250 landed the opposite instruction in a
sibling skill of the same plugin — plugins/claude-config/skills/audit-prompting-postures/SKILL.md now says, in the block that derives
its report path:
Run those and use the result. Do **not** express the path as a condition over `${CLAUDE_PROJECT_DIR}`
"when set": that placeholder is substituted inline before this file reaches you, so the literal token
is never visible and the condition is not yours to evaluate. Derive the key from commands you actually
run.
Two skills in one plugin now contradict each other on the same placeholder. Cheap fix, unchanged from
the original suggestion: phrase the default in prose — "the project root Claude Code resolved for this
session; otherwise git rev-parse --show-toplevel".
Severity: MED · Provenance: mixed, stated per row. F3 (structural half), F12, F13, F8, F9 are AUDITOR_VERIFIED. F5 is SELF_REPORTED — the non-write is a runtime observation by the session that ran the component, and nothing in the repository can confirm or refute it. F3's runtime half ("the run wrote no lease, no partial, no manifest") is single-observation and is marked as such above. Every file:line and quoted line was independently re-verified against HEAD by the validation pass.
Origin: handoff-inbox item 20260811-020411-claude-config-audit-pass-report-path-inside-scan-set
Ledger: .work/handoff-inbox-batch-4/ledgers/I8-audit-pass-report-path.md § F3, F5, F12, F13, F8, F9
Verified against repo HEAD 9b34a82a. Line anchors re-derived at that commit — SKILL.md grew from 353 to 395 lines under #2234, so every ledger anchor past line 57 has moved.
audit-passspecifies sha256 state keys, sixty-second heartbeats, two-sided lease liveness,compare-and-set
owner_epochfencing, append-only partials and a run manifest — across 1,547 lines ofSKILL.mdplus tenreference/*.md— and ships no scripts at all. It is the only audit skill inclaude-configwith noscripts/directory. Three separately-observable defects are consequences ofthat one gap: the lease the contract requires of every run was not written, the
/doctorhandoff's--resumeclosure depends on a partial the run is most likely to skip, and Phase 3 declines to boundthe one cost dimension that actually blew up while naming a mitigation that is not implemented.
Two smaller placeholder-semantics defects ride along in the same skill: the
{id}derivation thereport path depends on is still unstated, and the default
targetis expressed as a condition over aplaceholder the reader cannot evaluate — the exact shape the sibling
audit-prompting-posturesnowforbids in writing after #2250.
Rows
plugins/claude-config/skills/audit-pass/— 1,547 lines of machine-checkable contract acrossSKILL.mdand tenreference/*.md, zero scripts, in a plugin whose four sibling audit skills all shipscripts/with tests.SKILL.md:125andreference/run-state-and-resumability.md:76-100— the lease is specified in full (path, two-sided liveness window,releasedtombstone,owner_epochcompare-and-set) as prose with no executable, and the observed run wrote none.reference/report-location-and-schema.md:121andSKILL.md:285— Phase 4 marks the/doctorlaneopen, closable only by--resume;--resumereads the partial, not the report; no partial is written, so the report's instruction to the operator cannot work.SKILL.md:258-262— Phase 3 bounds lane count, explicitly declines to bound intra-lane fan-out, and mitigates with "let incremental persistence carry the rest" — the mechanism F5 shows absent. The observed failure was intra-lane.reference/report-location-and-schema.md:19-23— the{id}mangling rule is stated nowhere in the skill, and nothing records that${CLAUDE_PLUGIN_DATA}is not in the Bash tool's environment, so a run cannot expand it from a shell. Fixed by ceaf013 (fix(claude-config): stop audit-pass asking the model to test a substituted placeholder #2403); see the verification note below.SKILL.md:42-43— the default target is written as "${CLAUDE_PROJECT_DIR}when set, elsegit rev-parse --show-toplevel", a condition over a token the harness has already substituted before the reader sees it. Fixed by ceaf013 (fix(claude-config): stop audit-pass asking the model to test a substituted placeholder #2403); see the verification note below.Evidence
F3 — the spec-to-implementation gap
wc -lover the skill at HEAD:SKILL.md395 plus tenreference/*.md= 1,547 lines.git ls-tree -d origin/main plugins/claude-config/skills/*/scriptsreturnsaudit,audit-automation-gaps,audit-instructions,audit-permission-grants—audit-passis the onlyaudit skill in the plugin with no
scripts/directory. For contrast,plugins/claude-memory/skills/audit/scripts/ships ten files, five with.test.shsiblings.Scope this precisely. The "no scripts" fact is verifiable from the repository and was verified. The
consequence the originating item leans on — "the run wrote no lease, no partial, no manifest" — rests
on one observed run reported by the session that performed it and is not reproducible from the
repository.
Deferred shape, from the item and concurred with:
scripts/resolve-run-paths.sh(plugin data dir plus{id}mangling, state key across git/no-remote, the containment verdictreport_path ⊆ target_root,derived exclusion additions) and
scripts/lease.sh(acquire/heartbeat/release/classify). Notethe ordering dependency:
resolve-run-paths.shwould make the containment predicate that #2230 justlanded executable rather than prose, so it should follow the spec fixes rather than replace them.
F5 — the lease is specified and was not written
plugins/claude-config/skills/audit-pass/SKILL.md:125:reference/run-state-and-resumability.md:76-100(§ "The lease — how--resumetells a live run froman abandoned one") specifies the path, the contents (
run id,pid, ISO-8601 start, aheartbeat_atthe run rewrites in place, an
owner_epochinteger starting at 1), the two-sided liveness window, thereleasedtombstone, and the compare-and-set fencing — all prose, no executable.Keep the attribution split the originating audit itself makes. The missing lease is
audit-pass's own defect. The concurrent writer being undetectable at its destination is adifferent defect, owned by the unkeyed report paths filed separately in this batch. They must not be
retired by the same change.
F12 — the resume path depends on the artifact the run skips
reference/report-location-and-schema.md:121:SKILL.md:285: "openis an assembly terminator, not a completion. …--resumetherefore re-runsit, which for a delegated lane means re-prompting rather than re-scanning."
This is the one place the F3/F5 mechanism gap reaches the operator as a false instruction in the
report rather than as a missing internal, which is why it is worth its own row rather than being
folded into F3.
F13 — the disclaimed dimension is the one that blew up
SKILL.md:258-262:The reasoning in the passage is correct; the mitigation it names is the one F5 shows absent. The
observed failure was intra-lane (
instruction-scan.shexceeding a 120-second timeout over 39surfaces). The scanner and its cost belong to
audit-instructions; only the disclaimer and theunimplemented mitigation are this skill's.
F8 — placement, environment, and derivation
grep -rn CLAUDE_PLUGIN_DATA plugins/claude-config/skills/audit-pass/at HEAD. One of the threeoriginal facts is now fixed by #2229/#2230: the token does appear in
SKILL.md(:105,:393), andreference/report-location-and-schema.md:19-23now states the resolution and cites the source:Two facts remain unstated. (1) The
{id}mangling rule — "the plugin identifier with charactersoutside
a-z,A-Z,0-9,_, and-replaced by-" (plugins reference, fetched 2026-08-11) —appears nowhere in the skill; a wrong derivation produces a report the next run cannot find, which is
also how
--resumeloses a partial. (2) Nothing records that${CLAUDE_PLUGIN_DATA}is not in theBash tool's environment. Plugins reference, fetched 2026-08-11: "All three are exported as environment
variables to hook processes and to MCP and LSP server subprocesses." The Bash tool is none of those, so
the variable is not expandable from a run's shell.
Explicitly unconfirmed, and it should stay that way here: whether "skill content" substitution
extends to bundled
reference/*.mdloaded on demand viaReadis not stated by the docs. #1568 ownsthe empirical check; resolve it there rather than re-litigating it in this skill.
F9 — a condition over a token the reader never sees
plugins/claude-config/skills/audit-pass/SKILL.md:42-43, unchanged at HEAD:Plugins reference, fetched 2026-08-11: "Which fields substitute them inline depends on the plugin
component: | Skill and agent content | Anywhere the placeholder appears |".
SKILL.mdis unambiguouslyskill content, so for this file the substitution premise is doc-confirmed and the "when set" test is
one the reader is asked to make about a token the harness has already resolved. (Note the cross-page
tension #1568 records — the skills page's own substitution table omits
${CLAUDE_PLUGIN_DATA}and${CLAUDE_PLUGIN_ROOT}while listing${CLAUDE_PROJECT_DIR}— so for${CLAUDE_PROJECT_DIR}specifically both pages agree it substitutes in skill content.)
This row is stronger at HEAD than when it was filed. #2250 landed the opposite instruction in a
sibling skill of the same plugin —
plugins/claude-config/skills/audit-prompting-postures/SKILL.mdnow says, in the block that derivesits report path:
Two skills in one plugin now contradict each other on the same placeholder. Cheap fix, unchanged from
the original suggestion: phrase the default in prose — "the project root Claude Code resolved for this
session; otherwise
git rev-parse --show-toplevel".Adjacent, deliberately not duplicated
rerun-contract.md; none of them is any row here.${CLAUDE_*}substitution-scope question empirically; fix(architecture): improve's Gotcha asserts ${CLAUDE_PLUGIN_DATA} does not substitute in skill content — plugins-reference says it does #2207 is the same false-claim family inarchitecture:improve.--fixunreachable on a non-git target) is not listed above: fix(claude-config): audit-pass admits a non-git target its downstream contract cannot specify #2231 refuses non-git targets outright, which removes the conjunction it required.Provenance
Severity: MED · Provenance: mixed, stated per row. F3 (structural half), F12, F13, F8, F9 are AUDITOR_VERIFIED. F5 is SELF_REPORTED — the non-write is a runtime observation by the session that ran the component, and nothing in the repository can confirm or refute it. F3's runtime half ("the run wrote no lease, no partial, no manifest") is single-observation and is marked as such above. Every
file:lineand quoted line was independently re-verified against HEAD by the validation pass.Origin: handoff-inbox item
20260811-020411-claude-config-audit-pass-report-path-inside-scan-setLedger:
.work/handoff-inbox-batch-4/ledgers/I8-audit-pass-report-path.md§ F3, F5, F12, F13, F8, F9Verified against repo HEAD
9b34a82a. Line anchors re-derived at that commit —SKILL.mdgrew from 353 to 395 lines under #2234, so every ledger anchor past line 57 has moved.