claude-memory:audit writes its report to a fixed
${CLAUDE_PLUGIN_DATA}/audit/last-audit.md — machine-global, with no project dimension — and then
reads it back. report mode serves whatever that file currently holds and fix mode acts on it.
So on a machine with more than one repository, a claude-memory:audit report in project B can present
project A's findings as project B's, and fix mode can propose edits derived from another
repository's memory layer. That is a wrong answer served, not merely a lost artifact — which is why an
append-only history alone does not close it: the read path needs project identity.
Four sites, not the two the originating item enumerated.
Rows
Evidence
plugins/claude-memory/skills/audit/SKILL.md:91-92 at HEAD — the read path:
Read the most recent audit report from `${CLAUDE_PLUGIN_DATA}/audit/last-audit.md`. If
missing, first check the pre-rename location `${CLAUDE_PLUGIN_DATA}/health/last-audit.md`
plugins/claude-memory/skills/audit/context/audit.md:104 — the write path:
Use the output format from criteria.md. Save to `${CLAUDE_PLUGIN_DATA}/audit/last-audit.md`
plugins/claude-memory/skills/audit/reference/criteria.md:418 — the same instruction restated:
Save the report to `${CLAUDE_PLUGIN_DATA}/audit/last-audit.md` for the `report` action to
plugins/claude-memory/skills/audit/context/fix.md:4 — fix mode reads it back.
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 -."
Keyed to the plugin identifier only — no project, checkout, worktree, or session segment. The
directory is also deleted on uninstall from the last scope where the plugin is installed unless
--keep-data is passed, so it is uninstall-fragile as well as collision-prone.
Note what shape of fix this row does and does not accept. For a write-only artifact, a
non-destructive history (one file per run plus an appended line, as plugins/machine-health/skills/audit/SKILL.md:73-75
does) is sufficient. It is not sufficient here. Because SKILL.md:91 and context/fix.md:4 read
the file back, the fix must either key the path by project identity or verify project identity at read
time. Serving the newest report is not the same as serving this project's report.
The scheme to reuse is already in-fleet. plugins/claude-config/skills/audit-pass/reference/run-state-and-resumability.md:10-20
defines <state-key> = <repo-identity>/<worktree-discriminator> with the rationale written out —
"${CLAUDE_PLUGIN_DATA} is machine-global, not per-project, so state keyed by working directory would
collide or fragment". #2250 adopted exactly that scheme for claude-config:audit-prompting-postures,
including a nonrepo/<hash> rung and a mandated self-describing report header; that PR is the working
template. Do not mint a second scheme, and 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
the condition.
RKD-05 — nothing pins the property
plugins/claude-memory/skills/audit/evals/evals.json carries no assertion on this axis at all. Across
the fleet the keying property has zero eval coverage outside the two cases #2250 added to the
postures skill; audit-pass's nearest assertions are about report containment and about
suppression-anchor collisions inside one run, both different subjects.
Cross-lane note for whoever picks this up
plugins/claude-memory/skills/audit/context/audit.md was edited at :8-40 by #2234 (widening Step 1
discovery to user-global surfaces). This row edits :104. Different hunks, same file — rebase rather
than assume.
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. The file:line facts and doc quotes above were independently re-verified against HEAD by the validation pass, which also found four sites where the item reported two.
Origin: handoff-inbox item 2026-08-10-claude-config-report-keying-and-dispatch
Ledger: .work/handoff-inbox-batch-4/ledgers/I6-report-keying-dispatch.md § RKD-03, RKD-05
Verified against repo HEAD 9b34a82a. Line anchors re-derived at that commit — SKILL.md and context/audit.md both shifted under #2234.
claude-memory:auditwrites its report to a fixed${CLAUDE_PLUGIN_DATA}/audit/last-audit.md— machine-global, with no project dimension — and thenreads it back.
reportmode serves whatever that file currently holds andfixmode acts on it.So on a machine with more than one repository, a
claude-memory:audit reportin project B can presentproject A's findings as project B's, and
fixmode can propose edits derived from anotherrepository's memory layer. That is a wrong answer served, not merely a lost artifact — which is why an
append-only history alone does not close it: the read path needs project identity.
Four sites, not the two the originating item enumerated.
Rows
plugins/claude-memory/skills/audit/SKILL.md:91-92(read),context/audit.md:104(write),reference/criteria.md:418(write),context/fix.md:4(read) — one fixed machine-global path used as both sink and source.plugins/claude-memory/skills/audit/evals/evals.json— no eval asserts uniqueness, non-overwrite, or per-project scoping for the report path.Evidence
plugins/claude-memory/skills/audit/SKILL.md:91-92at HEAD — the read path:plugins/claude-memory/skills/audit/context/audit.md:104— the write path:plugins/claude-memory/skills/audit/reference/criteria.md:418— the same instruction restated:plugins/claude-memory/skills/audit/context/fix.md:4—fixmode reads it back.The harness fact, verbatim. https://code.claude.com/docs/en/plugins-reference § Persistent data
directory, fetched 2026-08-11:
Keyed to the plugin identifier only — no project, checkout, worktree, or session segment. The
directory is also deleted on uninstall from the last scope where the plugin is installed unless
--keep-datais passed, so it is uninstall-fragile as well as collision-prone.Note what shape of fix this row does and does not accept. For a write-only artifact, a
non-destructive history (one file per run plus an appended line, as
plugins/machine-health/skills/audit/SKILL.md:73-75does) is sufficient. It is not sufficient here. Because
SKILL.md:91andcontext/fix.md:4readthe file back, the fix must either key the path by project identity or verify project identity at read
time. Serving the newest report is not the same as serving this project's report.
The scheme to reuse is already in-fleet.
plugins/claude-config/skills/audit-pass/reference/run-state-and-resumability.md:10-20defines
<state-key>=<repo-identity>/<worktree-discriminator>with the rationale written out —"
${CLAUDE_PLUGIN_DATA}is machine-global, not per-project, so state keyed by working directory wouldcollide or fragment". #2250 adopted exactly that scheme for
claude-config:audit-prompting-postures,including a
nonrepo/<hash>rung and a mandated self-describing report header; that PR is the workingtemplate. Do not mint a second scheme, and 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
the condition.
RKD-05 — nothing pins the property
plugins/claude-memory/skills/audit/evals/evals.jsoncarries no assertion on this axis at all. Acrossthe fleet the keying property has zero eval coverage outside the two cases #2250 added to the
postures skill;
audit-pass's nearest assertions are about report containment and aboutsuppression-anchor collisions inside one run, both different subjects.
Cross-lane note for whoever picks this up
plugins/claude-memory/skills/audit/context/audit.mdwas edited at:8-40by #2234 (widening Step 1discovery to user-global surfaces). This row edits
:104. Different hunks, same file — rebase ratherthan assume.
Adjacent, deliberately not duplicated
claude-configsibling, already fixed — the template here.Provenance
Severity: MED · Provenance: SELF_REPORTED. The originating item declares itself "the evidence packet, not the ticket text" and directs that
/plugin-quality:auditbe run against these components before filing; that pass was never run. Thefile:linefacts and doc quotes above were independently re-verified against HEAD by the validation pass, which also found four sites where the item reported two.Origin: handoff-inbox item
2026-08-10-claude-config-report-keying-and-dispatchLedger:
.work/handoff-inbox-batch-4/ledgers/I6-report-keying-dispatch.md§ RKD-03, RKD-05Verified against repo HEAD
9b34a82a. Line anchors re-derived at that commit —SKILL.mdandcontext/audit.mdboth shifted under #2234.