/** * PreCompact hook — fired just before Claude Code truncates context. * Triggers `compact_memory` so superseded P/B frames merge before the * native compaction step. */ import { isDirectExecution } from '@waggle/hive-mind-shim-core'; import { pickStringFromObject, runHook, type HookHandler, type HookRunOptions, } from './_shared.js'; interface PreCompactPayload { scope: string | undefined; } export const preCompactHandler: HookHandler = { parse(raw): PreCompactPayload { const obj = (raw && typeof raw === 'object') ? raw as Record : {}; const scope = pickStringFromObject(obj, 'session_id') ?? pickStringFromObject(obj, 'sessionId') ?? pickStringFromObject(obj, 'scope'); return { scope }; }, async run(payload, { bridge, logger }): Promise { // Commit 1.4: scope param is unused at the upstream level (cleanup_frames // operates on the active workspace). We retain payload.scope on the // parsed payload for future use (workspace-id selection in Wave 2). const result = await bridge.cleanupFrames(); logger.debug('cleanup_frames done', { pruned: result.pruned, scope: payload.scope }); return undefined; }, }; export async function runPreCompact(opts: Partial = {}): Promise { return runHook(preCompactHandler, { name: 'pre-compact', ...opts }); } if (isDirectExecution(import.meta.url)) { void runPreCompact(); }