Skip to content

Bind /prep-compact to the invoking session (+ handoff noise filter, single-line /compact)#5

Merged
koenvdheide merged 8 commits into
mainfrom
session-bound-handoff
Jun 5, 2026
Merged

Bind /prep-compact to the invoking session (+ handoff noise filter, single-line /compact)#5
koenvdheide merged 8 commits into
mainfrom
session-bound-handoff

Conversation

@koenvdheide

@koenvdheide koenvdheide commented Jun 5, 2026

Copy link
Copy Markdown
Owner

What and why

When several Claude Code sessions run in the same project, /prep-compact could read the wrong session's handoff. The old §1 discovery globbed handoff-*.json, filtered by cwd, and picked the newest mtime, so in a shared working directory it would select a sibling session's record and contaminate the extractive fields (files, recent_user_requests, in_progress, agents). This binds the lookup to the invoking session instead, trims non-user noise out of the handoff, and makes the drafted /compact reliably one line.

Changes

  • Session-bound resolver. New skills/prep-compact/resolve-handoff.sh resolves the invoking session's own handoff by $CLAUDE_CODE_SESSION_ID (sanitised the same way as the hooks), validates the stored cwd, and prints HIT\n<path> / MISS / NOSID. Fail-open (always exit 0), deterministic root priority, malformed-candidate skip, and C:\.. vs /c/.. canonicalisation for Git Bash.
  • Rewire §1 discovery to call the resolver and branch on its output, replacing the newest-mtime scan. If the session id is unavailable it degrades to an in-memory survey, never another session's data.
  • Trim non-user noise from the handoff. The Stop hook drops .git/ internals and .claude/plugins/{data,cache}/ paths (VCS/plugin plumbing) from recent_files/cumulative_files, and drops injected messages (<task-notification>, [SYSTEM NOTIFICATION, skill-load preambles) from recent_user_requests. Real source files, temp dirs, and ~/.claude config reads are kept: the handoff is an inclusion list, so it should over-include rather than risk dropping real work.
  • Enforce single-line /compact. Removed the multi-line escape hatch from §4 and added a pre-emit verify gate in §5, so a stray newline after /compact can't drop the instructions.
  • Docs. README "How It Works" + "Known limits"; CHANGELOG.

Testing

bash test/run-tests.sh: 127 assertions, green on Windows Git Bash. New coverage: handoff noise filter (T-52..T-55), resolver unit tests (T-42..T-50, including the sibling-not-selected and cwd-mismatch regressions), §1 binding (T-41), single-line gate (T-51).

Possible follow-up (not in this PR)

  • The resolver binds by filename + cwd and does not cross-check the handoff's internal session_id. For real UUID sessions the filename equals the stored id, so this is belt-and-suspenders only; worth adding if we ever want to defend against a hand-misnamed file.

🤖 Generated with Claude Code

koenvdheide and others added 6 commits June 5, 2026 19:40
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@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: f0721c0baf

ℹ️ 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".

_nrm() { if command -v cygpath >/dev/null 2>&1; then cygpath -m "$1" 2>/dev/null || printf '%s' "$1"; else printf '%s' "$1"; fi; }
PLUGIN_DATA_N=""; [ -n "${CLAUDE_PLUGIN_DATA:-}" ] && PLUGIN_DATA_N="$(_nrm "$CLAUDE_PLUGIN_DATA")"

SID="${CLAUDE_CODE_SESSION_ID:-}" \

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Restore session binding without relying on missing env

When /prep-compact runs this helper from the skill, there is no hook JSON on stdin and Claude Code does not export the hook session_id as CLAUDE_CODE_SESSION_ID; the session id is only provided in hook input. In that normal invocation path SID is empty, the resolver prints NOSID, and the skill always falls back to the in-memory survey instead of reading the warm handoff the Stop hook just wrote, effectively disabling the core cumulative handoff behavior for users unless they happened to set this nonstandard env var themselves.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

this is wrong, CLAUDE_CODE_SESSION_ID is exposed, it just is not documented (yet)

Comment thread hooks/update-handoff.sh Outdated

_NOISE_RE = re.compile(
r'(?:^|[\\/])\.git[\\/]' # .git/ internals
r'|^/tmp/' # POSIX root temp

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep project files under /tmp in the handoff

When the repository itself is checked out under /tmp (common in CI, disposable sandboxes, or repro directories), every absolute path captured from normal Read/Edit/Write calls starts with /tmp/, so this filter removes the actual project files from both recent_files and cumulative_files. In that context /prep-compact loses the file list it is supposed to preserve, not just transient scratch files.

Useful? React with 👍 / 👎.

@koenvdheide

Copy link
Copy Markdown
Owner Author

/tmp/ exclusion is dumb and way too aggressive and broad, it creates a real risk of excluding working files. Reverting this so only .git and the plugin's own cache files are excluded

koenvdheide and others added 2 commits June 5, 2026 21:34
Temp dirs (/tmp, C:\tmp, AppData\Local\Temp) hold real user files; blacklisting them risked dropping work from the handoff. Keep only .git/ and .claude/plugins/{data,cache}/.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@koenvdheide

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

ℹ️ 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".

@koenvdheide koenvdheide merged commit 1e34f7e into main Jun 5, 2026
2 checks passed
@koenvdheide koenvdheide deleted the session-bound-handoff branch June 5, 2026 19:51
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