/** * SessionEnd Hook * * Claude Code 세션 종료 시 실행됩니다. * 세션 전체를 분석하여 요약 메모리를 생성합니다. * autoSync 활성화 시 pending 메모리를 원격 서버로 push합니다. */ import { getSharedDb } from './shared.js'; import { ConfigManager } from '../config/manager.js'; import { createLogger } from '../utils/logger.js'; import type { SessionEndContext } from '../types/index.js'; /** 네트워크 구간 전체 예산. 초과 시 남은 단계는 skip(다음 세션 이월 또는 유실 경고). */ export declare const NETWORK_BUDGET_MS = 20000; /** 개별 HTTP 클라이언트 타임아웃 상한 — 이게 없으면 배치 1개가 60초×재시도까지 간다. */ export declare const CLIENT_TIMEOUT_CAP_MS = 15000; export declare function handleSessionEnd(context: SessionEndContext): Promise; /** * 세션 파일에서 메모리 추출 (Phase 1 내부) */ /** * #90 (ADR-053 T4): CLI `session-extract`가 재사용하도록 export. * * 기존 CLI `extract`는 비-LLM `extractMemories`를 쓰므로(cli/commands/extract.ts:66) * LLM 분류와 세션 요약(`summarizeSession`)이 빠진다. 그것을 spawn 대상으로 삼으면 * goal 서빙 자산이 생성되지 않는다 — 그래서 이 함수 자체를 재사용한다. */ export declare function extractSessionMemories(context: SessionEndContext, config: ReturnType, db: ReturnType, logger: ReturnType, createdIds: string[], dedupStatsOut?: { add: number; update: number; delete: number; noop: number; }, /** * extract에 허용된 잔여 시간(ms)을 돌려주는 함수 (ADR-052 D3). * 선택적 LLM 후속 단계(contradiction / skill taxonomy)를 예산 안에서만 실행해 * Phase 3 네트워크 몫을 보존한다. 미전달 시 무제한(기존 동작). */ extractRemaining?: () => number, /** * #90 (ADR-053 T4): 대상에서 제외할 세션 id — SessionStart 채널 전용. * * SessionEnd에서는 "가장 최근 수정 파일 = 방금 끝난 세션"이 성립하지만, SessionStart가 * detached spawn한 자식은 **수 초 뒤에** 파일을 읽으므로 그때는 현재 세션 파일이 이미 * 생성돼 있다(실측: 부모 hook 10:42:53~10:43:02 / 현재 세션 파일 생성 10:43:10 — 여유 8초). * 그래서 세션 특정을 시각이 아니라 **식별자**로 한다. 부모가 자기 sessionId를 넘긴다. */ excludeSessionId?: string): Promise; /** * hook 전체 안전장치. * * #137 (ADR-067): 최악 실행 시간보다 **크게** 유지해야 한다. 산수: * * Phase 1 (LOCAL) 예산 무관 — remaining() 미사용, 실측 ~500ms * Phase 2+3 (extract+network) networkDeadline(NETWORK_BUDGET_MS=20,000ms)이 **진입**을 캡 * 마지막 진입 작업의 초과 최대 CLIENT_TIMEOUT_CAP_MS(15,000ms) * ──────── * 최악 ~35,500ms < 40,000ms (여유 ~4,500ms) * * ⚠️ `remaining() > 0`은 **진입 게이트**다. 그 검사를 통과한 작업이 예산을 넘겨 * 끝나는 것은 막지 못하고, trackProficiencyLocal / reinforceInjectedMemories는 * remaining을 인자로 받지도 않는다. 그래서 20초 예산이 20초를 보장하지 않는다. * * 이전 값 30,000ms는 이 최악값보다 작아 예산 소진 세션이 safety로 빠질 수 있었다. * 그 경로는 process.exit(0)이라 finally의 logger.flush()에 도달하지 못해 로그가 * 통째로 유실된다 — 2026-05-27~08-21 SessionEnd 로그 0건의 유력 원인. * * 🔴 단 그 인과는 **미확정**이다. 로그가 없으니 safety 발동 자체를 관측할 수 없었다. * 위 activeLogger.flush()가 그 관측을 가능하게 하므로, 다음 세션 로그에 * `Safety timeout` 이 있으면 이 가설이 확정되고 없으면 다른 원인(프로세스 kill 등)이다. * * 40초가 사용자 체감을 늘리지 않는 근거: settings.json의 이 hook은 `async: true`라 * 하네스가 즉시 backgrounded로 반환한다(블로킹 0). DB 경합은 busy_timeout 15초가 흡수. */ export declare const HOOK_TIMEOUT_MS = 40000; /** * CLI 엔트리포인트 * 전체 실행에 HOOK_TIMEOUT_MS 안전장치 적용 */ export declare function main(): Promise; //# sourceMappingURL=session-end.d.ts.map