Skip to content

docs(claude-memory): re-align auto-memory reference facts with live memory doc - #1933

Merged
kyle-sexton merged 7 commits into
mainfrom
docs/row127-memory-doc-alignment
Aug 5, 2026
Merged

docs(claude-memory): re-align auto-memory reference facts with live memory doc#1933
kyle-sexton merged 7 commits into
mainfrom
docs/row127-memory-doc-alignment

Conversation

@kyle-sexton

@kyle-sexton kyle-sexton commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Row-127 doc-alignment pass: every shipped claude-memory assertion about the auto-memory / project-memory page was verified against the live doc (https://code.claude.com/docs/en/memory, fetched 2026-08-04, 35,136 bytes, sha256 7440c455…). Most claims are current; this PR corrects the ones that drifted.

  • skills/audit/reference/official-guidance.md
    • @import recursion depth: 5 hops → 4 hops (live: "maximum depth of four hops").
    • autoMemoryDirectory: replaced the stale "user or local settings only; not accepted from project settings" claim with the live behavior — read from any settings scope (user, project, local, policy, --settings), with project/local values honored only after the workspace trust dialog.
    • Quote attribution: "Project memory" section no longer exists; now cites "Set up a project CLAUDE.md".
    • Added the backing quote for the MEMORY.md limit check measuring stripped content.
  • skills/audit/reference/criteria.md (1.5.0 → 1.5.1): M1 now measures the content that loads — YAML frontmatter and block-level HTML comments are stripped before the index loads and don't count toward the 200-line/25KB limits.
  • skills/audit/scripts/memory-dir-stats.sh: --memory-lines measures post-strip loaded content instead of raw wc -l, and a new --memory-bytes mode covers the 25KB limb; covered by memory-dir-stats.test.sh.
  • skills/audit/SKILL.md: scope table now states the 25KB limb of the MEMORY.md load limit alongside the 200-line one, and the pre-computed context reports both post-strip figures so M1 never disagrees with its own injected stats.
  • Version: claude-memory 0.5.4 → 0.5.5, with CHANGELOG entry.

Serialization note: this PR was rebased onto current main after the row-60 work landed. Row 60 shipped as #1932 at claude-memory 0.5.4 / criteria 1.5.0 (commit f668526f7), which is the main this branch now sits on, so this PR takes the next free literals — 0.5.5 / criteria 1.5.1. #1947 (row 74, stateless skill) is the only other open claude-memory PR and already claims 0.5.6; it is now rebased on top of this branch and does not touch skills/audit/reference/criteria.md.

Post-rebase CI fix (8664a65647)

The rebased head failed the hygiene check. Root cause: the post-strip test fixture wrote its literal markdown code fence inside a single-quoted printf format, and ShellCheck reads backticks in single quotes as an unexpanded command substitution (SC2016). The repo's gate invokes ShellCheck with an empty severity setting — ShellCheck's default style level — so the info-level finding failed CI rather than being advisory.

Fixed by writing the fixture with double quotes and escaped backticks, which produces byte-identical output (verified by md5) and keeps the file's existing printf convention rather than introducing a second fixture-writing mechanism. No # shellcheck disable was added.

Verified locally on the final head:

  • shellcheck --rcfile=.shellcheckrc over both scripts — exit 0, no findings.
  • bash memory-dir-stats.test.shall 23 checks passed, including the post-strip line and byte assertions. Both earlier review passes noted they could not execute this suite in the CI sandbox and asked for a local run; this is that run.

Strip correctness fix (e597abcd95) — the M1 gate could not fire

An independent verifier pass found that the post-strip measurement shipped earlier in this PR had a hole that inverted the check it was meant to sharpen.

strip_unloaded() treated a line-1 --- as opening YAML frontmatter and skipped every line until a closing ---. When no closing --- exists, the whole file was discarded:

"---\ntype: index\n# Title\nreal\n"    ->  lines=0 bytes=0
"---\n# Title\nreal one\nreal two\n"   ->  lines=0 bytes=0

M1 is a [FAIL]-severity size gate and 0 always passes it, so any index with frontmatter clipped mid-file — or a leading --- used as a thematic break — silently disarmed the gate. The memory doc notes Claude Code stamps a modified frontmatter field into any memory file that already has frontmatter, so MEMORY.md is frontmatter-bearing by design; this is a live shape. An unclosed <!-- swallowed the file the same way.

Fixed by holding an opening delimiter's lines and flushing them at EOF when it never closes, so an unterminated block is counted as the content it is — matching what a reader following criteria.md counts. One mechanism covers both block kinds.

Two further defects in the same function, found while fixing the first:

  • The fence rules ran before the comment rule, so a fence inside a comment toggled fence state and leaked the commented-out body back into the count.
  • A line sharing space with a comment's open or close was dropped whole, losing real content.

Provenance correction. The fenced-code carve-out was justified in the script header as "per the documented comment behavior". Re-fetching the live page shows that sentence sits under How CLAUDE.md files load, while the MEMORY.md limit paragraph under How it works says only that frontmatter and block-level HTML comments are stripped — the doc is silent on the carve-out for MEMORY.md. The behavior is kept (a comment inside a fence is code, not block-level markdown), but criteria.md M1 now records it, together with the unterminated-block rule, the partial-line rule, and the --memory-bytes LF-normalization assumption, under a **Provenance**: note marking them as this plugin's reading rather than doc-derived.

Also: official-guidance.md's Last researched line now scopes the 2026-08-04 re-verify to the memory page, the only source this PR re-checked, instead of implying the whole source list was refreshed.

Version stays 0.5.5 / criteria 1.5.1. 0.5.5 is unmerged and its CHANGELOG entry is this PR's own, so amending it is not a version event; #1947 keeps 0.5.6 and no re-stack is needed.

Verified on e597abcd95: ShellCheck exit 0, 29/29 tests pass (a regression test per defect), markdownlint clean, all 32 CI checks green and MERGEABLE / CLEAN.

No linked issue

Related

🤖 Generated with Claude Code

@cursor

cursor Bot commented Aug 4, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@claude

claude Bot commented Aug 4, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 45s —— View job


Security Review

  • Gather context (PR diff, changed files)
  • Review changed files for security issues
  • Report findings

Scope reviewed: git diff origin/main...HEAD — 5 files, all in plugins/claude-memory/:
.claude-plugin/plugin.json (version bump), CHANGELOG.md, skills/audit/SKILL.md,
skills/audit/reference/criteria.md, skills/audit/reference/official-guidance.md.

Findings: none.

This PR is a documentation-only change. It corrects prose/reference facts in the claude-memory
plugin's audit skill (recursion-depth number, a quote attribution, the autoMemoryDirectory
scope description, an M1 measurement note) and bumps the plugin/criteria version numbers in
plugin.json and CHANGELOG.md. There is:

  • No code execution surface — no scripts, hooks, or shell commands added or modified.
  • No GitHub Actions workflow files touched, so no pull_request_target/workflow_run risk,
    no permissions: changes, no script-injection surface via the github context.
  • No settings/config files that change actual runtime behavior — official-guidance.md and
    criteria.md are reference documentation consumed by the skill's own judgment-tier checks,
    not executable policy.
  • No secrets, tokens, or credentials referenced.
  • No dependency or action pin changes (supply-chain N/A for this diff).

The one content change worth noting for completeness — the corrected claim that
autoMemoryDirectory can be set from project/local settings (gated by the workspace trust
dialog) rather than only user/local settings — is a factual correction to documentation about
Claude Code's own behavior, not a change to any enforcement logic in this repo. It doesn't
introduce a vulnerability here.

No security issues found in this PR's diff.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0fa51e69ce

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/claude-memory/skills/audit/reference/criteria.md Outdated
@claude

claude Bot commented Aug 4, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 3m 3s —— View job


Code Review

  • Gather context (PR diff, changed files)
  • Review changed files for correctness & maintainability
  • Check alignment with CLAUDE.md / REVIEW.md
  • Independently re-verify factual claims against the live doc
  • Post findings

Scope reviewed: git diff 0fa51e69ce7cebf1cc50fb84d1c5bf54b4e39162~1 0fa51e69ce7cebf1cc50fb84d1c5bf54b4e39162 (the PR's single commit) — all 5 files under plugins/claude-memory/. Security is out of scope for this lane per REVIEW.md and was already covered by the separate security-review comment on this PR.

Fact-check

Re-fetched https://code.claude.com/docs/en/memory directly (not from training-data recall, per the repo's fresh-docs mandate) and checked every corrected claim against it word-for-word:

  • @import max depth: doc says "maximum depth of four hops" — matches the 5→4 correction.
  • autoMemoryDirectory: doc confirms "read from any settings scope: user, project, local, policy, or --settings" and that project/local values are "honored only after you accept the workspace trust dialog" — matches the new prose exactly.
  • Quote attribution: the "Project memory" section no longer exists; the build/test quote now lives under "Set up a project CLAUDE.md" — confirmed.
  • M1 stripped-content quote and the "before v2.1.211, Claude Code measured the raw file" parenthetical — both confirmed verbatim on the live page. This one was worth double-checking since the PR body's verification list doesn't call it out explicitly, but it checks out.

All content changes in this PR are accurate. No correctness issues with the doc facts themselves.

Finding (Suggestion — non-blocking)

M1's new "stripped content" methodology isn't reflected in the deterministic script that backs it, so the precomputed stat and the documented check can now disagree.

  • criteria.md#L300-303 now says M1 must count lines/bytes on content "with YAML frontmatter and block-level HTML comments" stripped first.
  • But memory-dir-stats.sh#L86-90 (unchanged by this PR) still runs raw wc -l on the whole file, and there's no byte-size (25KB) stat computed anywhere.
  • That raw count is what's injected as MEMORY.md lines in SKILL.md#L16, and SKILL.md explicitly calls M1 part of the "deterministic spine" that "yields byte-identical findings" (SKILL.md#L63-64).

context/audit.md's Step 2 does list M1 generically under "doc-derived health checks" (not among the checks it says to fold from a script without hand-deriving), so an audit run that reads criteria.md literally would still strip and recount correctly. But the precomputed line sitting right at the top of the skill, labeled MEMORY.md lines and framed as deterministic/byte-identical, is an easy trap for a future run (or edit) to cite directly as the M1 answer — producing a false FAIL whenever frontmatter/comments push a file over 200 raw lines while the loaded content is actually under budget. Recommend either teaching memory-dir-stats.sh --memory-lines to strip frontmatter/comments before counting (and adding a byte-size mode), or annotating the precomputed line as raw/pre-strip so it's not mistaken for the M1 verdict. Codex's automated review flagged the same gap independently.

No other correctness, error-handling, or maintainability issues found — version bumps (0.5.3→0.5.4, criteria 1.4.0→1.4.1) are applied consistently everywhere they're referenced, and no stale version strings were left behind.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

Claude has reviewed this PR 5 times. The lane skips further automatic reviews after 5; deleting this comment resets the count.

@claude

claude Bot commented Aug 4, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 1m 27s —— View job


Security Review (re-run on latest push, HEAD 127b382)

  • Gather context (PR diff, changed files)
  • Review changed files for security issues
  • Report findings

Scope reviewed: git diff 5d097a9...HEAD (equivalent to origin/main...HEAD, shallow-clone merge base) — 7 files in plugins/claude-memory/: .claude-plugin/plugin.json, CHANGELOG.md, skills/audit/SKILL.md, skills/audit/reference/criteria.md, skills/audit/reference/official-guidance.md, skills/audit/scripts/memory-dir-stats.sh, skills/audit/scripts/memory-dir-stats.test.sh.

Findings: none.

This push adds one substantive change beyond the prior commit reviewed earlier: memory-dir-stats.sh now strips YAML frontmatter and block-level HTML comments before computing --memory-lines, and adds a new --memory-bytes mode — closing the gap Codex and the earlier code-review pass flagged (deterministic M1 stats now match the documented stripped-content methodology). Reviewed this script and its test file specifically for injection/logic-flaw risk:

  • memory-dir-stats.sh:96-112strip_unloaded() runs awk over $index, a path built from resolve-memory-dir.sh's output (unchanged by this PR) joined with the literal MEMORY.md. The path is quoted throughout ("$index"), no eval, no unquoted expansion into a command string, no shell metacharacter interpretation of file contents — the file is only ever read as awk/tr/wc input data, never executed.
  • No new command-line arguments or environment inputs are introduced; mode is still validated against a fixed allowlist (--md-count/--memory-lines/--memory-bytes/--help) before any branch runs.
  • SKILL.md's pre-computed-context line for the new --memory-bytes mode follows the same !bash "${CLAUDE_PLUGIN_ROOT}/…" --memory-bytes 2>/dev/null || echo "0"`` pattern as the existing lines — no new shell-expansion surface in the skill body itself (the harness-composition constraint this file's own header comment documents).
  • memory-dir-stats.test.sh additions are local fixture-based tests (heredoc/printf into a tmp MEMORY.md, compared with assert_eq) — no network, no secrets, no injection surface.
  • Remaining files (plugin.json version bump, CHANGELOG.md, SKILL.md scope-table wording, criteria.md/official-guidance.md prose) are non-executable documentation/reference content with no runtime effect.

No GitHub Actions workflows touched, no permissions/settings changes, no secrets or credentials referenced, no dependency/action pin changes. Consistent with the earlier security-review pass on this PR — still no security issues found.

@claude

claude Bot commented Aug 4, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 2m 26s —— View job


Code Review (re-run on latest push, HEAD 127b382)

  • Gather context (PR diff, changed files)
  • Review changed files for correctness & maintainability
  • Check alignment with CLAUDE.md / REVIEW.md
  • Independently re-verify factual claims against the live doc
  • Post findings

Scope reviewed: git diff 5d097a9...HEAD (merge-base main) — all 7 files under plugins/claude-memory/. Security is out of scope for this lane per REVIEW.md (this repo has a .github/workflows/claude-security-review.yml lane, which already reviewed this PR separately).

This push closes the previously flagged gap

Both my earlier code-review pass and Codex's review comment flagged that criteria.md's new "M1 measures stripped content" rule wasn't backed by the deterministic script — memory-dir-stats.sh --memory-lines still ran raw wc -l, and no byte-size stat existed. This commit fixes it:

  • memory-dir-stats.sh#L96-112 adds strip_unloaded(), an awk state machine stripping YAML frontmatter (first ------ block) and block-level HTML comments while preserving comments inside fenced code blocks — matching the documented behavior already sourced at official-guidance.md#L207 (pre-existing, unchanged by this PR).
  • A new --memory-bytes mode covers the 25KB limb that had no stat at all before.
  • SKILL.md#L16-17 relabels the pre-computed lines MEMORY.md loaded lines (200 cap) / MEMORY.md loaded bytes (25KB cap) — unambiguous about what's measured, so a future run can't mistake the precomputed value for a raw count.
  • criteria.md#L300-306 now explicitly tells the checker to use those pre-computed figures rather than re-measuring the raw file, removing the disagreement risk both reviews raised.

I hand-traced the new --memory-bytes/--memory-lines test case (memory-dir-stats.test.sh#L101-108) against the awk logic: frontmatter (lines 1-3) and the multi-line comment (lines 5-6) correctly drop, the fenced comment (line 9) correctly survives, leaving 5 loaded lines / 35 bytes — matches the asserted expectations exactly. Wasn't able to execute the test script directly in this sandbox (bash execution required approval that wasn't grantable here), so this is a manual trace, not a live run — worth a bash memory-dir-stats.test.sh locally to be sure, though the trace gives me high confidence it's correct.

Suggestion (non-blocking, low severity)

strip_unloaded() drops any trailing content that shares a line with a block comment's closing -->. memory-dir-stats.sh#L104: once incomment is set, a line containing --> clears the flag but still nexts unconditionally — so real content --> more real content on the same line loses more real content from the count, even though it's not part of the comment. Same-line-close-with-trailing-text is an edge case unlikely to appear in a maintainer-notes-style comment, and undercounting (never overcounting) only risks a false PASS rather than a false FAIL, so this doesn't need to block the PR — flagging for awareness in case a future MEMORY.md hits it.

Everything else

Version bumps (0.5.3→0.5.4, criteria 1.4.0→1.4.1) are consistent across plugin.json, CHANGELOG.md, and criteria.md, with no stale references left behind. The doc-fact corrections in this PR's first commit (@import depth, autoMemoryDirectory scope, quote attribution) were already independently re-verified against the live page in the earlier review pass on this PR and remain accurate — this second commit doesn't introduce any new factual claims, only script/doc consistency fixes, so no re-fetch was needed for it specifically.

No other correctness, error-handling, or maintainability issues found.

@kyle-sexton

Copy link
Copy Markdown
Contributor Author

HOLD — do not merge as-is. Version collision: this PR claims claude-memory 0.5.4 / criteria 1.5.0, but PR #1932 merged first with the same claim (origin/main f668526). Required before merge: rebase onto main, re-claim 0.5.5 / criteria 1.5.1, preserve the landed row-60 content (per-line C2, C1 diagnostic) through conflict resolution on CHANGELOG.md, criteria.md, official-guidance.md, plugin.json — then a fresh-context verifier pass on the final rebased diff. Context: doc-alignment row 127; the substantive drift fixes here (import depth 5→4, autoMemoryDirectory any-scope + trust dialog, M1 post-strip measurement) are verified-real and wanted.

kyle-sexton and others added 2 commits August 4, 2026 16:40
…emory doc

Row-127 doc-alignment pass over code.claude.com/docs/en/memory (fetched
2026-08-04). Corrects two drifted facts in audit's official-guidance.md:
@import recursion depth is 4 hops, not 5; and autoMemoryDirectory is read
from any settings scope (user, project, local, policy, --settings) with
project/local values gated behind the workspace trust dialog, replacing
the stale claim that project settings are not accepted. Aligns M1 with
the documented limit check (frontmatter and block-level HTML comments
are stripped before the MEMORY.md index loads, so they don't count
toward the 200-line/25KB limits), adds the backing quote, states the
25KB limb in the audit SKILL.md scope table, and fixes a section-name
attribution. claude-memory 0.5.3 -> 0.5.4; criteria 1.4.0 -> 1.4.1.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Codex review: criteria M1 now specifies post-strip measurement, but the
SKILL.md pre-compute injected a raw wc -l line count, so the
deterministic spine could contradict its own criteria. memory-dir-stats
now strips YAML frontmatter and block-level HTML comments (preserving
comments inside fenced code blocks) before measuring, gains a
--memory-bytes mode for the 25KB limb, and the pre-computed context
reports both figures. M1 points at the pre-computed values; tests cover
the strip semantics and the new mode.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
@kyle-sexton
kyle-sexton force-pushed the docs/row127-memory-doc-alignment branch from 127b382 to b8c04b2 Compare August 4, 2026 20:50
@claude

claude Bot commented Aug 4, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 1m 15s —— View job


Security Review (re-run on latest push, HEAD b8c04b2)

  • Gather context (PR diff, changed files)
  • Review changed files for security issues
  • Report findings

Scope reviewed: git diff origin/main...HEAD (merge-base f668526, post-rebase) — 7 files, all in plugins/claude-memory/: .claude-plugin/plugin.json, CHANGELOG.md, skills/audit/SKILL.md, skills/audit/reference/criteria.md, skills/audit/reference/official-guidance.md, skills/audit/scripts/memory-dir-stats.sh, skills/audit/scripts/memory-dir-stats.test.sh.

Findings: none.

This push rebases the branch onto current main (resolving the version collision with #1932 called out in the HOLD comment) and re-claims claude-memory 0.5.5 / criteria 1.5.1. Diffed the resulting content against the last-reviewed commit (127b382, reviewed above): the substantive change set — memory-dir-stats.sh's strip_unloaded() awk state machine, the new --memory-bytes mode, and the doc/prose corrections (@import depth, autoMemoryDirectory scope, M1 stripped-content methodology) — is unchanged, only version literals and CHANGELOG wording moved (0.5.4→0.5.5, criteria 1.5.0→1.5.1) to land after main's current tip.

Re-checked the script surface specifically for this push, since it's the only executable content in the diff:

  • memory-dir-stats.sh:96-112 (strip_unloaded()) still only reads $index (a path built from resolve-memory-dir.sh's output, quoted throughout) as awk/tr/wc input data — no eval, no unquoted expansion, no interpretation of file contents as shell.
  • Mode dispatch (--md-count/--memory-lines/--memory-bytes/--help) remains a fixed allowlist; no new CLI args or env inputs introduced by this push.
  • No GitHub Actions workflow files touched, no permissions: changes, no secrets/credentials referenced, no dependency or action pin changes.

Consistent with both prior security-review passes on this PR (commits 0fa51e6 and 127b382) — still no security issues found. This is a documentation/version-realignment push with no new runtime or trust-boundary surface.

@claude

claude Bot commented Aug 4, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 1m 26s —— View job


Code Review (re-run on latest push, HEAD b8c04b2)

  • Gather context (PR diff, changed files)
  • Review changed files for correctness & maintainability
  • Check alignment with CLAUDE.md / REVIEW.md
  • Verify rebase preserved row-60 content through conflict resolution
  • Post findings

Scope reviewed: git diff origin/main...HEAD (merge-base f668526, current main tip after #1932) — all 7 files under plugins/claude-memory/. Security is out of scope for this lane per REVIEW.md (covered separately by the claude-security-review lane, which already re-reviewed this exact commit).

Rebase verification (per kyle-sexton's HOLD comment)

The HOLD required: rebase onto main, re-claim non-colliding version literals, preserve #1932's row-60 content (per-line C2, C1 diagnostic) through conflict resolution, then a fresh-context pass on the final diff. Checked each:

  • Version collision resolved. plugin.json 0.5.4→0.5.5, CHANGELOG.md new ## [0.5.5] entry, criteria.md 1.5.0→1.5.1. git diff origin/main...HEAD confirms origin/main is already at f668526 (docs(claude-memory): run the C2 deletion test per line and codify C1's symptom-first diagnostic #1932's merge commit), so this branch is rebased onto the correct base — no lingering collision.
  • Row-60 content intact. criteria.md still has ### C1: Line Budget (line 16) and ### C2: Deletion Test [WARN per line] (line 43) from docs(claude-memory): run the C2 deletion test per line and codify C1's symptom-first diagnostic #1932, untouched by this PR's diff — confirmed via grep and diff, neither section appears in this PR's changed hunks.
  • No stale version strings. Grepped 0\.5\.[0-9]|1\.5\.[0-9] across plugin.json/CHANGELOG.md/criteria.md: current version is 0.5.5/1.5.1 everywhere it's asserted as current; older CHANGELOG entries (0.5.4, 0.5.3, …) are historical records, correctly left as-is.
  • Substantive content unchanged from the last-reviewed commit (127b382). Diffed this push's memory-dir-stats.sh/.test.sh/SKILL.md/criteria.md/official-guidance.md changes against what was already fact-checked and logic-traced in the prior review pass on this PR — byte-identical aside from version literals and CHANGELOG wording. The strip_unloaded() awk state machine, the new --memory-bytes mode, the @import depth (5→4) and autoMemoryDirectory any-scope+trust-dialog corrections all carried through the rebase correctly.
  • No dangling references to the old label. MEMORY.md lines (pre-rename) doesn't appear anywhere in the plugin; only the new MEMORY.md loaded lines (200 cap) / MEMORY.md loaded bytes (25KB cap) labels are used, consistently, in SKILL.md, criteria.md, and the script's own --help text.

Test coverage

memory-dir-stats.test.sh case 4b (post-strip stats) and the case-6/7 additions (--memory-bytes in the empty-dir and output-contract checks) match what I hand-traced and confirmed correct in the prior review pass. Wasn't able to execute the script in this sandbox either (same bash-approval constraint as the earlier pass) — worth running bash memory-dir-stats.test.sh locally before merge for a live confirmation, though the trace gives high confidence.

Outstanding non-blocking note (carried from earlier passes, not re-litigated)

strip_unloaded()'s same-line -->-close-with-trailing-text edge case (undercounts, never overcounts — false-PASS risk only) still applies; already flagged twice, low severity, not a merge blocker.

Verdict

Rebase is clean: version collision resolved, #1932's content preserved, no regressions or stale references introduced. No new correctness, error-handling, or maintainability issues found in this push.

…ckticks

The post-strip fixture's literal code fence sat inside a single-quoted
printf format, which ShellCheck reads as an unexpanded command
substitution (SC2016). The hygiene gate runs at default `style` severity,
so the info-level finding failed CI. Double quotes with escaped backticks
produce byte-identical output and keep the file's printf convention.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Aug 5, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 2m 58s —— View job


Code Review (re-run on latest push, HEAD 8664a65)

  • Gather context (PR diff, changed files since last review)
  • Review changed files for correctness & maintainability
  • Check alignment with CLAUDE.md / REVIEW.md
  • Post findings

Scope reviewed: git diff b8c04b2...8664a65 — the only change since the last code-review pass on this PR. Full-PR scope (git diff origin/main...HEAD, base f668526 = #1932) is unchanged otherwise: all 7 files under plugins/claude-memory/ were already reviewed and verified across three earlier passes on this PR. Security is out of scope for this lane per REVIEW.md (covered separately by claude-security-review).

This push

One commit, one file: memory-dir-stats.test.sh#L104 rewrites the Case 4b fixture from a single-quoted printf string containing literal backticks to a double-quoted string with \` escapes:

-printf -- '---\ntype: index\n---\n# Index\n\nreal\n```\n\n```\n' >"$M3/MEMORY.md"
+printf -- "---\ntype: index\n---\n# Index\n\nreal\n\`\`\`\n\n\`\`\`\n" >"$M3/MEMORY.md"

Verified this is behavior-neutral, not a bug fix: in POSIX/bash, backticks are literal inside single quotes (no command-substitution risk either way), and I confirmed the two forms emit byte-identical fixture content via cmp in a sandbox scratch dir. I also hand-re-traced the strip_unloaded() awk state machine against the fixture: frontmatter (lines 1-3) and the multi-line comment (lines 5-6) strip correctly, the fenced ``/``/`` block survives, leaving `# Index`, `real`, ``, ``, `` `` — 5 lines / 35 bytes, matching the asserted expectations at lines 105-106 exactly. (Executing the test script directly is blocked in this sandbox, same constraint noted in earlier passes on this PR — cmp/hand-trace substitute for a live run.)

This reads as a defensive fix for whatever flagged the raw backticks (repo lint/portability tooling most likely, given scripts/check-shell-portability.sh and shell-portability-tokens.txt exist and discuss backtick handling) rather than a runtime correctness issue — no objection to landing it as-is.

Everything else (carried from prior passes, unchanged by this push)

No new correctness, error-handling, or maintainability issues found in this push.

@claude

claude Bot commented Aug 5, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 41s —— View job


Security Review (re-run on latest push, HEAD 8664a65)

  • Gather context (PR diff, changed files since last review)
  • Review changed files for security issues
  • Report findings

Scope reviewed: git diff origin/main...HEAD — same 7 files in plugins/claude-memory/ as the prior passes. The delta since the last-reviewed commit (b8c04b2) is a single one-line change:

plugins/claude-memory/skills/audit/scripts/memory-dir-stats.test.sh | 2 +-

Findings: none.

The only change in this push swaps the test fixture's quoting style in memory-dir-stats.test.sh (case 4b) from a single-quoted printf format string to a double-quoted one with the backticks escaped (\`):

-printf -- '---\ntype: index\n---\n# Index\n\nreal\n```\n\n```\n' >"$M3/MEMORY.md"
+printf -- "---\ntype: index\n---\n# Index\n\nreal\n\`\`\`\n\n\`\`\`\n" >"$M3/MEMORY.md"

Both forms produce the identical literal byte string written to the fixture file — this is a quoting-style fix (avoiding unquoted-backtick lint warnings), not a behavior change. The backticks in the double-quoted form are escaped (\``), so there's no command-substitution risk introduced, and the written content is only ever consumed as fixture *data* (read by --memory-lines/--memory-bytesand compared viaassert_eq), never executed or eval`'d.

No new command-line arguments, environment inputs, network calls, secrets, or GitHub Actions workflow changes in this push. Consistent with all four prior security-review passes on this PR (0fa51e6, 127b382, b8c04b2, now 8664a65) — still no security issues found.

kyle-sexton added a commit that referenced this pull request Aug 5, 2026
…rge command

`claude project purge` wipes a project's transcripts and auto memory under
projects/, its per-session tasks/, debug/, and file-history/ entries, its matching
history.jsonl lines, and its ~/.claude.json entry; the stateless skill deliberately
stops at auto memory, so a user who asks to wipe what Claude saved about a repo
needs the broader route named. Pointer, not a copy of its flags: the reference
file quotes the doc's deletion list verbatim and the other call sites cite it.

Doc-alignment row 74. Version 0.5.6 sits above #1933's 0.5.5; this branch is
stacked on #1933 and merges after it.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…size gate

`strip_unloaded()` treated a line-1 `---` as frontmatter and skipped to a
closing `---` that need not exist, so a leading thematic break or frontmatter
clipped mid-file discarded the whole file and reported 0 lines / 0 bytes. M1 is
a [FAIL]-severity size check and 0 passes it, so the gate could not fire. An
unclosed `<!--` swallowed the file the same way. MEMORY.md carries frontmatter
by design — Claude Code stamps a `modified` field into any memory file that has
it — so this is a live shape, not a corner case.

An opening delimiter is now held rather than dropped and flushed at EOF when it
never closes, which counts the whole file exactly as a reader following
criteria.md would. One mechanism covers both block kinds.

Two further strip defects, same function: the fence rules ran before the
comment rule, so a fence inside a comment toggled fence state and leaked the
commented-out body back into the count; and a line sharing space with a
comment's open or close was dropped whole, losing real content.

criteria.md M1 now states the four readings the strip applies and marks them as
this plugin's reading, not doc-derived. The memory doc states the fenced-code
carve-out under "How CLAUDE.md files load" and says nothing either way for
MEMORY.md, so the previous "per the documented comment behavior" was an
inference presented as a citation. Byte counts are LF-normalized; that
assumption is now recorded rather than silent.

official-guidance.md's `Last researched` date scopes the 2026-08-04 re-verify to
the memory page, the only source this PR re-checked.

Version stays 0.5.5 / criteria 1.5.1: 0.5.5 is unmerged and its changelog entry
is this PR's own, so amending it is not a version event. #1947 keeps 0.5.6.

Tests: 29/29 pass, including regressions for each defect above. ShellCheck exit 0.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@claude

claude Bot commented Aug 5, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 3m 32s —— View job


Code Review (re-run on latest push, HEAD e597abc)

  • Gather context (diff since last-reviewed commit 8664a65)
  • Review the new commit for correctness & maintainability
  • Check alignment with CLAUDE.md / REVIEW.md
  • Post findings

Scope reviewed: git diff 8664a65..e597abc — the only change since the last code-review pass on this PR. This commit ("stop an unterminated block from disarming the M1 size gate") touches CHANGELOG.md, criteria.md, official-guidance.md, memory-dir-stats.sh, and memory-dir-stats.test.sh. Full-PR scope (git diff origin/main...HEAD) is otherwise unchanged and was already reviewed across four earlier passes on this PR. Security is out of scope for this lane per REVIEW.md (covered separately by claude-security-review, already green on this HEAD).

This push fixes a real bug — and closes a note from earlier reviews

The rewritten strip_unloaded() awk state machine in
memory-dir-stats.sh#L96-136 fixes two distinct issues, both genuine:

  1. Unterminated blocks previously reported 0. The old code's fm == 1 { ...; next } and incomment { ...; next } branches discarded lines unconditionally with no fallback if the closing delimiter never appeared — so a file starting with a clipped frontmatter block or an unclosed `` block would flip fence even though it's inside a stripped comment — letting the "commented-out" fence body leak back into the count on a later un-closed toggle. The new ordering puts the `incomment` check first, so once inside a comment, `next` always fires before the fence pattern is even evaluated.

I hand-traced the awk state machine against all 5 new fixture cases in
memory-dir-stats.test.sh#L108-127 line-by-line (unclosed frontmatter → 4, leading --- with no close → 4, unclosed comment → 4, fence-inside-comment → 1, single- and multi-line comment with same-line trailing content → 1 and 2) — all match the asserted expectations. I also re-traced the pre-existing case 4b (properly closed frontmatter + comment + fence-preserved-comment) against the new logic to confirm it still resolves to 5 lines / 35 bytes as before — it does. Wasn't able to execute bash memory-dir-stats.test.sh directly in this sandbox (same constraint noted on every earlier pass of this PR); the trace is a substitute for a live run, not a replacement — worth confirming with an actual run before merge, as flagged repeatedly already.

Worth calling out: case 4e is exactly the same-line -->-trailing-text scenario flagged as a non-blocking suggestion in three earlier review passes on this PR ("undercounts, never overcounts — false-PASS risk"). This commit fixes it (reading #2 in the new criteria.md section) and adds a regression test for it. That outstanding note is now resolved.

Documentation is consistent and provenance-correct

criteria.md#L307-320 adds a "Four readings" list plus a Provenance note explicitly marking these as the plugin's own interpretation, not doc-derived — the live memory doc states the fenced-code carve-out for CLAUDE.md only and says nothing about unterminated blocks, partial lines, or line endings for MEMORY.md. That's the right call under this repo's fresh-docs mandate: no claim here is presented as sourced from the live page when it isn't. official-guidance.md's "Last researched" line is updated to reflect the 2026-08-04 re-verification without re-claiming the other (unchecked) sources were re-verified. The CHANGELOG entry folds cleanly into the existing (unreleased) [0.5.5] section rather than bumping again, and plugin.json/criteria.md version literals (0.5.5 / 1.5.1) are correctly left unchanged — appropriate since this is a fix-up of not-yet-released content, not a new release.

Minor, non-blocking suggestion

The new edge-case tests (4c/4d/4e) only assert --memory-lines, unlike case 4b which asserts both --memory-lines and --memory-bytes. Since the same strip_unloaded() output feeds both counting modes and this commit's new pending/END-flush code path is exercised by both, extending at least one of the new cases (e.g. the unterminated-comment case) to also assert --memory-bytes would close a small coverage gap — not a blocker, since the byte-counting path is structurally identical to the already-covered line-counting path.

Everything else (carried from prior passes, unchanged by this push)

No correctness, error-handling, or maintainability issues found in this push. Both issues it fixes (silent-pass-on-unterminated-block, fence-toggle-inside-comment ordering) are real and well-tested.

@claude

claude Bot commented Aug 5, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 43s —— View job


Security Review (re-run on latest push, HEAD e597abc)

  • Gather context (PR diff since last-reviewed commit)
  • Review changed files for security issues
  • Report findings

Scope reviewed: git diff 8664a65...e597abc (the only change since the last security-review pass on this PR) — 5 files, all in plugins/claude-memory/: CHANGELOG.md, skills/audit/reference/criteria.md, skills/audit/reference/official-guidance.md, skills/audit/scripts/memory-dir-stats.sh, skills/audit/scripts/memory-dir-stats.test.sh. Full-PR scope (git diff origin/main...HEAD, base f668526 = #1932) is otherwise unchanged from the four prior passes.

Findings: none.

This push rewrites the strip_unloaded() awk state machine in memory-dir-stats.sh to fix the correctness gap flagged (non-blocking) in earlier review passes — an unterminated ---/<!-- block previously swallowed the rest of the file and reported 0 lines, which could silently disarm M1's [FAIL]-severity size gate. Reviewed the new logic specifically for security impact:

  • strip_unloaded() still only reads $index (built from resolve-memory-dir.sh's output, unchanged by this PR) as tr/awk/wc input data — no eval, no unquoted expansion, no interpretation of file contents as shell or awk source. The awk program itself remains a static single-quoted literal; nothing from the file is spliced into it.
  • The added pending buffer only accumulates and prints file content already treated as untrusted data in the prior version — no new sink is introduced (still print/printf to stdout, piped to wc).
  • memory-dir-stats.test.sh additions (cases 4c/4d/4e) are local fixture-based tests using printf into a tmp MEMORY.md, compared via assert_eq — no network, no secrets, no injection surface.
  • CHANGELOG.md, criteria.md, official-guidance.md changes are non-executable documentation explaining the new stripping semantics — no runtime effect.

No new command-line arguments, environment inputs, GitHub Actions workflow changes, permissions changes, secrets, or dependency/action pin changes in this push. Consistent with all four prior security-review passes on this PR (0fa51e6, 127b382, b8c04b2, 8664a65) — still no security issues found.

kyle-sexton added a commit that referenced this pull request Aug 5, 2026
…rge command

`claude project purge` wipes a project's transcripts and auto memory under
projects/, its per-session tasks/, debug/, and file-history/ entries, its matching
history.jsonl lines, and its ~/.claude.json entry; the stateless skill deliberately
stops at auto memory, so a user who asks to wipe what Claude saved about a repo
needs the broader route named. Pointer, not a copy of its flags: the reference
file quotes the doc's deletion list verbatim and the other call sites cite it.

Doc-alignment row 74. Version 0.5.6 sits above #1933's 0.5.5; this branch is
stacked on #1933 and merges after it.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…blank the M1 count

A MEMORY.md that opens with a --- thematic break and carries any later --- had the
entire span between them stripped as frontmatter, collapsing a 253-line index to a
single loaded line and silently disarming the FAIL-severity M1 size gate. Frontmatter
mode is now bounded twice: it ends at the first held line that is not blank, a comment,
or a key: mapping entry, and at a 20-line cap, with abandonment re-emitting the held
lines as content. Both bounds fail toward counting, so the gate can fire early but can
no longer be blanked. New test cases cover both the line and byte limbs and confirm
well-formed frontmatter still strips.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@claude

claude Bot commented Aug 5, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 1m 18s —— View job


Security Review (re-run on latest push, HEAD 61474d0)

  • Gather context (gh/git diff, changed files since last-reviewed commit e597abc)
  • Review changed files for security issues
  • Report findings

Scope reviewed: git diff e597abc..HEAD — the only change since the last security-review pass on this PR. 3 files: plugins/claude-memory/skills/audit/reference/criteria.md, plugins/claude-memory/skills/audit/scripts/memory-dir-stats.sh, plugins/claude-memory/skills/audit/scripts/memory-dir-stats.test.sh. Full-PR scope (git diff f668526..HEAD, base = #1932) is otherwise unchanged from the five prior passes and still totals the same 7 files under plugins/claude-memory/.

Findings: none.

This push adds a second bound to strip_unloaded()'s frontmatter-detection branch in memory-dir-stats.sh:126-149: a leading --- now only stays in "frontmatter mode" while subsequent lines are blank, a comment, or a key: mapping line, and only for up to fmcap = 20 lines — closing a real gap where a thematic-break --- followed by any later --- would strip the entire span between them down to a false near-zero count (correctness fix, already covered by new regression tests in memory-dir-stats.test.sh). Reviewed this change specifically for security impact:

  • The new grammar/length bound is pure pattern-matching (awk regex tests: ^[[:space:]]*$, ^[[:space:]]*#, ^[[:space:]]*[A-Za-z_][A-Za-z0-9_-]*:) against lines already treated as untrusted data, not code — no eval, no unquoted shell expansion, no interpretation of MEMORY.md content as a command. Same trust model as every prior pass on this script.
  • fmcap is a fixed literal (20), not attacker- or config-influenced; there's no way for file content to change how many lines the cap allows.
  • The re-emit-as-content fallback (printf "%s", pending) prints previously-held file content back to stdout — the same data-in/data-out flow as the rest of the function, feeding into wc -l/wc -c, not a shell.
  • memory-dir-stats.test.sh additions (cases 4c2/4c3) are local fixture-based tests — printf into a tmp MEMORY.md, compared via assert_eq/raw_lines/raw_bytes helpers — no network, no secrets, no injection surface.
  • criteria.md changes are non-executable documentation describing the new two-bound reading — no runtime effect.

No new command-line arguments, environment inputs, GitHub Actions workflow changes, permissions changes, secrets, or dependency/action pin changes in this push. Consistent with all five prior security-review passes on this PR (0fa51e6, 127b382, b8c04b2, 8664a65, e597abc) — still no security issues found. This remains a documentation/reference-audit-skill PR with no code-execution, authorization, or trust-boundary surface.

…content lines

A line carrying two HTML comments with text between them matched through to the LAST
close, consuming the whole line and losing the text between: a 1-line, 32-byte index
reported 0 lines and 0 bytes, an under-count on the FAIL-severity M1 gate. Both close
matches now stop at the first close, spelled as a bounded-complement body that cannot
itself contain a close delimiter, since awk ERE has no lazy quantifier. Only the first
comment on a line is stripped, so a second one counts as content: an over-count, the
direction every other bound here already fails toward. New cases cover both limbs, the
close-path shape, and the empty, lone-dash, and multi-dash-closer idiom edges.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@claude

claude Bot commented Aug 5, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 45s —— View job


Security Review (re-run on latest push, HEAD 95e284a)

  • Gather context (diff since last-reviewed commit 61474d0)
  • Review changed files for security issues
  • Report findings

Scope reviewed: git diff 61474d0..95e284a — the only change since the last security-review pass on this PR. 3 files: plugins/claude-memory/skills/audit/reference/criteria.md, plugins/claude-memory/skills/audit/scripts/memory-dir-stats.sh, plugins/claude-memory/skills/audit/scripts/memory-dir-stats.test.sh. Full-PR scope (git diff f668526..HEAD, base = #1932's merge commit) is otherwise unchanged and still totals the same 7 files under plugins/claude-memory/.

Findings: none.

This push tightens strip_unloaded()'s HTML-comment-close regex in memory-dir-stats.sh:151,159 — replacing a greedy .*--> with a bounded-complement pattern (([^-]|-[^-]|--+[^->])*--+>) so the match stops at the first --> on a line instead of the last, fixing a case where two comments on one line caused the text between them to be wrongly stripped (correctness fix, covered by five new regression cases in memory-dir-stats.test.sh). Reviewed specifically for security impact:

  • The change is a pure regex refinement over data already treated as untrusted content, not code — awk's ERE matching (POSIX ERE, not a backtracking PCRE engine) has no eval, no shell re-interpretation, and no code path where file content is spliced into the awk program itself (the program remains a static single-quoted literal). No ReDoS concern: POSIX ERE alternation over single-character classes is matched via NFA/DFA simulation in awk, not backtracking, so this bounded-complement pattern is linear in input length regardless of comment-marker density.
  • No new command-line arguments, environment inputs, file paths, or externally-controlled parameters are introduced. tr/awk/wc pipeline shape and quoting ("$index") are unchanged from prior passes.
  • memory-dir-stats.test.sh additions (cases 4f + idiom guards) are local fixture-based tests (printf into a tmp MEMORY.md, compared via assert_eq) — no network, no secrets, no injection surface.
  • criteria.md change is non-executable documentation describing the new "first close wins" reading — no runtime effect.

No new command-line arguments, GitHub Actions workflow changes, permissions changes, secrets, or dependency/action pin changes in this push. Consistent with all six prior security-review passes on this PR (0fa51e6, 127b382, b8c04b2, 8664a65, e597abc, 61474d0) — still no security issues found. This remains a documentation/reference-audit-skill PR with no code-execution, authorization, or trust-boundary surface.

kyle-sexton added a commit to melodic-software/ci-workflows that referenced this pull request Aug 5, 2026
## Summary

- replace regex-only HTML-comment stripping in the reusable PR-linkage
gate with a Markdown-aware state machine
- preserve comment-looking text inside inline code spans and fenced code
blocks
- retain fail-closed behavior for actual unterminated HTML comments
- add regressions for inline, multiline-inline, and fenced-code cases

## Root cause

A valid PR body described an HTML-comment parser bug using the rendered
literal `&lt;!--`. The gate's unbounded fallback regex treated that
code-span text as a real unterminated comment and deleted the rest of
the body before validation, including a valid `No linked issue` marker
and populated `## Related` section.

## Validation

- `node --test .github/scripts/pr-issue-linkage.test.cjs` — 20 passed
- full `.github/scripts/*.test.cjs` corpus — 498 passed; 10 unrelated
tests could not invoke `/bin/bash` because WSL/Bash is unavailable on
this Windows host
- `git diff --check` — passed

No linked issue

## Related

- Reproduced by melodic-software/claude-code-plugins#1933
One line can carry several HTML comments. Ending the strip after the first left every
later comment counted as content, so measuring the text between two comments needs both
a first-close bound and a re-scan of what follows. The scan now walks each line with
index and substr and removes whole comment spans only, so real text is never dropped
while a line that is entirely comment still disappears. Text loading before an
unterminated opener is emitted at once rather than held, because the held block is
discarded when the comment closes and folding that text in would lose it outright;
only whitespace ahead of the opener joins the hold, which keeps an indented opener
counted without re-counting a comment already stripped from the line.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@claude

claude Bot commented Aug 5, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 1m 22s —— View job


Security Review (re-run on latest push, HEAD ecbbd1f)

  • Gather context (diff since last-reviewed commit 95e284a)
  • Review changed files for security issues
  • Report findings

Scope reviewed: git diff 95e284a..ecbbd1f — the only change since the last security-review pass on this PR. 3 files: plugins/claude-memory/skills/audit/reference/criteria.md, plugins/claude-memory/skills/audit/scripts/memory-dir-stats.sh, plugins/claude-memory/skills/audit/scripts/memory-dir-stats.test.sh. Full-PR scope (git diff origin/main...HEAD, base = #1932's merge commit) is otherwise unchanged and still totals the same 7 files under plugins/claude-memory/.

Findings: none.

This push replaces strip_unloaded()'s single-comment-per-line regex substitution in memory-dir-stats.sh with an index/substr-based scan (uncomment()) that removes every complete `` span on a line, re-scanning after each close instead of stopping at the first — fixing a case where a second comment on the same line was miscounted as content (correctness fix, covered by new regression cases in memory-dir-stats.test.sh). Reviewed specifically for security impact:

  • The rewrite is still pure string-manipulation over data already treated as untrusted content, not code: index() and substr() are awk string builtins operating on values already read from $0, with no system(), no getline "cmd" form, no ENVIRON/ARGV reads, and no path where file content is spliced back into the awk program text (confirmed via grep -n "system(\|getline\|ENVIRON\|ARGV" memory-dir-stats.sh — no hits). The awk program itself remains a single static single-quoted literal.
  • The new uncomment()/emit() helper functions only accumulate and print substrings of already-untrusted line content into pending/stdout, which continues to feed wc -l/wc -c — no new sink type introduced.
  • No new command-line arguments, environment inputs, file paths, or externally-controlled parameters. tr/awk/wc pipeline shape and quoting ("$index") are unchanged from prior passes.
  • The while ((p = index(s, "<!--")) > 0) loop in uncomment() always advances s (via substr(s, p + q + 6), strictly shorter than the input) or returns, so it terminates — no unbounded-loop/DoS concern from crafted input.
  • memory-dir-stats.test.sh additions are local fixture-based tests (printf into a tmp MEMORY.md, compared via assert_eq) — no network, no secrets, no injection surface.
  • criteria.md change is non-executable documentation describing the updated "re-scan for multiple comments" reading — no runtime effect.

No new command-line arguments, GitHub Actions workflow changes, permissions changes, secrets, or dependency/action pin changes in this push. Consistent with all seven prior security-review passes on this PR (0fa51e6, 127b382, b8c04b2, 8664a65, e597abc, 61474d0, 95e284a) — still no security issues found. This remains a documentation/reference-audit-skill PR with no code-execution, authorization, or trust-boundary surface.

@kyle-sexton
kyle-sexton merged commit 9841272 into main Aug 5, 2026
33 of 34 checks passed
@kyle-sexton
kyle-sexton deleted the docs/row127-memory-doc-alignment branch August 5, 2026 20:17
kyle-sexton added a commit that referenced this pull request Aug 5, 2026
…rge command

`claude project purge` wipes a project's transcripts and auto memory under
projects/, its per-session tasks/, debug/, and file-history/ entries, its matching
history.jsonl lines, and its ~/.claude.json entry; the stateless skill deliberately
stops at auto memory, so a user who asks to wipe what Claude saved about a repo
needs the broader route named. Pointer, not a copy of its flags: the reference
file quotes the doc's deletion list verbatim and the other call sites cite it.

Doc-alignment row 74. Version 0.5.6 sits above #1933's 0.5.5; this branch is
stacked on #1933 and merges after it.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Aug 5, 2026
…rge command (#1947)

## Summary

Roster row 74. The `stateless` skill governs auto memory only, and said
so without naming the official route for the broader ask ("wipe
everything Claude saved about this repo"). Claude Code now ships that
route: `claude project purge` (v2.1.124+). This PR names it wherever the
skill states its own scope boundary — the SKILL.md scope statement and
table, `context/purge.md`'s pre-gate presentation and follow-through,
and `reference/official-guidance.md`'s out-of-scope section — and
retires the reference file's now-false "there is no built-in purge
command" claim.

Pointer, not a copy: the deletion plan and flags stay in
https://code.claude.com/docs/en/claude-directory.

No executable step changes. The bash fences driving Steps 2–4 (manifest
capture, backup, delete) and the confirmation gate are byte-identical to
the base branch; the additions are narrative bullets outside any
executable block, and nothing causes the skill to invoke `claude project
purge` itself.

## Review finding fixed — full deletion scope

Codex flagged (P2, `official-guidance.md:127`) that the summarized
deletion scope omitted a category. Re-fetching the live page on
2026-08-04 confirmed it: the command deletes **four** categories, and
the PR's original prose listed three, dropping per-session `tasks/`,
`debug/`, and `file-history/` entries — checkpoint/restore and debug
history. That matters because this text is read to a user deciding
whether to run a destructive wipe; the omission would have led them to
believe checkpoint history survives.

Sweeping the diff found the same omission in **five** places, not the
one flagged. All are corrected:

| Location | Treatment |
|---|---|
| `reference/official-guidance.md` out-of-scope section | No longer
paraphrases; the verbatim quote block now carries the doc's complete
bullet list |
| `SKILL.md` scope statement | Lists all four categories |
| `context/purge.md` Step 2 (pre-gate text) | Lists all four categories
|
| `context/purge.md` Step 5 | Was a second hand-maintained copy; now
points at Step 2's enumeration |
| `CHANGELOG.md` 0.5.6 entry | Lists all four categories |

Two authoritative enumerations now remain (the reference file's verbatim
quote and Step 2's pre-gate text), down from five
independently-maintained paraphrases.

## Stacking and version

Rebased onto `main` after #1933 merged, so the diff contains only this
PR's five files. `0.5.6` sits directly above #1933's `0.5.5` in both
`plugin.json` and the CHANGELOG, with no gap.

Fresh-context verification completed 2026-08-05 after the rebase: the
five-file diff was reviewed against the live official `claude-directory`
page; `claude project purge` version, deletion scope, exclusions,
confirmation behavior, session cleanup, and history persistence all
match. `markdownlint` (14 files), JSON parsing, changelog/version
parity, and `git diff --check` pass locally; the repository-wide skill
gate exceeded the local 60-second observation window, so protected CI
remains authoritative for that lane.

No linked issue

## Related

- Source of truth: https://code.claude.com/docs/en/claude-directory
(`claude project purge`, v2.1.124+)
- Campaign save-point and remaining-work ledger: #1941
- Stacked on: #1933 (roster row 127, claude-memory 0.5.5 / criteria
1.5.1)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Aug 5, 2026
…lock would swallow (#1962)

Follow-up to #1933 (work-items row 127, campaign ledger #1941). #1933
shipped the M1 index-size measurement fixes for `memory-dir-stats.sh`;
this closes the last under-count residual that surfaced during its gate
review, after the PR had already merged.

No linked issue — the residual was found by #1933's own gate review
rather than filed as an issue, and the campaign ledger it belongs to
stays open past this PR.

## The bug

`memory-dir-stats.sh` admitted `#` lines to its frontmatter grammar. A
`MEMORY.md` that opens with a `---` thematic break, carries heading
lines, and reaches any later `---` therefore had the whole span stripped
as frontmatter:

```
---
# heading one
# heading two
---
body
```

Raw 5 lines / 41 bytes, reported **1 line / 5 bytes**.

M1 is a `[FAIL]`-severity size gate, and a low count always passes it,
so the shape disarmed the gate outright rather than merely mismeasuring
it. This is the same failure species #1933 exists to eliminate — silent
under-count on the gate — reached through the frontmatter grammar
instead of the comment strip.

A `#` line is a comment to YAML but a **heading** to markdown, and
headings are loaded content. The grammar now accepts only blank lines
and `key:` mapping entries.

## Evidence

Measured against `origin/main`'s script and this branch's, same
fixtures:

| fixture | 0.5.6 | 0.5.7 |
|---|---|---|
| 5-line heading pseudo-block | 1 line / 5 bytes | 5 / 41 (raw) |
| 20 headings + later `---` (23 lines) | 1 line / 5 bytes | 23 / 123
(raw) |
| genuine `key:`-only frontmatter | 1 / 5 | 1 / 5 (still strips) |
| genuine frontmatter with a `# note` | 1 / 5 | 6 / 44 (raw) |

The bound is capped at `fmcap` (20) lines, so the worst case was ~22
content lines — 11% of the 200-line budget — never a full disarm of the
line limb, but enough to make a five-line index report one.

## The cost, stated plainly

A real YAML comment inside frontmatter now ends the block, and ending it
strips **nothing at all**: the opening `---`, every entry held so far,
and the rest of the block through its close all count. That is an
over-count, the direction M1's readings already guess toward — it can
make the gate fire early, never fail to fire. It takes a hand-edited
index to reach, since Claude Code only stamps a `modified` scalar into
frontmatter a file already has. Comments join an existing class rather
than opening a new one: frontmatter this grammar cannot parse already
ended the block before this change, and a block sequence under `tags:`
still does.

`criteria.md` M1 reading 1 records both halves.

## Verification

- Full suite **60/60, exit 0** — run in this worktree off current
`main`.
- Fresh-context verifier, rationale withheld, **PASS on all six
criteria** (suite; heading fixture reports raw; `key:`-only frontmatter
still strips; comment/fence behavior unregressed; no `#` alternation
left in the executed awk; version + changelog hygiene). It derived every
expectation from the awk before looking at output, and added its own
mutation check — running `origin/main`'s pre-fix script side by side to
confirm the fix is load-bearing and the numbers above reproduce.

## Versions

`claude-memory` 0.5.6 → **0.5.7** (0.5.5 → 0.5.6 landed via #1947);
`criteria.md` 1.5.1 → **1.5.2**; CHANGELOG entry under `[0.5.7]`.

## Related

- #1933 — predecessor, merged. Shipped the M1 measurement fixes
(frontmatter bounding, greedy-comment fix, comment re-scan) this builds
on; the residual fixed here was found during its gate review. Not closed
by this PR.
- #1941 — campaign ledger tracking work-items row 127 and its siblings.
Stays open past this PR.
- #1947 — carried `claude-memory` 0.5.5 → 0.5.6, the version this PR
bumps from. Reference only.

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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