import type { MemoryDatabase } from '../db/database.js'; import type { createLogger } from '../utils/logger.js'; export interface AutoRebuildConfig { enabled: boolean; lagDays: number; nullThreshold: number; } /** SessionEnd 배선 fallback (config.contextrank 미존재 시). manager zod default와 동일값. */ export declare const DEFAULT_AUTO_REBUILD: AutoRebuildConfig; /** * rebuild in-flight lock TTL. 초과 시 stale로 간주하여 회수(spawn 죽음/중단 대비). * build 최대 소요에 여유를 둔 30분 — #208 이후 전건 완주가 **234초**라 TTL 이 7.7배 여유다. */ export declare const REBUILD_LOCK_TTL_MS: number; /** * #207 (ADR-089 v2.3 D-A): 리스 갱신 주기. * 일하는 자식이 이 주기로 락 mtime 을 갱신하므로 `age > TTL` 이 살아 있는 프로세스에 대해 * 참이 되지 않는다. TTL(30분) 대비 여유 29.75배 — 최악 갱신 지연 = 60s + 루프 1회전(0.517s). * ⚠️ 회전 게이트(`i & N`)를 두지 마라 — 초반 512회전이 264초라 실효 간격이 4배 이상 늘어난다. * `Date.now()` 는 약 25ns 라 n=33,000 전건 호출이 0.83ms 다(총 소요의 1억분의 1). */ export declare const LEASE_RENEW_MS: number; /** ADR-089 D-B: 락 소유권 핸들. `edge-builder` 가 fs 를 모르게 함수로 주입한다. */ export interface LeaseHandle { /** 자기 락이면 mtime 갱신 후 true. 축출됐거나 사라졌으면 false(자식은 즉시 종료). */ renew(): boolean; } /** * #207 (ADR-089 D-B): 소유권 토큰 기반 리스 핸들. * 락 본문이 내 토큰일 때만 mtime 을 갱신한다 — 축출된 자식이 후속 자식의 락을 * 갱신하다 `finally` 에서 지우는 「축출 캐스케이드」를 막는다. */ export declare function makeLease(lockPath: string, token: string): LeaseHandle; /** * #207 (ADR-089 D-B/M3): 자기 락일 때만 회수. * 수동 실행(토큰 없음)과 축출된 자식은 남의 락을 지우지 않는다. */ export declare function releaseLease(lockPath: string | undefined, token: string | undefined): boolean; export interface RebuildDecision { rebuild: boolean; reason: string; nullCount: number; lagDays: number | null; } /** * stale 판정: (a) 한 번도 계산 안 됨, OR (b) scores lag ≥ lagDays, OR (c) NULL count ≥ nullThreshold. */ export declare function shouldRebuildShadowScores(db: MemoryDatabase, cfg: AutoRebuildConfig, nowMs: number): RebuildDecision; /** * lock 경로 — db 파일과 같은 디렉토리(예: ~/.a2a/.contextrank-rebuild.lock). * * #68 (ADR-050): 이전에는 `resolve(dbPath)`만 했다. 그런데 config의 `db.path`는 * `~/.a2a/memory.db` 문자열이고 **`~`는 Node가 확장하지 않는다** → lock 경로가 * `/~/.a2a/...`가 되어 `writeFileSync`가 ENOENT → `lock-write-failed` → * **spawn이 영구히 일어나지 않았다**(#65가 발동 0이던 진짜 원인 중 하나). * DB 오픈 경로는 `resolvePath`를 거쳐서 정상이라 아무도 눈치채지 못했다. */ export declare function rebuildLockPath(dbPath: string): string; /** * rebuild 로그 경로 — lock과 같은 디렉토리(예: ~/.a2a/.contextrank-rebuild.log). * #69 (T-B, rule 74): detached spawn stdio:'ignore'가 자식 크래시를 지우던 것을 로그로 돌린다. */ export declare function rebuildLogPath(dbPath: string): string; /** * in-flight lock 활성 여부. mtime < TTL이면 활성(true). TTL 초과 stale lock은 * 회수(unlink) 후 false 반환. */ export declare function isRebuildLocked(lockPath: string, nowMs: number, logger?: { warn(msg: string, meta?: Record): void; }): boolean; export interface RebuildSpawnResult { spawned: boolean; reason: string; } /** * SessionEnd hook 진입점 — stale 판정 후 detached background spawn. * hook은 spawn().unref() 후 즉시 반환하며, `contextrank rebuild`가 완료 시 lock을 회수한다. */ export declare function maybeSpawnShadowRebuild(db: MemoryDatabase, dbPath: string, cfg: AutoRebuildConfig, logger: ReturnType, nowMs: number, /** * #207 (ADR-089 DoD 11): 어느 hook 이 띄웠는지. 종전에는 session-start 가 **별도 로그 줄**을 * 하나 더 남겨, `grep "shadow-rebuild spawned"`(substring)가 **같은 spawn 을 두 번** 셌다. * ⇒ 기입 사이트를 하나로 두고 채널은 meta 로 구분한다. */ channel?: string): RebuildSpawnResult; //# sourceMappingURL=shadow-rebuild.d.ts.map