SessionStart catch-up for force-killed sessions (release 0.2.6) - #7
Merged
Conversation
Some environments force-kill Claude Code instead of ending it cleanly: a worktree/pane manager (e.g. Orca) SIGKILLs the process group when you delete a worktree, and a SIGKILL cannot run any hook. Verified empirically — a signal-trap process inside an Orca worktree got no trappable signal and its EXIT trap never ran when the worktree was deleted — and in Orca's own code (process.kill(-pgid, "SIGKILL")). So the SessionEnd sync + backup silently never fire in that flow; only sessions that hit PreCompact get indexed. Raw transcripts stay durable on disk, but the searchable index falls behind. Fix by moving the safety net to SessionStart, which always runs: - New: bare `memware sync` (no path, not --from-hook) catches up the configured backup.transcript_src (default ~/.claude/projects), so it indexes whatever the last force-killed session left unsynced. - New SessionStart hook runs that catch-up sync plus a throttled `memware backup --if-stale 20`, backgrounded (nohup … &) so session startup is never delayed and nothing is injected into context. - SessionEnd/PreCompact are kept — SessionEnd still fires on clean exits. Bumps to 0.2.6 (package + both manifests, per the guard test). Docs (README, integrations.md) and CHANGELOG updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NnaQwZUSDRbVUNh8fsdksD
The SessionStart catch-up runs sync + backup in the background on every start, so several memware processes can now touch the store at once (SessionStart catch-up, a session-end sync, the backup cron). WAL permits one writer at a time; without a busy timeout a concurrent write fails immediately with "database is locked". Wait-and-retry instead. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NnaQwZUSDRbVUNh8fsdksD
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem (found by testing your actual workflow)
Deleting an Orca worktree SIGKILLs the process group — proven two ways:
STARTEDwhen the worktree was deleted — none of its SIGTERM/SIGHUP/SIGINT/SIGQUIT traps fired, and even bash'sEXITtrap didn't run. That's an untrappable kill.process.kill(-pgid, "SIGKILL").A
SIGKILLcannot run any hook, so the plugin'sSessionEndsync and backup never fire when a worktree is deleted (the common flow — nobody types/quitfirst). Consequence: a short session that never hits/compactis never indexed (itsPreCompactnever runs either). Raw transcripts stay safe on disk, but recall falls behind.The fix — move the safety net to
SessionStartSessionStartalways runs, so it can catch up whatever the previous force-killed session missed:memware syncwith no path (and not--from-hook) now indexes the configuredbackup.transcript_src(default~/.claude/projects). Useful on its own; it's what the hook calls.SessionStarthook: runs that catch-up sync + a throttledmemware backup --if-stale 20, backgrounded (nohup … &) so startup is never delayed and nothing lands in the new session's context.SessionEnd/PreCompact—SessionEndstill fires on clean exits, so this is belt-and-suspenders.Net: the previous session is indexed at the next start even when its
SessionEndwas skipped.Tests
test_bare_sync_catches_up_configured_transcript_src—memware syncwith no path indexes the configured source.--from-hook).Bumps to 0.2.6 (package + both manifests, enforced by the drift-guard test). Full suite, ruff, format, mypy, and a hooks.json JSON-validity check all green locally.
🤖 Generated with Claude Code