From 42ad3fe8535987ac4acd9d66ff2b7b7d768be05b Mon Sep 17 00:00:00 2001 From: Tibsfox Date: Fri, 10 Apr 2026 11:47:07 -0700 Subject: [PATCH] feat(hooks): auto-record session state on context exhaustion (#1974) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the context monitor detects CRITICAL threshold (25% remaining) and a GSD project is active, spawn a fire-and-forget subprocess to record "Stopped At: context exhaustion at N%" in STATE.md. This provides automatic breadcrumbs for /gsd-resume-work when sessions crash from context exhaustion — the most common unrecoverable scenario. Previously, session state was only saved via voluntary /gsd-pause-work. The subprocess is detached and unref'd so it doesn't block the hook or the agent. The advisory warning to the agent is unchanged. Closes #1974 Co-Authored-By: Claude Opus 4.6 --- hooks/gsd-context-monitor.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/hooks/gsd-context-monitor.js b/hooks/gsd-context-monitor.js index 150646d8b..ed36374b2 100644 --- a/hooks/gsd-context-monitor.js +++ b/hooks/gsd-context-monitor.js @@ -128,6 +128,21 @@ process.stdin.on('end', () => { // Detect if GSD is active (has .planning/STATE.md in working directory) const isGsdActive = fs.existsSync(path.join(cwd, '.planning', 'STATE.md')); + // On CRITICAL with active GSD project, auto-record session state as a + // breadcrumb for /gsd-resume-work (#1974). Fire-and-forget subprocess — + // doesn't block the hook or the agent. + if (isCritical && isGsdActive) { + try { + const gsdTools = path.join(process.env.HOME || '', '.claude', 'get-shit-done', 'bin', 'gsd-tools.cjs'); + const timestamp = new Date().toISOString().split('T')[0]; + require('child_process').spawn( + process.execPath, + [gsdTools, 'state', 'update', 'Stopped At', `context exhaustion at ${usedPct}% (${timestamp})`], + { cwd, detached: true, stdio: 'ignore' } + ).unref(); + } catch { /* non-critical — don't let state recording break the hook */ } + } + // Build advisory warning message (never use imperative commands that // override user preferences — see #884) let message;