fix(claude): detach the session-end akm index reindex (#90) - #92
Merged
Conversation
sessionEnd() ran `akm index` through a blocking akmRunChecked() with an INDEX_TIMEOUT cap. In headless mode (`claude -p`) the harness tears the hook process down as soon as the hook returns, so the reindex was killed mid-run and the process died before reaching its own appendLog(SESSION_LOG, "akm_index_failed", ...) line — the failure was recorded nowhere in the plugin state dir, and every scripted run printed `SessionEnd hook [...] failed: Hook cancelled` on stderr. Spawn it detached + unref'd instead, matching sessionStart()'s reindex and extractSession(). Following extractSession()'s precedent, the child's stdout/stderr go to STATE_DIR/index.log rather than stdio: "ignore" so a reindex that fails after the parent is gone still leaves a trace, and the spawn attempt is recorded in session.log as `index_spawned` (a failed spawn still logs `akm_index_failed`). AKM_INDEX_TIMEOUT no longer has a consumer and is removed along with its README row; index.log is documented in the state-file table. Fixes #90 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018aDbzuoe77LGKFre2Dtj2k
Contributor
Eval diff
Metric deltas
Plugin surfaceNo surface changes. No regressions. |
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.
Fixes #90
Cause
sessionEnd()calledrunIndexOnSessionEnd(), which ranakm indexthrough a blockingakmRunChecked(["index"], undefined, INDEX_TIMEOUT * 1000). That holds the hook process open for a full reindex. In headless mode (claude -p) the harness tears the hook down first and kills it, printingSessionEnd hook [...] failed: Hook cancelled, and:runIndexOnSessionEnd()never reaches its ownappendLog(SESSION_LOG, "akm_index_failed", ...)line and the failure is recorded nowhere in the plugin state dir.Fix
Spawn the reindex
detached: true+child.unref(), matching the two patterns already in the same file:sessionStart()'s reindex andextractSession(), which demonstrably survives the same teardown.Following
extractSession()'s precedent (see theEXTRACT_LOGcomment near the top of the file), the child does not vanish intostdio: "ignore": its stdout/stderr are appended toSTATE_DIR/index.log(owner-only, rotated like every other state file), and the spawn attempt itself is recorded insession.logasindex_spawned. A spawn that throws still logsakm_index_failed. So the diagnosability that issue #90 reports as lost is preserved — a reindex that fails after the parent is gone leaves a trace inindex.log.runIndexOnSessionEnd()has exactly one caller (sessionEnd()), confirmed by grep, so no other path needed the checked/blocking behavior.AKM_INDEX_TIMEOUTno longer has a consumer and is removed along with its README row;index.logis documented in the state-file table.No new config knobs, no console/stdout/stderr writes, subprocess boundary wrapped in try/catch with plugin-local logging (AGENTS.md).
Tests
Reused the existing harness in
tests/claude-plugin.test.ts(runHook,waitFor,shellQuote,permissionBits):session-end does not block on the reindex (issue #90): a fakeakmthatsleep 3s onindexthen touches a marker. Asserts the hook returns in well under 3s, that the marker does not yet exist when it returns (i.e. it did not block on a checked reindex), and that the detached child completes afterwards.session-end records the spawn and captures the child's output in index.log(wassession-end logs akm index failures without throwing): assertsindex_spawnedinsession.log, theakm_indexheader inindex.log, the failing child's stderr landing inindex.log, and0600permissions.session-end runs akm index and no longer writes a session_checkpoint memorynow polls withwaitForsince the fake CLI writes after the hook returns.Verification
cd claude && bun install && bun run typecheck:(clean, no diagnostics)
bun test tests/claude-plugin.test.ts:Full
bun testfrom the repo root:The 2 failures + 1 error are pre-existing and unrelated — they are in
tests/opencode-plugin.test.ts(Cannot find module '@opencode-ai/plugin') andtests/opencode-eval-harness.test.ts, both from OpenCode deps not being installed in this environment. Baseline onmainwith the change stashed:192 pass, 4 skip, 2 fail, 1 error— same failures, one fewer passing test (the new regression test).🤖 Generated with Claude Code
https://claude.ai/code/session_018aDbzuoe77LGKFre2Dtj2k