Skip to content

fix(claude-config): audit-instructions writes one machine-global last-audit.md, then computes a token delta against another project's report #2276

Description

@kyle-sexton

claude-config:audit-instructions persists its report to a fixed
${CLAUDE_PLUGIN_DATA}/audit-instructions/last-audit.md. That directory is keyed to the plugin
identifier and nothing else, so every run from every project on the machine overwrites the last. The
loss is the smaller half: the same Phase D block requires the report header to carry "the estimated
per-surface token delta versus the previous catalog version", a computation over the prior
last-audit.md. Under collision that prior file exists but belongs to a different project's surface
set, so the skill computes and prints a delta against an unrelated baseline instead of declining. A
silent wrong number in the report header, not just a missing file.

This is now the outlier inside its own plugin. audit-pass has keyed correctly since it shipped
(runs/<state-key>/<run-id>/), and #2250 moved audit-prompting-postures onto the same
<repo-identity>/<worktree-discriminator> scheme. audit-instructions is the remaining
claude-config writer on a fixed path.

Rows

  • RKD-01plugins/claude-config/skills/audit-instructions/SKILL.md:368 — fixed machine-global report path, no project/checkout/worktree discriminator anywhere in the Phase D block.
  • RKD-05 (this plugin's half) — plugins/claude-config/skills/audit-instructions/evals/evals.json:8 — the only assertion on the axis is "persisted to CLAUDE_PLUGIN_DATA"; nothing asserts uniqueness, non-overwrite, or per-project scoping.
  • I8 F7 — same defect, reached independently from audit-pass's side. Not a separate finding — recorded here per the batch reconciliation, because it contributes the datum the originating item lacked: audit-pass keys correctly (runs/<state-key>/<run-id>/) while its siblings do not, which makes this an inconsistency inside one plugin rather than a fleet-wide omission.

Evidence

plugins/claude-config/skills/audit-instructions/SKILL.md:368 at HEAD:

Persist the report to `${CLAUDE_PLUGIN_DATA}/audit-instructions/last-audit.md` and summarize it in

No discriminator anywhere in the Phase D block (:366-380). Two lines later, :371:

estimated per-surface token delta versus the previous catalog version — and it confirms the run

— a computation over the prior file. The evidence packet shows this path live: the producing run's own
report recorded "first run on this machine — no prior last-audit.md, so no per-surface token delta
versus a previous catalog version is computable". The second project on the same machine does not get
that decline; it gets a number.

The harness fact, verbatim. https://code.claude.com/docs/en/plugins-reference § Persistent data
directory
, fetched 2026-08-11:

"The ${CLAUDE_PLUGIN_DATA} directory resolves to ~/.claude/plugins/data/{id}/, where {id} is
the plugin identifier with characters outside a-z, A-Z, 0-9, _, and - replaced by -."

The formula is keyed to the plugin identifier only. There is no project, checkout, worktree, or session
segment, and reports and audit history are not among the documented intended uses (the table lists
"installed dependencies … generated code, and caches"). Upstream is silent here, not permissive —
nothing to wait for.

Two further docs facts that shape the fix:

"The data directory is deleted automatically when you uninstall the plugin from the last scope where
it is installed. … The CLI deletes by default; pass --keep-data to preserve it."

— so anything stored there is uninstall-fragile, which argues against an unbounded per-project report
tree and for an append-a-line history alongside a stable "read the last audit" path.

Two reference implementations, both verified at HEAD.

  1. Full identity keyingplugins/claude-config/skills/audit-pass/reference/run-state-and-resumability.md:10-20: <state-key> = <repo-identity>/<worktree-discriminator>, where repo-identity is the first configured remote normalized to host/owner/repo (or local/<sha256 of repo root> truncated to 12) and the discriminator is sha256 of the canonicalized worktree root truncated to 8. Its stated property — the working directory is never an input — is exactly the assertion this writer lacks. Reuse this scheme; do not mint a second one. fix(claude-config): audit-prompting-postures report path has no project dimension, so any other root overwrites it #2250 already did precisely that for the sibling skill, including a third nonrepo/<hash> rung for a non-repo root, and that PR is the shortest path to a matching fix here.
  2. Cheapest non-destructive adoptionplugins/machine-health/skills/audit/SKILL.md:73-75, verified verbatim: one report file per run (reports/health-<UTC-timestamp>.md — "one file per run, so a same-day rerun does not overwrite the earlier report") plus state/latest.json and an appended line in state/history.jsonl, "the trend source of truth."

One thing #2250 settled that this fix must not undo. Do not express the path as a condition over
${CLAUDE_PROJECT_DIR} "when set". That placeholder substitutes inline in skill content
(plugins-reference, fetched 2026-08-11), so the model never sees the literal token and cannot evaluate
"when set". Derive the key from commands the run actually executes — which is what the merged sibling
fix does and says out loud.

RKD-05 — nothing pins the property

plugins/claude-config/skills/audit-instructions/evals/evals.json:8 asserts only that the report is
"persisted to CLAUDE_PLUGIN_DATA". No case asserts uniqueness, non-overwrite, or per-project scoping.
For contrast, audit-pass's evals.json nearest assertion is about containment (whether the report
lands inside the scan set), which is a different axis; and #2250 added the two cases this skill still
needs — two-roots-produce-two-reports and non-repo-root-still-keys-and-self-describes — to the
postures skill. Copy that shape.

Adjacent, deliberately not duplicated

Provenance

Severity: MED · Provenance: SELF_REPORTED. The originating item declares itself "the evidence packet, not the ticket text" and directs that /plugin-quality:audit be run against these components before filing; that pass was never run, so no independent audit stands behind these rows. The file:line facts and the doc quotes above were independently re-verified against HEAD by the validation pass.
Origin: handoff-inbox items 2026-08-10-claude-config-report-keying-and-dispatch (RKD-01, RKD-05), 20260811-020411-claude-config-audit-pass-report-path-inside-scan-set (F7 — same defect, AUDITOR_VERIFIED, contributing the in-plugin-inconsistency datum)
Ledgers: .work/handoff-inbox-batch-4/ledgers/I6-report-keying-dispatch.md § RKD-01, RKD-05 · .../I8-audit-pass-report-path.md § F7
Verified against repo HEAD 9b34a82a.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions