@wrongstack/core 0.275.1 → 0.276.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/{agent-bridge-D9JkPvJ0.d.ts → agent-bridge-D7A-eu3C.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-CArSFKFl.d.ts → agent-subagent-runner-CEuw4ATz.d.ts} +16 -10
  3. package/dist/{brain-DCkB5_e7.d.ts → brain-BLOyN5ZP.d.ts} +127 -1
  4. package/dist/{compactor-CzSvxM1g.d.ts → compactor-DcBpaJsI.d.ts} +1 -1
  5. package/dist/{config-BzFRKkg7.d.ts → config-Bf5mj-ad.d.ts} +20 -2
  6. package/dist/{context-BrLe8pJy.d.ts → context-CLnUMW5g.d.ts} +40 -2
  7. package/dist/coordination/index.d.ts +43 -24
  8. package/dist/coordination/index.js +849 -648
  9. package/dist/coordination/index.js.map +1 -1
  10. package/dist/defaults/index.d.ts +28 -28
  11. package/dist/defaults/index.js +1636 -845
  12. package/dist/defaults/index.js.map +1 -1
  13. package/dist/execution/index.d.ts +16 -16
  14. package/dist/execution/index.js +218 -49
  15. package/dist/execution/index.js.map +1 -1
  16. package/dist/execution/prompt-enhancer.d.ts +1 -1
  17. package/dist/extension/index.d.ts +7 -7
  18. package/dist/extension/index.js.map +1 -1
  19. package/dist/{global-mailbox-CXkugtNQ.d.ts → global-mailbox-Iqfkgmwu.d.ts} +3 -3
  20. package/dist/{goal-store-DUwdbdoY.d.ts → goal-store-DGb6b5Ed.d.ts} +1 -1
  21. package/dist/hq/index.d.ts +6 -6
  22. package/dist/hq/index.js +178 -75
  23. package/dist/hq/index.js.map +1 -1
  24. package/dist/{index-CtlizLTK.d.ts → index-Cn0NOshr.d.ts} +10 -5
  25. package/dist/{index-neOCEy6q.d.ts → index-L4RZN9jJ.d.ts} +2 -2
  26. package/dist/index.d.ts +56 -48
  27. package/dist/index.js +2789 -1546
  28. package/dist/index.js.map +1 -1
  29. package/dist/infrastructure/index.d.ts +6 -6
  30. package/dist/infrastructure/index.js +26 -7
  31. package/dist/infrastructure/index.js.map +1 -1
  32. package/dist/kernel/index.d.ts +20 -12
  33. package/dist/kernel/index.js +55 -9
  34. package/dist/kernel/index.js.map +1 -1
  35. package/dist/{mailbox-types-_7gaY0Rl.d.ts → mailbox-types-DTl7bRH3.d.ts} +3 -1
  36. package/dist/{mcp-servers-MLL6bMlv.d.ts → mcp-servers-CuZGf9fI.d.ts} +4 -4
  37. package/dist/models/index.d.ts +5 -5
  38. package/dist/models/index.js +223 -139
  39. package/dist/models/index.js.map +1 -1
  40. package/dist/{models-registry-CrkcxQ-g.d.ts → models-registry-8XOdxWQu.d.ts} +16 -1
  41. package/dist/{multi-agent-coordinator-Dc_HuG9p.d.ts → multi-agent-coordinator-CiRtKVTk.d.ts} +8 -1
  42. package/dist/{null-fleet-bus-BMZwMin7.d.ts → null-fleet-bus-d9G-bVy9.d.ts} +26 -22
  43. package/dist/observability/index.d.ts +2 -2
  44. package/dist/{path-resolver-uVK4BatM.d.ts → path-resolver-BhIb6mtd.d.ts} +8 -3
  45. package/dist/{permission-CJR1qfOi.d.ts → permission-BCbQDR2s.d.ts} +1 -1
  46. package/dist/{permission-policy-DLVKKk4w.d.ts → permission-policy-C0ikndX_.d.ts} +2 -18
  47. package/dist/{pipeline-BYR-Vdau.d.ts → pipeline-Dl6XbfE7.d.ts} +10 -6
  48. package/dist/{provider-model-resolve-iREK_1lG.d.ts → provider-model-resolve-B70epO19.d.ts} +3 -3
  49. package/dist/{provider-runner-i7SQXZuC.d.ts → provider-runner-DZ808MSM.d.ts} +3 -3
  50. package/dist/{retry-policy-BmY5ooh3.d.ts → retry-policy-Dt3_z8Aj.d.ts} +1 -1
  51. package/dist/sdd/index.d.ts +19 -10
  52. package/dist/sdd/index.js +411 -240
  53. package/dist/sdd/index.js.map +1 -1
  54. package/dist/{secret-vault-C9leEMzr.d.ts → secret-vault-BUJ2d1gB.d.ts} +1 -1
  55. package/dist/security/index.d.ts +5 -5
  56. package/dist/security/index.js +30 -6
  57. package/dist/security/index.js.map +1 -1
  58. package/dist/{selector-qjpee9BF.d.ts → selector-BCkWgdwy.d.ts} +1 -1
  59. package/dist/{session-event-bridge-m7y--I-H.d.ts → session-event-bridge-CMvIO59_.d.ts} +1 -1
  60. package/dist/{session-reader-BjLH4V9n.d.ts → session-reader-C8aiChUu.d.ts} +1 -1
  61. package/dist/skills/index.js +1 -0
  62. package/dist/skills/index.js.map +1 -1
  63. package/dist/storage/index.d.ts +68 -30
  64. package/dist/storage/index.js +839 -528
  65. package/dist/storage/index.js.map +1 -1
  66. package/dist/{strategy-compactor-C2bmlWYg.d.ts → strategy-compactor-DI1OHVbB.d.ts} +10 -10
  67. package/dist/{todos-checkpoint-oDS9IBNS.d.ts → todos-checkpoint-Ddd2CGr0.d.ts} +56 -9
  68. package/dist/{tool-executor-D4YdaJ-M.d.ts → tool-executor-Bmd5Ygoo.d.ts} +45 -10
  69. package/dist/tools/index.d.ts +2 -2
  70. package/dist/tools/index.js.map +1 -1
  71. package/dist/types/index.d.ts +20 -20
  72. package/dist/types/index.js +331 -98
  73. package/dist/types/index.js.map +1 -1
  74. package/dist/utils/index.d.ts +16 -3
  75. package/dist/utils/index.js +159 -83
  76. package/dist/utils/index.js.map +1 -1
  77. package/dist/{worktree-manager-A1Efnvs0.d.ts → worktree-manager-DBdl_5rs.d.ts} +4 -1
  78. package/instructions/agents/shadow-agent.md +3 -3
  79. package/instructions/coordination/director-preamble.md +3 -3
  80. package/instructions/modes/research-web.md +4 -4
  81. package/package.json +1 -1
  82. package/skills/research-web/SKILL.md +26 -26
  83. package/skills/research-web/SKILL.save.md +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/atomic-write.ts","../../src/utils/expect-defined.ts","../../src/utils/message-invariants.ts","../../src/utils/term.ts","../../src/utils/color.ts","../../src/utils/deep-merge.ts","../../src/utils/error.ts","../../src/utils/regex-guard.ts","../../src/utils/safe-json.ts","../../src/utils/slug.ts","../../src/utils/ulid.ts","../../src/utils/wstack-paths.ts","../../src/storage/session-helpers.ts","../../src/storage/file-session-writer.ts","../../src/storage/session-id.ts","../../src/storage/session-summary.ts","../../src/storage/session-tool-call-ends.ts","../../src/storage/storage-concurrency.ts","../../src/storage/session-store.ts","../../src/storage/queue-store.ts","../../src/storage/attachment-store.ts","../../src/types/memory.ts","../../src/storage/memory-backend.ts","../../src/storage/memory-store.ts","../../src/storage/memory-graph-backend.ts","../../src/utils/instruction-file.ts","../../src/storage/memory-consolidator.ts","../../src/types/errors.ts","../../src/storage/config-store.ts","../../src/security/secret-vault.ts","../../src/types/context-window.ts","../../src/types/config.ts","../../src/types/default-config.ts","../../src/storage/config-loader.ts","../../src/storage/config-migration.ts","../../src/storage/recovery-lock.ts","../../src/storage/session-reader.ts","../../src/utils/session-scoped-path.ts","../../src/storage/annotations-store.ts","../../src/replay/hash.ts","../../src/storage/replay-log-store.ts","../../src/storage/session-recovery.ts","../../src/storage/tool-audit-log.ts","../../src/storage/session-analyzer.ts","../../src/session-registry.ts","../../src/agent-status-tracker.ts","../../src/fleet-notifier.ts","../../src/storage/session-rewinder.ts","../../src/storage/todos-checkpoint.ts","../../src/storage/plan-store.ts","../../src/storage/plan-templates.ts","../../src/storage/task-store.ts","../../src/storage/director-state.ts","../../src/storage/goal-store.ts","../../src/storage/prompt-store.ts","../../src/storage/prompt-usage-store.ts","../../src/storage/cloud-sync.ts","../../src/storage/session-event-bridge.ts"],"names":["path","fs","stat","resolve","open","randomBytes","slugify","projectHash","path3","fsp","path4","entry","path5","fsp3","fsp4","path6","path7","fs2","writeFile","mkdir","fs3","path8","path10","deepMerge","fs5","path11","os2","fsp6","path12","fs6","path13","randomUUID","fs7","createHash","storageErrorString","offset","fs8","path14","fs9","path15","stableStringify","fs10","sortKeys","path16","projectSlug","fs11","pidAlive","path17","fs12","path18","fsp7","fsp8","fsp9","fsp10","fsp11","lock","hostname","fsp12","fs13","path19","fs14","path20","path21","fs15","relative"],"mappings":"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","file":"index.js","sourcesContent":["import { randomBytes } from 'node:crypto';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\nexport interface AtomicWriteOptions {\n mode?: number | undefined;\n encoding?: BufferEncoding | undefined;\n}\n\nexport interface FileLockOptions {\n timeoutMs?: number | undefined;\n staleMs?: number | undefined;\n}\n\nexport async function atomicWrite(\n targetPath: string,\n content: string | Uint8Array,\n opts: AtomicWriteOptions = {},\n): Promise<void> {\n const dir = path.dirname(targetPath);\n await fs.mkdir(dir, { recursive: true });\n const tmp = path.join(dir, `.${path.basename(targetPath)}.${randomBytes(6).toString('hex')}.tmp`);\n\n // Write content to tmp first; 'wx' ensures exclusive creation (fails if\n // tmp already exists — extremely unlikely with 6-byte random suffix).\n try {\n if (typeof content === 'string') {\n await fs.writeFile(tmp, content, { flag: 'wx', encoding: opts.encoding ?? 'utf8' });\n } else {\n await fs.writeFile(tmp, content, { flag: 'wx' });\n }\n try {\n const fh = await fs.open(tmp, 'r+');\n try {\n await fh.sync();\n } finally {\n await fh.close();\n }\n } catch {\n // fsync best-effort\n }\n // Now safely read mode from target (if it exists) and apply to tmp before rename.\n // Prefer opts.mode for new files; for existing files preserve their mode.\n let mode: number | undefined;\n try {\n const stat = await fs.stat(targetPath);\n mode = stat.mode & 0o777;\n } catch {\n mode = opts.mode;\n }\n if (mode !== undefined) {\n await fs.chmod(tmp, mode);\n }\n await renameWithRetry(tmp, targetPath);\n // P3 #20 (before-release.md): on Windows, fs.rename (MoveFileExW) does\n // not preserve Unix permission bits — the chmod above applies to the tmp\n // file, but the rename may reset the destination's mode to the Windows\n // default. Re-apply the mode after rename on win32 so an edited file\n // keeps its executable bit (or any non-default permission). On POSIX,\n // rename preserves metadata so this is a no-op (chmod is idempotent and\n // cheap), but we gate it on win32 to avoid the extra stat+chmod on the\n // common path.\n if (mode !== undefined && process.platform === 'win32') {\n try {\n await fs.chmod(targetPath, mode);\n } catch {\n // Best-effort: a transient EPERM (antivirus lock) should not fail\n // the write — the content is already on disk.\n }\n }\n } catch (err) {\n try {\n await fs.unlink(tmp);\n } catch {\n // ignore cleanup error\n }\n throw err;\n }\n}\n\nexport async function ensureDir(dir: string): Promise<void> {\n await fs.mkdir(dir, { recursive: true });\n}\n\nexport async function withFileLock<T>(\n targetPath: string,\n fn: () => Promise<T>,\n opts: FileLockOptions = {},\n): Promise<T> {\n const dir = path.dirname(targetPath);\n await fs.mkdir(dir, { recursive: true });\n const lockPath = path.join(dir, `.${path.basename(targetPath)}.lock`);\n const timeoutMs = opts.timeoutMs ?? 5_000;\n const staleMs = opts.staleMs ?? 30_000;\n const started = Date.now();\n let handle: fs.FileHandle | undefined;\n\n for (;;) {\n try {\n handle = await fs.open(lockPath, 'wx');\n await handle.writeFile(`${process.pid}:${Date.now()}`);\n break;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n // ENOENT means the directory was deleted (e.g. by concurrent cleanup).\n // Recreate it and retry acquiring the lock.\n if (code === 'ENOENT') {\n await fs.mkdir(dir, { recursive: true });\n continue;\n }\n if (code !== 'EEXIST') throw err;\n try {\n const stat = await fs.stat(lockPath);\n if (Date.now() - stat.mtimeMs > staleMs) {\n await fs.unlink(lockPath);\n continue;\n }\n } catch {\n continue;\n }\n if (Date.now() - started >= timeoutMs) {\n throw new Error(`Timed out waiting for file lock: ${targetPath}`);\n }\n await new Promise((resolve) => setTimeout(resolve, 25));\n }\n }\n\n try {\n return await fn();\n } finally {\n try {\n await handle?.close();\n } catch {\n // ignore\n }\n try {\n await fs.unlink(lockPath);\n } catch {\n // ignore\n }\n }\n}\n\n// On Windows, fs.rename over an existing file can fail with EPERM/EBUSY/EACCES\n// when antivirus, file indexers, editor file watchers, or a concurrent writer\n// briefly hold a handle on the destination. These are transient — retry with a\n// short backoff before giving up. POSIX renames are atomic and won't hit this.\nconst TRANSIENT_RENAME_CODES = new Set(['EPERM', 'EBUSY', 'EACCES', 'ENOTEMPTY']);\n\nasync function renameWithRetry(from: string, to: string): Promise<void> {\n if (process.platform !== 'win32') {\n await fs.rename(from, to);\n return;\n }\n const delays = [10, 25, 60, 120, 250];\n let lastErr: unknown;\n for (let i = 0; i <= delays.length; i++) {\n try {\n await fs.rename(from, to);\n return;\n } catch (err) {\n lastErr = err;\n const code = (err as NodeJS.ErrnoException)?.code;\n if (!code || !TRANSIENT_RENAME_CODES.has(code) || i === delays.length) {\n throw err;\n }\n await new Promise((resolve) => setTimeout(resolve, delays[i]));\n }\n }\n throw lastErr;\n}\n","/** Assert a value is neither null nor undefined. Throws if it is.\n * Useful after optional chaining and indexed access when the\n * control flow guarantees the value exists but TypeScript can't\n * prove it (e.g. after a check on a related field). */\nexport function expectDefined<T>(value: T | null | undefined, label?: string): T {\n if (value === null || value === undefined) {\n const err = new Error(label ? `Expected ${label} to be defined` : 'Expected value to be defined');\n err.name = 'ExpectDefinedError';\n throw err;\n }\n return value;\n}\n","import { expectDefined } from './expect-defined.js';\nimport type { ContentBlock, ToolResultBlock, ToolUseBlock } from '../types/blocks.js';\nimport type { Message } from '../types/messages.js';\nexport interface MessageRepairReport {\n changed: boolean;\n removedToolUses: string[];\n removedToolResults: string[];\n removedMessages: number;\n}\n\nexport interface MessageRepairResult {\n messages: Message[];\n report: MessageRepairReport;\n}\n\n/**\n * Repair provider-level tool-call adjacency invariants.\n *\n * Anthropic requires every assistant `tool_use` block to have a matching\n * `tool_result` block in the immediately following user message. Manual\n * context surgery (summary/prune) can cut through the middle of such an\n * exchange. This function removes only the now-orphaned protocol blocks,\n * preserving surrounding text/images/thinking blocks where possible.\n */\nexport function repairToolUseAdjacency(messages: Message[]): MessageRepairResult {\n const removedToolUses: string[] = [];\n const removedToolResults: string[] = [];\n let removedMessages = 0;\n let changed = false;\n const out: Message[] = [];\n\n for (let i = 0; i < messages.length; i++) {\n const original = expectDefined(messages[i]);\n let msg = original;\n\n if (hasToolUse(msg)) {\n const nextIds = toolResultIds(messages[i + 1]);\n const filtered = mapContent(msg, (blocks) => {\n const next: ContentBlock[] = [];\n for (const block of blocks) {\n if (block.type === 'tool_use' && !nextIds.has(block.id)) {\n removedToolUses.push(block.id);\n changed = true;\n continue;\n }\n next.push(block);\n }\n return next;\n });\n msg = filtered ?? msg;\n }\n\n if (hasToolResult(msg)) {\n const allowed = toolUseIds(out[out.length - 1]);\n const filtered = mapContent(msg, (blocks) => {\n const next: ContentBlock[] = [];\n for (const block of blocks) {\n if (block.type === 'tool_result' && !allowed.has(block.tool_use_id)) {\n removedToolResults.push(block.tool_use_id);\n changed = true;\n continue;\n }\n next.push(block);\n }\n return next;\n });\n msg = filtered ?? msg;\n }\n\n if (isEmptyMessage(msg)) {\n removedMessages++;\n changed = true;\n continue;\n }\n out.push(msg);\n }\n\n return {\n messages: changed ? out : messages,\n report: { changed, removedToolUses, removedToolResults, removedMessages },\n };\n}\n\nfunction hasToolUse(msg: Message | undefined): boolean {\n return contentBlocks(msg).some((b): b is ToolUseBlock => b.type === 'tool_use');\n}\n\nfunction hasToolResult(msg: Message | undefined): boolean {\n return contentBlocks(msg).some((b): b is ToolResultBlock => b.type === 'tool_result');\n}\n\nfunction toolUseIds(msg: Message | undefined): Set<string> {\n const ids = new Set<string>();\n if (msg?.role !== 'assistant') return ids;\n for (const block of contentBlocks(msg)) {\n if (block.type === 'tool_use') ids.add(block.id);\n }\n return ids;\n}\n\nfunction toolResultIds(msg: Message | undefined): Set<string> {\n const ids = new Set<string>();\n if (msg?.role !== 'user') return ids;\n for (const block of contentBlocks(msg)) {\n if (block.type === 'tool_result') ids.add(block.tool_use_id);\n }\n return ids;\n}\n\nfunction contentBlocks(msg: Message | undefined): ContentBlock[] {\n return msg && Array.isArray(msg.content) ? msg.content : [];\n}\n\nfunction mapContent(\n msg: Message,\n fn: (blocks: ContentBlock[]) => ContentBlock[],\n): Message | null {\n if (!Array.isArray(msg.content)) return msg;\n const next = fn(msg.content);\n if (next.length === msg.content.length && next.every((b, idx) => b === msg.content[idx])) {\n return msg;\n }\n return { ...msg, content: next };\n}\n\nfunction isEmptyMessage(msg: Message): boolean {\n if (typeof msg.content === 'string') return msg.content.trim().length === 0;\n return msg.content.length === 0;\n}\n","/**\n * TTY detection helpers — the single source of truth for \"is this process\n * running against a real terminal?\". Replaces ad-hoc `process.stdin.isTTY`\n * / `process.stdout.isTTY` checks scattered across the codebase so that:\n *\n * 1. test code can mock a single module instead of stubbing `isTTY` on\n * every ReadStream/WriteStream the test happens to touch;\n * 2. a future TTY-detection source (an env var override, a Windows\n * ConPTY workaround, …) lands in one place;\n * 3. `isInteractive()` encodes the rule the project already used inline\n * (\"both streams are TTYs AND we're not running under CI\") in one\n * testable helper instead of the same 3-condition check in two\n * different files.\n *\n * Scope: detection only. Raw-mode control (`setRawMode`), resize\n * subscriptions, and write-injection belong to a future, larger TTY\n * abstraction; this module is the smallest pull that gives us a\n * testable seam and dedups 20+ call sites.\n */\n\nconst hasStdout = (): boolean => typeof process !== 'undefined' && !!process.stdout;\nconst hasStdin = (): boolean => typeof process !== 'undefined' && !!process.stdin;\n\n/** True when `process.stdout` is attached to a terminal (not a pipe/file). */\nexport function isStdoutTTY(): boolean {\n return hasStdout() && Boolean(process.stdout.isTTY);\n}\n\n/** True when `process.stdin` is attached to a terminal (not a pipe/file). */\nexport function isStdinTTY(): boolean {\n return hasStdin() && Boolean(process.stdin.isTTY);\n}\n\n/**\n * True when the current process is an interactive session: both stdin and\n * stdout are TTYs. Callers that also need a \"not a single-shot invocation\"\n * or \"not under CI\" check should layer that on top — keeping this helper\n * minimal preserves the original inline checks it replaces.\n */\nexport function isInteractive(): boolean {\n return isStdinTTY() && isStdoutTTY();\n}\n\n/** Current terminal size in characters, with a 24×80 fallback for non-TTYs. */\nexport function getTermSize(): { rows: number; cols: number } {\n if (!hasStdout()) return { rows: 24, cols: 80 };\n return {\n rows: process.stdout.rows ?? 24,\n cols: process.stdout.columns ?? 80,\n };\n}\n\n/**\n * Subscribe to terminal resize events. `cb` is called with the new size each\n * time the underlying stream emits `resize`. Returns a cleanup function the\n * caller MUST call on dispose to remove the listener — leaving a stale\n * `resize` listener on a disposed component leaks the closure (and the\n * component itself, transitively) until the process exits.\n *\n * The stream argument defaults to `process.stdout`. Pass an explicit\n * `NodeJS.WriteStream` when the caller already owns one (e.g. a status line\n * that targets an injected `out` for testability). For non-TTY streams no\n * listener is registered and the returned cleanup is a no-op.\n */\nexport function onResize(\n cb: (size: { rows: number; cols: number }) => void,\n stream: NodeJS.WriteStream = process.stdout,\n): () => void {\n if (!stream || typeof stream.on !== 'function') return () => {};\n const handler = (): void => {\n cb({\n rows: stream.rows ?? 24,\n cols: stream.columns ?? 80,\n });\n };\n stream.on('resize', handler);\n return () => {\n stream.off('resize', handler);\n };\n}\n\n/**\n * Toggle raw mode on a TTY stdin stream. Returns `true` when the toggle was\n * applied, `false` when the stream is null, not a TTY, or doesn't expose\n * `setRawMode` (pipes, file descriptors, Windows ConPTY edge cases). Callers\n * that need to restore the previous mode should snapshot `input.isRaw`\n * BEFORE the call and pass the value to a second call to flip back.\n *\n * Use this helper to drop the now-redundant\n * `if (input.isTTY) input.setRawMode(...)` ceremony at every call site.\n */\nexport function setRawMode(input: NodeJS.ReadStream, mode: boolean): boolean {\n if (input?.isTTY !== true) return false;\n if (typeof input.setRawMode !== 'function') return false;\n input.setRawMode(mode);\n return true;\n}\n\n/**\n * Bracket installed by the interactive input reader while a `readline`\n * prompt is on screen. Out-of-band terminal writes — logger WARN/INFO\n * lines, async activity from the Telegram bridge, etc. — go to the same\n * physical terminal as the half-typed prompt but readline has no idea they\n * happened, so it never repaints. The result is the classic corruption the\n * user sees: every async line strands the in-progress draft as a fresh\n * scrollback row (sometimes with its cursor underline).\n *\n * The guard closes that gap. `suspend()` wipes the draft row so the message\n * prints clean; `resume()` repaints the prompt + draft (cursor preserved).\n * When no prompt is active the guard is `null` and writes pass straight\n * through — so agent-turn output (spinner, renderer) is untouched.\n */\nexport interface OutputLineGuard {\n /** Clear the current input row right before an out-of-band write. */\n suspend(): void;\n /** Repaint the prompt + in-progress draft right after the write. */\n resume(): void;\n}\n\nlet activeOutputGuard: OutputLineGuard | null = null;\n\n/**\n * Register (or clear, with `null`) the guard that brackets out-of-band\n * writes. Installed by {@link writeOut}/{@link writeErr} consumers — in\n * practice the CLI's readline input reader — only while a prompt is live.\n * Idempotent; the most recent caller wins.\n */\nexport function setOutputLineGuard(guard: OutputLineGuard | null): void {\n activeOutputGuard = guard;\n}\n\n/**\n * Stream-agnostic write primitive. Returns `false` when the stream is\n * missing or doesn't expose `write` so callers can degrade silently under\n * hostile host environments (closed pipe, mock injects `null`, test\n * replaces the stream with a stub).\n *\n * When an {@link OutputLineGuard} is installed (a readline prompt is on\n * screen) the write is bracketed by `suspend()`/`resume()` so the user's\n * half-typed input survives the interruption instead of being stranded in\n * scrollback. The guard's own redraw uses raw stream writes — never\n * `writeOut`/`writeErr` — so there is no re-entrancy here.\n *\n * **Not exported in the public API.** Exposed only inside `term.ts` for\n * `writeOut` / `writeErr` to share a single implementation. If a caller\n * needs to write to an arbitrary stream, they should call `writeOut` (or\n * `writeErr`) with an explicit `stream` argument — the named functions\n * are the public surface so the \"this is the standard error stream\"\n * intent stays visible at every call site.\n */\nfunction writeTo(\n s: string,\n stream: NodeJS.WriteStream | undefined,\n): boolean {\n if (!stream || typeof stream.write !== 'function') return false;\n const guard = activeOutputGuard;\n if (!guard) {\n stream.write(s);\n return true;\n }\n // A prompt is live — wipe the draft row, emit the message, repaint.\n guard.suspend();\n stream.write(s);\n guard.resume();\n return true;\n}\n\n/**\n * Write `s` to `stream` (defaults to `process.stdout`). Returns `false`\n * when the stream is missing or doesn't expose `write` so callers can\n * degrade silently under hostile host environments (closed pipe, mock\n * injects `null`, test replaces the stream with a stub).\n *\n * Why a helper:\n * 1. **Single seam for output capture in tests** — stub `writeOut` once\n * and assert on what the rest of the codebase intended to print,\n * without spying on `process.stdout.write` (which is brittle and\n * leaks across parallel test files).\n * 2. **Stream swap without grep** — routing the CLI's output to a\n * logger or `out.log` becomes a one-line change at process boot.\n * 3. **Defensive default** — closes the \"what if `process.stdout` is\n * `null`\" gap that currently exists at ~50 call sites that just\n * call `process.stdout.write(s)` and crash on certain Windows\n * redirect invocations.\n *\n * Call-site migration is staged: this commit introduces the helper, a\n * follow-up commit replaces the 50+ `process.stdout.write(...)` sites\n * with `writeOut(...)`. Until that migration lands, both forms coexist\n * and `writeOut` is the preferred form for new code.\n */\nexport function writeOut(\n s: string,\n stream: NodeJS.WriteStream = process.stdout,\n): boolean {\n return writeTo(s, stream);\n}\n\n/**\n * Symmetric partner of `writeOut` for the standard error stream. Same shape,\n * same defensive contract, same single-seam-for-tests story — just defaults to\n * `process.stderr` instead of `process.stdout`.\n *\n * Use this in code paths that emit error/diagnostic/warning text. Keeping\n * these two helpers split (rather than a single `writeTo(s, stream)`) means\n * the call site reads as a clear intent signal: \"I am writing an error\" vs.\n * \"I am writing a result\" — which matters for callers that decide between\n * stdout/stderr routing (e.g. `--quiet` flags, log-level filtering,\n * structured-log rewriters that fork on stream).\n *\n * Stderr writes from the core logger (see `infrastructure/logger.ts`) and from\n * the TUI guard (see `tui/run-tui.ts`) used to call `process.stderr.write`\n * directly. Routing them through this helper lets tests stub the stream at\n * one boundary and lets future logging middleware (e.g. a JSON-line rewriter)\n * swap the destination for the entire process in one place.\n */\nexport function writeErr(\n s: string,\n stream: NodeJS.WriteStream = process.stderr,\n): boolean {\n return writeTo(s, stream);\n}\n","import { isStdoutTTY } from './term.js';\n\nconst isColorTty = (): boolean => {\n if (envFlag(process.env.NO_COLOR)) return false;\n if (envFlag(process.env.FORCE_COLOR)) return true;\n return isStdoutTTY();\n};\n\nfunction envFlag(value: string | undefined): boolean {\n if (value === undefined) return false;\n if (value.trim() === '') return false;\n return !/^(0|false|no|off)$/i.test(value.trim());\n}\n\nconst COLOR = isColorTty();\n\nconst wrap =\n (open: string, close: string) =>\n (s: string): string =>\n COLOR ? `\\x1b[${open}m${s}\\x1b[${close}m` : s;\n\nexport const color = {\n reset: wrap('0', '0'),\n bold: wrap('1', '22'),\n dim: wrap('2', '22'),\n italic: wrap('3', '23'),\n underline: wrap('4', '24'),\n red: wrap('31', '39'),\n green: wrap('32', '39'),\n yellow: wrap('33', '39'),\n blue: wrap('34', '39'),\n magenta: wrap('35', '39'),\n cyan: wrap('36', '39'),\n gray: wrap('90', '39'),\n amber: wrap('38;5;214', '39'),\n pink: wrap('38;5;205', '39'),\n bgRed: wrap('41', '49'),\n bgGreen: wrap('42', '49'),\n};\n\nexport function stripAnsi(s: string): string {\n return s.replace(/\\x1b\\[[0-9;]*[A-Za-z]/g, '');\n}\n","/**\n * Deep merge utility — safely merges nested objects with configurable\n * conflict resolution, array merging, and prototype-pollution guarding.\n *\n * Used by:\n * - config-loader (config layer merging with primitive-array concatenation)\n * - secret-vault (config patching)\n * - json-path (json_merge tool with prefer-base / prefer-patch semantics)\n *\n * @module utils/deep-merge\n */\n\n// ---------------------------------------------------------------------------\n// Prototype-pollution guard — shared set of forbidden __proto__ keys\n// ---------------------------------------------------------------------------\n\nexport const FORBIDDEN_PROTO_KEYS = new Set([\n '__proto__',\n 'constructor',\n 'prototype',\n '__defineGetter__',\n '__defineSetter__',\n '__lookupGetter__',\n '__lookupSetter__',\n]);\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** True when every element is a primitive or null (no nested objects/arrays). */\nexport function isPrimitiveArray(a: unknown[]): boolean {\n return a.every((v) => v === null || (typeof v !== 'object' && typeof v !== 'function'));\n}\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface DeepMergeOptions {\n /**\n * Which side wins on collision for scalars and arrays.\n *\n * - `'prefer-patch'` (default): patch value replaces base value.\n * - `'prefer-base'`: base value is kept, patch value is ignored.\n */\n conflictResolution?: 'prefer-base' | 'prefer-patch';\n\n /**\n * How to handle array values.\n *\n * - `'replace'` (default): patch array replaces base array entirely.\n * - `'concat-primitives'`: when both values are primitive arrays,\n * they are concatenated and deduped (via Set). Non-primitive\n * arrays still replace the base wholesale.\n */\n arrayMode?: 'replace' | 'concat-primitives';\n\n /**\n * Skip prototype-pollution keys (`__proto__`, `constructor`, etc.).\n * Enabled by default. Only disable when you control both inputs\n * and the keyset (e.g. when merging trusted JSON schemas).\n */\n protectProto?: boolean;\n\n /**\n * Optional callback fired when a non-primitive (object) array is\n * replaced wholesale (only relevant with `arrayMode: 'concat-primitives'`).\n * Receives the key name, existing array length, and patch array length.\n * Used by config-loader for debug logging.\n */\n onNonPrimitiveArrayReplace?: (\n key: string,\n existingLen: number,\n patchLen: number,\n ) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\n/**\n * Recursively merge `patch` into `base`, returning a new object.\n *\n * - Nested plain objects are merged recursively.\n * - Arrays are handled per `options.arrayMode`.\n * - Scalar collisions are resolved per `options.conflictResolution`.\n * - `null` and non-object values in `patch` replace the base value\n * (unless `conflictResolution` is `'prefer-base'`).\n * - Keys in `base` that are absent from `patch` are preserved.\n * - `FORBIDDEN_PROTO_KEYS` are skipped in the patch (unless\n * `options.protectProto` is set to `false`).\n *\n * The function is generic over `T extends Record<string, unknown>` for\n * callers that pass typed config objects, but the runtime signature\n * also accepts `unknown` inputs (used by the json-path plugin).\n */\nexport function deepMerge<T extends Record<string, unknown>>(\n base: T,\n patch: Record<string, unknown>,\n options?: DeepMergeOptions,\n): T;\n\nexport function deepMerge(\n base: unknown,\n patch: unknown,\n options?: DeepMergeOptions,\n): unknown;\n\nexport function deepMerge(\n base: unknown,\n patch: unknown,\n options: DeepMergeOptions = {},\n): unknown {\n const {\n conflictResolution = 'prefer-patch',\n arrayMode = 'replace',\n protectProto = true,\n onNonPrimitiveArrayReplace,\n } = options;\n\n // Non-object / null handling — delegate to conflict resolution.\n if (typeof base !== 'object' || base === null) {\n return conflictResolution === 'prefer-patch' ? patch : base;\n }\n if (typeof patch !== 'object' || patch === null) {\n return conflictResolution === 'prefer-patch' ? patch : base;\n }\n\n // Arrays — handled *before* the object merge so array-of-objects\n // aren't accidentally treated as plain records.\n if (Array.isArray(base) && Array.isArray(patch)) {\n if (\n arrayMode === 'concat-primitives' &&\n isPrimitiveArray(base) &&\n isPrimitiveArray(patch)\n ) {\n return [...new Set([...base, ...patch])];\n }\n return conflictResolution === 'prefer-patch' ? patch : base;\n }\n\n // If only one side is an array, treat as scalar collision.\n if (Array.isArray(base) || Array.isArray(patch)) {\n return conflictResolution === 'prefer-patch' ? patch : base;\n }\n\n // Plain object merge.\n const baseObj = base as Record<string, unknown>;\n const patchObj = patch as Record<string, unknown>;\n const out: Record<string, unknown> = { ...baseObj };\n\n for (const [k, v] of Object.entries(patchObj)) {\n if (protectProto && FORBIDDEN_PROTO_KEYS.has(k)) continue;\n\n const existing = out[k];\n if (\n v !== null &&\n typeof v === 'object' &&\n !Array.isArray(v) &&\n existing !== null &&\n typeof existing === 'object' &&\n !Array.isArray(existing)\n ) {\n // Recursive merge for nested plain objects.\n out[k] = deepMerge(existing, v, options);\n } else if (Array.isArray(v) && Array.isArray(existing)) {\n // Delegate to top-level array handling so arrayMode\n // (e.g. 'concat-primitives') applies to nested arrays too.\n // Fire debug hook when a non-primitive array replaces an existing\n // array (for non-primitive arrays, concat-primitives is a no-op and\n // the result is always a wholesale replacement).\n if (onNonPrimitiveArrayReplace && !isPrimitiveArray(v)) {\n onNonPrimitiveArrayReplace(k, existing.length, v.length);\n }\n out[k] = deepMerge(existing, v, options);\n } else if (v !== undefined) {\n // Fire debug hook when a non-primitive (object) array replaces an\n // existing value in concat-primitives mode.\n if (\n onNonPrimitiveArrayReplace &&\n Array.isArray(v) &&\n !isPrimitiveArray(v)\n ) {\n const existingLen = Array.isArray(existing) ? existing.length : 0;\n onNonPrimitiveArrayReplace(k, existingLen, v.length);\n }\n out[k] = v;\n }\n // When v === undefined, leave the existing value untouched\n // (this matches config-loader's behaviour: undefined in patch\n // means \"don't change this key\").\n }\n\n return out;\n}\n","/**\n * Converts an unknown error value to a human-readable string.\n * Used in 40+ files across the codebase to normalize error messaging.\n */\nexport function toErrorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n","/**\n * Compile a user-supplied regex with conservative bounds against ReDoS.\n *\n * Duplicated from @wrongstack/tools/_regex.ts to avoid a circular\n * dependency (tools depends on core, not vice versa). Keep both copies\n * in sync if the heuristics change.\n *\n * V8's regex engine is backtracking-based and cannot interrupt a\n * synchronous match — a pattern like `(a+)+$` against a sufficiently\n * long line will pin a worker for seconds.\n */\n\nconst MAX_PATTERN_LEN = 512;\n\n// Heuristics for catastrophic-backtracking constructs.\nconst DANGEROUS_PATTERNS: ReadonlyArray<RegExp> = [\n /(\\([^)]*[+*][^)]*\\))[+*]/, // (a+)+, (.*)+, etc\n /(\\(\\?:[^)]*[+*][^)]*\\))[+*]/, // same, with non-capturing group\n];\n\nexport interface CompileResult {\n ok: true;\n regex: RegExp;\n}\n\nexport interface CompileFail {\n ok: false;\n reason: string;\n}\n\nexport function compileUserRegex(pattern: string, flags: string): CompileResult | CompileFail {\n if (typeof pattern !== 'string') {\n return { ok: false, reason: 'pattern must be a string' };\n }\n if (pattern.length === 0) {\n return { ok: false, reason: 'pattern is empty' };\n }\n if (pattern.length > MAX_PATTERN_LEN) {\n return { ok: false, reason: `pattern exceeds ${MAX_PATTERN_LEN} characters` };\n }\n for (const rx of DANGEROUS_PATTERNS) {\n if (rx.test(pattern)) {\n return {\n ok: false,\n reason:\n 'pattern looks vulnerable to catastrophic backtracking — rewrite without nested quantifiers',\n };\n }\n }\n try {\n return { ok: true, regex: new RegExp(pattern, flags) };\n } catch (err) {\n return {\n ok: false,\n reason: err instanceof Error ? err.message : 'invalid regex',\n };\n }\n}\n","import { toErrorMessage } from './error.js';\n\nexport interface SafeParseResult<T> {\n ok: boolean;\n value?: T | undefined;\n error?: string | undefined;\n}\n\nexport function safeParse<T = unknown>(input: string, maxBytes = 5_000_000): SafeParseResult<T> {\n if (input.length > maxBytes) {\n return { ok: false, error: `Input exceeds limit (${maxBytes} bytes)` };\n }\n try {\n return { ok: true, value: JSON.parse(input) as T };\n } catch (err) {\n return {\n ok: false,\n error: toErrorMessage(err),\n };\n }\n}\n\nexport function safeStringify(value: unknown, pretty = false): string {\n const seen = new WeakSet();\n const replacer = (_k: string, v: unknown): unknown => {\n if (typeof v === 'bigint') return v.toString();\n if (v instanceof Error) {\n return { name: v.name, message: v.message, stack: v.stack };\n }\n if (typeof v === 'object' && v !== null) {\n if (seen.has(v as object)) return '[Circular]';\n seen.add(v as object);\n }\n return v;\n };\n try {\n return JSON.stringify(value, replacer, pretty ? 2 : undefined) ?? 'null';\n } catch (err) {\n return JSON.stringify({\n __serialization_error: toErrorMessage(err),\n });\n }\n}\n\n/**\n * Attempt to parse JSON5-style input and return a valid JSON string.\n * Handles trailing commas, single-line comments, and unquoted keys\n * that are common in provider output.\n *\n * Returns the sanitized string if it parses successfully as JSON,\n * or `null` if the input cannot be made valid. Callers use this to\n * decide whether to proceed with the parsed result or fall back to\n * raw handling.\n */\nexport function sanitizeJsonString(s: string): string | null {\n let out = s.trim();\n\n // Stage 1: strip single-line comments (// to end of line) that appear\n // outside of string values. This is a heuristic: comments inside strings\n // are preserved because we only strip // when preceded by a char that\n // strongly suggests we're not in a string (quote count modulo 2 is even).\n out = stripSingleLineComments(out);\n\n // Stage 2: strip trailing commas before } or ]\n out = out.replace(/,(\\s*[}\\]])/g, '$1');\n\n // Stage 3: escape literal control characters that appear *inside* string\n // values. Models frequently emit raw newlines/tabs inside a code payload\n // (e.g. edit's old_string/new_string) instead of the required \\n / \\t, which\n // makes JSON.parse throw. This is the single most common malformed-args case.\n out = escapeControlCharsInStrings(out);\n\n // Stage 4: attempt full parse; return null if it fails so callers can\n // distinguish \"already valid JSON\" from \"unrecoverable\".\n try {\n JSON.parse(out);\n return out;\n } catch {\n return null; // stripped but still not valid JSON; caller handles it\n }\n}\n\n/**\n * Walk the string tracking whether we are inside a JSON string literal and\n * replace raw control characters (U+0000–U+001F) that appear inside strings\n * with their valid JSON escape sequences. Characters outside strings are left\n * untouched (insignificant whitespace stays as-is). Already-escaped sequences\n * are not double-escaped because we only act on *literal* control bytes.\n */\nfunction escapeControlCharsInStrings(s: string): string {\n let inString = false;\n let out = '';\n for (let i = 0; i < s.length; i++) {\n const c = s.charAt(i);\n if (c === '\"' && (i === 0 || s[i - 1] !== '\\\\')) {\n inString = !inString;\n out += c;\n continue;\n }\n const code = c.charCodeAt(0);\n if (inString && code < 0x20) {\n switch (c) {\n case '\\n':\n out += '\\\\n';\n break;\n case '\\r':\n out += '\\\\r';\n break;\n case '\\t':\n out += '\\\\t';\n break;\n case '\\b':\n out += '\\\\b';\n break;\n case '\\f':\n out += '\\\\f';\n break;\n default:\n out += `\\\\u${code.toString(16).padStart(4, '0')}`;\n }\n continue;\n }\n out += c;\n }\n return out;\n}\n\nfunction stripSingleLineComments(s: string): string {\n let inString = false;\n const chars: string[] = [];\n let i = 0;\n while (i < s.length) {\n const c = s.charAt(i);\n if (c === '\"' && (i === 0 || s.charAt(i - 1) !== '\\\\')) {\n inString = !inString;\n chars.push(c);\n } else if (c === '/' && s.charAt(i + 1) === '/' && !inString) {\n // skip to end of line\n while (i < s.length && s.charAt(i) !== '\\n') i++;\n } else {\n chars.push(c);\n }\n i++;\n }\n return chars.join('');\n}\n","/**\n * Turn an arbitrary string into a filesystem- and URL-safe lowercase slug.\n *\n * Collapses every run of non-alphanumeric characters into a single hyphen,\n * trims leading/trailing hyphens, and caps the length. Returns `fallback`\n * when the input slugifies to the empty string.\n *\n * Used as the stable dedup + registry key for prompts. (Distinct from the\n * project-folder slug in `wstack-paths.ts`, which has its own `'project'`\n * fallback and shorter cap.)\n */\nexport function slugify(name: string, fallback = 'prompt', maxLen = 64): string {\n return (\n name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, maxLen)\n .replace(/-+$/g, '') || fallback\n );\n}\n","import { randomBytes } from 'node:crypto';\n\n/**\n * Crockford base32 alphabet (excludes I, L, O, U to avoid ambiguity).\n */\nconst ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';\nconst ENCODING_LEN = ENCODING.length;\nconst TIME_LEN = 10;\nconst RANDOM_LEN = 16;\n\nfunction encodeTime(now: number, len: number): string {\n let mod: number;\n let str = '';\n for (let i = len - 1; i >= 0; i--) {\n mod = now % ENCODING_LEN;\n str = ENCODING[mod] + str;\n now = (now - mod) / ENCODING_LEN;\n }\n return str;\n}\n\nfunction encodeRandom(len: number): string {\n const bytes = randomBytes(len);\n let str = '';\n for (let i = 0; i < len; i++) {\n str += ENCODING[(bytes[i] as number) % ENCODING_LEN];\n }\n return str;\n}\n\n/**\n * Generate a ULID — a 26-char Crockford-base32 identifier whose first 10 chars\n * encode the millisecond timestamp (so IDs sort lexicographically by creation\n * time) followed by 16 chars of randomness. Zero runtime dependencies.\n *\n * The codebase convention is \"IDs are ULIDs\"; use this for any new store key.\n */\nexport function ulid(seedTime: number = Date.now()): string {\n return encodeTime(seedTime, TIME_LEN) + encodeRandom(RANDOM_LEN);\n}\n\n/** True for a well-formed 26-char Crockford-base32 ULID. */\nexport function isUlid(value: string): boolean {\n if (value.length !== TIME_LEN + RANDOM_LEN) return false;\n for (const ch of value) {\n if (!ENCODING.includes(ch)) return false;\n }\n return true;\n}\n","import { createHash } from 'node:crypto';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\n\n/**\n * Path layout. All developer-level state lives in ~/.wrongstack/.\n * Per-project state is keyed by sha256(absoluteProjectRoot).slice(0,12)\n * under ~/.wrongstack/projects/<hash>/.\n *\n * The ONLY thing inside the project tree is the optional\n * .wrongstack/AGENTS.md (committed) and .wrongstack/skills/ (committed).\n */\n\nexport interface WstackPaths {\n /** ~/.wrongstack — global root. */\n globalRoot: string;\n /**\n * ~/.wrongstack — directory for user-global stateful config files\n * (mode.json, theme.json, …). Currently an alias for `globalRoot`;\n * separate name lets us split out per-OS XDG_CONFIG_HOME later\n * without rewriting callers.\n */\n configDir: string;\n /** ~/.wrongstack/config.json */\n globalConfig: string;\n /** ~/.wrongstack/.key — 32 random bytes, mode 0600, AES-GCM key for the secret vault. */\n secretsKey: string;\n /** ~/.wrongstack/memory.md — user-global memory. */\n globalMemory: string;\n /** ~/.wrongstack/skills — user-global skills. */\n globalSkills: string;\n /** ~/.wrongstack/design-kits — user-global Design Studio kits. */\n globalDesignKits: string;\n /** ~/.wrongstack/prompts — user-global prompt library. */\n globalPrompts: string;\n /** ~/.wrongstack/instructions — user-global system instruction overrides. */\n globalInstructions: string;\n /** ~/.wrongstack/prompt-usage.json — per-slug insert counts (recent/popular). */\n promptUsage: string;\n /** ~/.wrongstack/cache — fetched data (models.dev, etc.). */\n cacheDir: string;\n /** ~/.wrongstack/cache/models.dev.json */\n modelsCache: string;\n /** ~/.wrongstack/cache/models-overlay.json — cached curated overlay. */\n modelsOverlayCache: string;\n /**\n * Per-project codebase symbol index (SQLite). Lives under the global project\n * dir — NOT inside the repo — so it never clutters the working tree or needs\n * gitignoring. `~/.wrongstack/projects/<hash>/codebase-index`.\n */\n projectCodebaseIndex: string;\n /** ~/.wrongstack/history — REPL line history. */\n historyFile: string;\n /** ~/.wrongstack/logs/wrongstack.log */\n logFile: string;\n /** ~/.wrongstack/projects/<hash> */\n projectDir: string;\n /** ~/.wrongstack/projects/<hash>/memory.md */\n projectMemory: string;\n /** ~/.wrongstack/projects/<hash>/sessions */\n projectSessions: string;\n /** ~/.wrongstack/projects/<hash>/trust.json */\n projectTrust: string;\n /** ~/.wrongstack/projects/<hash>/meta.json */\n projectMeta: string;\n /** ~/.wrongstack/projects/<hash>/config.local.json — optional override */\n projectLocalConfig: string;\n /** <project>/.wrongstack/config.json — per-project settings (safe fields only).\n * This lives inside the project root so it can be gitignored or shared. */\n inProjectConfig: string;\n /** <project>/.wrongstack/AGENTS.md — committed project memory. */\n inProjectAgentsFile: string;\n /** <project>/.wrongstack/skills — committed project skills. */\n inProjectSkills: string;\n /** <project>/.wrongstack/prompts — committed project prompt library. */\n inProjectPrompts: string;\n /** <project>/.wrongstack/instructions — committed project instruction overrides. */\n inProjectInstructions: string;\n /** <project>/.wrongstack/design-kits — committed project Design Studio kits. */\n inProjectDesignKits: string;\n /** <project>/.wrongstack/worktrees — git worktrees for per-phase isolation (gitignored). */\n inProjectWorktrees: string;\n /** Stable hash for the project root. */\n projectHash: string;\n /** Human-readable project slug: `wrongstack-a1b2c3` instead of `3024e5e6fa58`. */\n projectSlug: string;\n /** ~/.wrongstack/projects/<hash>/goal.json — goal persistence */\n projectGoal: string;\n /** ~/.wrongstack/projects/<hash>/specs — SDD spec files */\n projectSpecs: string;\n /** ~/.wrongstack/projects/<hash>/task-graphs — SDD task graphs */\n projectTaskGraphs: string;\n /** ~/.wrongstack/projects/<hash>/sdd-session.json — SDD session state */\n projectSddSession: string;\n /** ~/.wrongstack/projects/<hash>/plan.json — plan persistence */\n projectPlan: string;\n /** ~/.wrongstack/projects/<hash>/autophase — AutoPhase phase-graph JSON files */\n projectAutophase: string;\n /** ~/.wrongstack/projects/<hash>/sdd-boards — live SDD board snapshots + JSONL event logs */\n projectSddBoards: string;\n /** ~/.wrongstack/sync.json — CloudSync configuration */\n syncConfig: string;\n /** Function to get the status.json path for a project given its hash. */\n projectStatus: (projectHash: string) => string;\n}\n\nexport function projectHash(absRoot: string): string {\n return createHash('sha256').update(path.resolve(absRoot)).digest('hex').slice(0, 12);\n}\n\n/**\n * Human-readable project directory name: slugified folder name + short hash\n * suffix for uniqueness. e.g. `wrongstack-a1b2c3` instead of `3024e5e6fa58`.\n */\nexport function projectSlug(absRoot: string): string {\n const base = slugify(path.basename(absRoot));\n const hash = createHash('sha256').update(path.resolve(absRoot)).digest('hex').slice(0, 6);\n return `${base}-${hash}`;\n}\n\n/** Turn a folder name into a filesystem-safe lowercase slug. */\nfunction slugify(name: string): string {\n return (\n name\n .toLowerCase()\n // Collapse any run of non-alphanumeric chars into a single hyphen.\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 40) || 'project'\n );\n}\n\nexport interface WstackPathOptions {\n userHome?: string | undefined;\n projectRoot: string;\n /** Override the global root (e.g. for tests). Default: `${userHome}/.wrongstack`. */\n globalRoot?: string | undefined;\n}\n\n/**\n * The global `~/.wrongstack` root, honoring the `WRONGSTACK_HOME` env\n * override. The override exists so tests (and sandboxed runs) can redirect\n * ALL global state — config, secrets, logs, projects/, mailboxes — away from\n * the real user home. Before it existed, `pnpm test` booted runtimes against\n * the real `~/.wrongstack`: it read the user's real config.json (starting a\n * second live Telegram poller), appended to the real wrongstack.log, and left\n * ~20k orphaned fixture dirs under projects/.\n *\n * Every code path that wants the global dir must come through here (or\n * through `resolveWstackPaths`) instead of `path.join(os.homedir(), '.wrongstack')`.\n */\nexport function wstackGlobalRoot(): string {\n const fromEnv = process.env['WRONGSTACK_HOME'];\n if (fromEnv && fromEnv.trim().length > 0) return path.resolve(fromEnv);\n return path.join(os.homedir(), '.wrongstack');\n}\n\nexport function resolveWstackPaths(opts: WstackPathOptions): WstackPaths {\n // Precedence: explicit globalRoot > explicit userHome (callers/tests that\n // pass one expect paths under it) > WRONGSTACK_HOME env > real home dir.\n const globalRoot =\n opts.globalRoot ?? (opts.userHome ? path.join(opts.userHome, '.wrongstack') : wstackGlobalRoot());\n const hash = projectHash(opts.projectRoot);\n const slug = projectSlug(opts.projectRoot);\n const projectDir = path.join(globalRoot, 'projects', slug);\n return {\n globalRoot,\n configDir: globalRoot,\n globalConfig: path.join(globalRoot, 'config.json'),\n secretsKey: path.join(globalRoot, '.key'),\n globalMemory: path.join(globalRoot, 'memory.md'),\n globalSkills: path.join(globalRoot, 'skills'),\n globalDesignKits: path.join(globalRoot, 'design-kits'),\n globalPrompts: path.join(globalRoot, 'prompts'),\n globalInstructions: path.join(globalRoot, 'instructions'),\n promptUsage: path.join(globalRoot, 'prompt-usage.json'),\n cacheDir: path.join(globalRoot, 'cache'),\n modelsCache: path.join(globalRoot, 'cache', 'models.dev.json'),\n modelsOverlayCache: path.join(globalRoot, 'cache', 'models-overlay.json'),\n historyFile: path.join(globalRoot, 'history'),\n logFile: path.join(globalRoot, 'logs', 'wrongstack.log'),\n projectDir,\n projectCodebaseIndex: path.join(projectDir, 'codebase-index'),\n projectMemory: path.join(projectDir, 'memory.md'),\n projectSessions: path.join(projectDir, 'sessions'),\n projectTrust: path.join(projectDir, 'trust.json'),\n projectMeta: path.join(projectDir, 'meta.json'),\n projectLocalConfig: path.join(projectDir, 'config.local.json'),\n inProjectConfig: path.join(opts.projectRoot, '.wrongstack', 'config.json'),\n inProjectAgentsFile: path.join(opts.projectRoot, '.wrongstack', 'AGENTS.md'),\n inProjectSkills: path.join(opts.projectRoot, '.wrongstack', 'skills'),\n inProjectPrompts: path.join(opts.projectRoot, '.wrongstack', 'prompts'),\n inProjectInstructions: path.join(opts.projectRoot, '.wrongstack', 'instructions'),\n inProjectDesignKits: path.join(opts.projectRoot, '.wrongstack', 'design-kits'),\n inProjectWorktrees: path.join(opts.projectRoot, '.wrongstack', 'worktrees'),\n projectHash: hash,\n projectSlug: slug,\n projectGoal: path.join(projectDir, 'goal.json'),\n projectSpecs: path.join(projectDir, 'specs'),\n projectTaskGraphs: path.join(projectDir, 'task-graphs'),\n projectSddSession: path.join(projectDir, 'sdd-session.json'),\n projectPlan: path.join(projectDir, 'plan.json'),\n projectAutophase: path.join(projectDir, 'autophase'),\n projectSddBoards: path.join(projectDir, 'sdd-boards'),\n syncConfig: path.join(globalRoot, 'sync.json'),\n projectStatus: (projectHash: string) => path.join(globalRoot, 'projects', projectHash, 'status.json'),\n };\n}\n","import type { ContentBlock } from '../types/blocks.js';\n\n/**\n * Derive a short title from a user_input event's content. Used by both\n * `DefaultSessionStore.summarize()` (offline summary rebuild) and\n * `FileSessionWriter.observeForSummary()` (live tracking), so it lives\n * here to avoid a bidirectional import between those two modules.\n */\nexport function userInputTitle(content: string | ContentBlock[]): string {\n const text =\n typeof content === 'string'\n ? content\n : content\n .filter((b): b is { type: 'text'; text: string } => b.type === 'text')\n .map((b) => b.text)\n .join(' ');\n return (text || '(non-text input)').slice(0, 60);\n}\n","import * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { EventBus } from '../kernel/events.js';\nimport type {\n FileSnapshot,\n SessionEvent,\n SessionMetadata,\n SessionSummary,\n SessionWriter,\n} from '../types/session.js';\nimport type { SecretScrubber } from '../types/secret-scrubber.js';\nimport { atomicWrite } from '../utils/atomic-write.js';\nimport { toErrorMessage } from '../utils/index.js';\nimport { userInputTitle } from './session-helpers.js';\n\n/**\n * Append-mode JSONL session writer with batched writes, write serialization,\n * and enriched summary tracking.\n *\n * Extracted from session-store.ts to keep each module focused: this class\n * owns the per-session write path (append/flush/close/checkpoint/truncate),\n * while `DefaultSessionStore` owns the store-level read/list/index/delete path.\n */\nexport class FileSessionWriter implements SessionWriter {\n private closed = false;\n private closePromise: Promise<void> | null = null;\n private manifestFile: string;\n private summary: SessionSummary;\n private tokenIn = 0;\n private tokenOut = 0;\n private readonly filePath: string;\n get transcriptPath(): string | undefined {\n return this.filePath || undefined;\n }\n /**\n * Lazy session_start/session_resumed init, shared by all appenders.\n * A single promise (not a boolean) so a second append racing the first\n * can't push its event into the buffer BEFORE the first append's event —\n * every appender awaits the same init and resumes in FIFO call order.\n */\n private initPromise: Promise<void> | null = null;\n private ensureInit(): Promise<void> {\n if (!this.initPromise) this.initPromise = this.writeSessionStartLazy();\n return this.initPromise;\n }\n private readonly resumed: boolean;\n private appendFailCount = 0;\n private lastAppendWarnAt = 0;\n private readonly secretScrubber?: SecretScrubber | undefined;\n private readonly onCloseCb?: (((summary: SessionSummary) => void | Promise<void>)) | undefined;\n /** Implements SessionWriter.traceId — propagated from ContextInit.traceId. */\n traceId: string | undefined;\n\n // ── Write buffer — batches events to reduce per-event disk I/O ──────────────\n //\n // Every append() pushes the scrubbed event into an in-memory buffer instead\n // of calling handle.appendFile() synchronously. The buffer flushes to disk\n // when it reaches FLUSH_SIZE events OR after FLUSH_INTERVAL_MS of inactivity.\n // This cuts the number of disk writes by ~95% without changing the on-disk\n // format — the JSONL is still one JSON object per line.\n private writeBuffer: SessionEvent[] = [];\n private flushTimer: ReturnType<typeof setTimeout> | null = null;\n private static readonly FLUSH_INTERVAL_MS = 500;\n private static readonly FLUSH_SIZE = 50;\n\n // ── Write serialization ─────────────────────────────────────────────────────\n //\n // All disk writes are funneled through a FIFO promise chain. Without it,\n // a timer-driven flush racing an explicit flush()/close() issues two\n // concurrent appendFile() calls on the shared O_APPEND handle — the kernel\n // may complete them out of order (chronology breaks) or, for large\n // batches, interleave partial writes (torn JSONL lines). The chain keeps\n // exactly one write in flight; failures don't break the chain.\n private writeChain: Promise<void> = Promise.resolve();\n\n /** Enqueue a write on the FIFO chain. Resolves/rejects with that write. */\n private enqueueWrite(data: string): Promise<void> {\n const write = this.writeChain.then(() => this.handle.appendFile(data, 'utf8'));\n this.writeChain = write.then(\n () => undefined,\n () => undefined,\n );\n return write;\n }\n\n // ── Enriched summary tracking ───────────────────────────────────────────────\n private iterationCount = 0;\n private toolCallCount = 0;\n private toolErrorCount = 0;\n private toolBreakdown: Record<string, number> = {};\n private fileChangeCount = 0;\n private compactionCount = 0;\n private outcome: SessionSummary['outcome'] = undefined;\n\n /**\n * Scrub secrets out of conversation-turn events before they are observed\n * for the summary, written to the JSONL log, or surfaced on resume. Only\n * `user_input` / `llm_response` carry free-form user/model text; other event\n * types either have no secret-bearing content or are already scrubbed\n * upstream (tool results). Returns the event unchanged when no scrubber is\n * configured.\n */\n private scrubEvent(event: SessionEvent): SessionEvent {\n const s = this.secretScrubber;\n if (!s) return event;\n if (event.type === 'user_input') {\n return {\n ...event,\n content:\n typeof event.content === 'string' ? s.scrub(event.content) : s.scrubObject(event.content),\n };\n }\n if (event.type === 'llm_response') {\n return { ...event, content: s.scrubObject(event.content) };\n }\n return event;\n }\n\n private pendingFileSnapshots: Array<{\n path: string;\n action: 'created' | 'modified' | 'deleted';\n before: string | null;\n after: string | null;\n }> = [];\n /** Tracks open tool_use IDs during the current run to serialize on close for resume. */\n private openToolUses = new Set<string>();\n\n recordFileChange(input: {\n path: string;\n action: 'created' | 'modified' | 'deleted';\n before: string | null;\n after: string | null;\n }): void {\n this.pendingFileSnapshots.push(input);\n }\n\n recordSideEffect(input: {\n toolUseId: string;\n toolName: string;\n input: Record<string, unknown>;\n outcome?: string | undefined;\n risk: 'fs.write' | 'shell' | 'package' | 'network' | 'config';\n }): void {\n // Fire-and-forget — side-effect recording must never block tool execution.\n this.append({\n type: 'side_effect',\n ts: new Date().toISOString(),\n toolUseId: input.toolUseId,\n toolName: input.toolName,\n input: input.input,\n outcome: input.outcome,\n risk: input.risk,\n }).catch(() => { /* best-effort */ });\n }\n\n constructor(\n public readonly id: string,\n private handle: fsp.FileHandle,\n private readonly startedAt: string,\n private readonly meta: Omit<SessionMetadata, 'startedAt'>,\n private readonly events?: EventBus | undefined,\n opts: {\n resumed?: boolean | undefined;\n dir?: string | undefined;\n filePath?: string | undefined;\n secretScrubber?: SecretScrubber | undefined;\n /** Called on close() with the finalized summary for index/sidecar writes. */\n onClose?: (((summary: SessionSummary) => void | Promise<void>)) | undefined;\n } = {},\n traceId?: string | undefined,\n ) {\n this.resumed = opts.resumed ?? false;\n // id already contains a date-prefix shard (e.g. \"2026-06-06/17-46-57Z_…\").\n // opts.dir is the shard directory — join with basename so the manifest\n // lives next to the JSONL file instead of creating a double-nested path.\n this.manifestFile = opts.dir ? path.join(opts.dir, `${path.basename(id)}.summary.json`) : '';\n this.filePath = opts.filePath ?? '';\n this.secretScrubber = opts.secretScrubber;\n this.onCloseCb = opts.onClose;\n this.summary = {\n id,\n title: '(empty session)',\n startedAt,\n model: meta.model ?? 'unknown',\n provider: meta.provider ?? 'unknown',\n tokenTotal: 0,\n };\n // Propagated from ContextInit.traceId via SessionWriter.traceId so that\n // storage events carry the run-level trace ID without needing a Context\n // handle in every storage operation.\n this.traceId = traceId;\n }\n\n get pendingToolUses(): string[] {\n return Array.from(this.openToolUses);\n }\n\n private async writeSessionStartLazy(): Promise<void> {\n // Write through the SAME file handle that flushBuffer() uses — avoids\n // cross-fd issues on Windows where a separate fsp.writeFile can contend\n // with the already-open append-mode handle. The handle was opened with\n // O_APPEND so this write lands at the current end-of-file regardless of\n // whether the file is empty or already contains prior session data.\n const record = `${JSON.stringify({\n type: this.resumed ? 'session_resumed' : 'session_start',\n ts: this.startedAt,\n id: this.id,\n model: this.meta.model ?? 'unknown',\n provider: this.meta.provider ?? 'unknown',\n })}\\n`;\n try {\n await this.enqueueWrite(record);\n } catch {\n // best-effort\n }\n }\n\n async append(event: SessionEvent): Promise<void> {\n if (this.closed) return;\n await this.ensureInit();\n // Scrub before observing (the summary title is derived from user_input\n // content) and before buffering, so neither the JSONL nor the sidecar\n // ever holds a cleartext secret.\n const scrubbed = this.scrubEvent(event);\n // observeForSummary MUST run synchronously here — the summary counters\n // (toolCallCount, tokenIn/Out, outcome) drive the .summary.json sidecar\n // and the session index. Deferring observation to flush time would leave\n // the summary stale if close() fires before the next timer tick.\n this.observeForSummary(scrubbed);\n this.writeBuffer.push(scrubbed);\n\n if (this.writeBuffer.length >= FileSessionWriter.FLUSH_SIZE) {\n // Buffer full — flush immediately. Cancel any pending timer so we\n // don't double-flush on the next tick.\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n await this.flushBuffer();\n } else {\n this.scheduleFlush();\n }\n }\n\n async appendBatch(events: SessionEvent[]): Promise<void> {\n if (this.closed || events.length === 0) return;\n await this.ensureInit();\n for (const event of events) {\n const scrubbed = this.scrubEvent(event);\n this.observeForSummary(scrubbed);\n this.writeBuffer.push(scrubbed);\n }\n if (this.writeBuffer.length >= FileSessionWriter.FLUSH_SIZE) {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n await this.flushBuffer();\n } else {\n this.scheduleFlush();\n }\n }\n\n /**\n * Flush buffered events to disk immediately. Critical events\n * (user_input, llm_response) call this so they survive SIGKILL/crash\n * instead of sitting in the in-memory buffer for up to 500ms.\n *\n * Idempotent — cancels any pending timer and writes whatever has\n * accumulated in the buffer. Safe to call even when the buffer\n * is empty (no-op).\n */\n async flush(): Promise<void> {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n await this.flushBuffer();\n }\n\n /** Schedule a deferred flush. No-op if a timer is already pending. */\n private scheduleFlush(): void {\n if (this.flushTimer) return;\n this.flushTimer = setTimeout(() => {\n this.flushTimer = null;\n /* v8 ignore start -- defensive: flushBuffer logs its own errors; this guards the timer callback */\n this.flushBuffer().catch(() => {\n // flushBuffer already logs via the throttled-warning path;\n // this catch prevents an unhandled rejection in the timer callback.\n });\n /* v8 ignore stop */\n }, FileSessionWriter.FLUSH_INTERVAL_MS);\n }\n\n /**\n * Flush all buffered events to disk as a single appendFile call.\n * Errors use the same throttled-warning pattern the old per-event\n * append path used — one warning every 5s with a suppressed count.\n * On failure the buffer is cleared (events are best-effort, same as\n * the old per-event path where a failed write was silently dropped).\n */\n private async flushBuffer(): Promise<void> {\n if (this.writeBuffer.length === 0) return;\n const eventCount = this.writeBuffer.length;\n const batch = this.writeBuffer.map((e) => JSON.stringify(e)).join('\\n') + '\\n';\n this.writeBuffer = [];\n const t0 = Date.now();\n let outcome: 'success' | 'failure' = 'success';\n let errorMsg: string | undefined;\n try {\n await this.enqueueWrite(batch);\n } catch (err) {\n outcome = 'failure';\n errorMsg = toErrorMessage(err);\n this.appendFailCount += eventCount;\n const now = Date.now();\n if (now - this.lastAppendWarnAt > 5000) {\n const suppressed = this.appendFailCount - 1;\n const tail = suppressed > 0 ? ` (+${suppressed} suppressed)` : '';\n console.warn(\n '[session] flush failed:',\n toErrorMessage(err),\n tail,\n );\n this.lastAppendWarnAt = now;\n this.appendFailCount = 0;\n }\n } finally {\n this.events?.emit('storage.write', {\n sessionId: this.id,\n store: 'session',\n filePath: this.filePath,\n operation: 'flush',\n outcome,\n durationMs: Date.now() - t0,\n ...(errorMsg !== undefined ? { error: errorMsg } : {}),\n ...(eventCount !== undefined ? { eventCount } : {}),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n }\n }\n\n private observeForSummary(event: SessionEvent): void {\n // Track open tool uses so we can serialize them on close for resume.\n // The authoritative source is the llm_response content (a core event,\n // always written at every audit level); the legacy 'tool_use' event is\n // kept for alternate writers that still emit it.\n if (event.type === 'llm_response') {\n for (const block of event.content) {\n if (block.type === 'tool_use') this.openToolUses.add(block.id);\n }\n }\n if (event.type === 'tool_use') {\n this.openToolUses.add(event.id);\n } else if (event.type === 'tool_call_start') {\n this.toolCallCount++;\n this.toolBreakdown[event.name] = (this.toolBreakdown[event.name] ?? 0) + 1;\n } else if (event.type === 'tool_result') {\n this.openToolUses.delete(event.id);\n if (event.isError) {\n this.toolErrorCount++;\n this.outcome = 'error';\n }\n } else if (event.type === 'file_snapshot') {\n this.fileChangeCount += event.files.length;\n } else if (event.type === 'compaction') {\n this.compactionCount++;\n }\n // Error events (provider errors, execution errors) mark the session as failed.\n if (event.type === 'error' || event.type === 'provider_error') {\n this.outcome = 'error';\n }\n if (event.type === 'user_input' && this.summary.title === '(empty session)') {\n this.summary = { ...this.summary, title: userInputTitle(event.content) };\n } else if (event.type === 'llm_response') {\n this.tokenIn += event.usage.input;\n this.tokenOut += event.usage.output;\n this.summary = { ...this.summary, tokenTotal: this.tokenIn + this.tokenOut };\n } else if (event.type === 'session_end') {\n const total = event.usage.input + event.usage.output;\n if (total > 0) this.summary = { ...this.summary, tokenTotal: total };\n } else if (event.type === 'in_flight_start') {\n this.iterationCount++;\n }\n }\n\n async close(): Promise<void> {\n // Idempotent AND awaitable: concurrent/repeat callers share the same\n // promise, so nobody proceeds (e.g. to tear down the session directory)\n // while the first close is still flushing.\n if (this.closePromise) return this.closePromise;\n this.closePromise = this.doClose();\n return this.closePromise;\n }\n\n private async doClose(): Promise<void> {\n this.closed = true;\n // Flush any buffered events before finalizing. The summary counters\n // (toolCallCount, tokenIn/Out, outcome) are already up to date because\n // observeForSummary runs synchronously on every append, but the JSONL\n // must have all events on disk before we write the .summary.json sidecar.\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n await this.flushBuffer();\n // Drain any write enqueued outside flushBuffer (e.g. the lazy\n // session_start record) before the handle is closed.\n await this.writeChain;\n // Finalize the summary before writing.\n this.summary = {\n ...this.summary,\n endedAt: new Date().toISOString(),\n iterationCount: this.iterationCount,\n toolCallCount: this.toolCallCount,\n toolErrorCount: this.toolErrorCount,\n fileChangeCount: this.fileChangeCount,\n compactionCount: this.compactionCount > 0 ? this.compactionCount : undefined,\n toolBreakdown:\n { ...this.toolBreakdown },\n outcome: this.outcome ?? 'completed',\n };\n // Emit storage.write for the manifest sidecar.\n if (this.manifestFile) {\n const t0 = Date.now();\n let outcome: 'success' | 'failure' = 'success';\n let errorMsg: string | undefined;\n try {\n await atomicWrite(this.manifestFile, JSON.stringify(this.summary), { mode: 0o600 });\n } catch (err) {\n outcome = 'failure';\n errorMsg = toErrorMessage(err);\n // manifest write is best-effort\n } finally {\n this.events?.emit('storage.write', {\n sessionId: this.id,\n store: 'session',\n filePath: this.manifestFile,\n operation: 'close',\n outcome,\n durationMs: Date.now() - t0,\n ...(errorMsg !== undefined ? { error: errorMsg } : {}),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n }\n }\n // Notify the store so it can update the session index. Await so the\n // index write completes before close() resolves — otherwise the\n // fire-and-forget _index.jsonl append races callers that tear down the\n // session directory right after close() (e.g. ENOTEMPTY on Windows).\n // Emit storage.write here so it carries this.traceId; the actual I/O\n // is delegated to onCloseCb (appendToIndex) which no longer emits.\n const idxT0 = Date.now();\n let idxOutcome: 'success' | 'failure' = 'success';\n let idxError: string | undefined;\n try {\n await this.onCloseCb?.(this.summary);\n /* v8 ignore start -- best-effort: appendToIndex swallows its own errors */\n } catch (err) {\n idxOutcome = 'failure';\n idxError = toErrorMessage(err);\n // best-effort\n } finally {\n /* v8 ignore stop */\n this.events?.emit('storage.write', {\n sessionId: this.summary.id,\n store: 'session',\n filePath: this.filePath,\n operation: 'index_append',\n outcome: idxOutcome,\n durationMs: Date.now() - idxT0,\n ...(idxError !== undefined ? { error: idxError } : {}),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n }\n try {\n await this.handle.close();\n } catch {\n // ignore\n }\n }\n\n async writeCheckpoint(promptIndex: number, promptPreview: string): Promise<void> {\n const fileCount = this.pendingFileSnapshots.length;\n if (fileCount > 0) {\n await this.writeFileSnapshot(promptIndex, [...this.pendingFileSnapshots]);\n this.pendingFileSnapshots = [];\n }\n await this.append({\n type: 'checkpoint',\n ts: new Date().toISOString(),\n promptIndex,\n promptPreview,\n });\n this.events?.emit('checkpoint.written', {\n promptIndex,\n promptPreview,\n ts: new Date().toISOString(),\n fileCount,\n });\n }\n\n async writeFileSnapshot(\n promptIndex: number,\n files: FileSnapshot[],\n ): Promise<void> {\n await this.append({\n type: 'file_snapshot',\n ts: new Date().toISOString(),\n promptIndex,\n files,\n });\n }\n\n /**\n * Truncate the session file to the checkpoint with the given promptIndex,\n * removing all events that follow it. Uses a single-pass byte-offset scan\n * so post-checkpoint content is never read or parsed — O(1) memory instead\n * of O(N) JSON.parse calls over the full file.\n */\n async truncateToCheckpoint(targetPromptIndex: number): Promise<number> {\n /* v8 ignore next -- defensive: filePath is always set for a live writer */\n if (!this.filePath) return 0;\n\n // Flush buffered events to disk before reading — otherwise the in-memory\n // events that haven't hit the JSONL yet would be invisible to the\n // truncation logic and would be silently dropped by the rewrite.\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n await this.flushBuffer();\n // Drain the write chain so no in-flight write straddles the close/rename/reopen.\n await this.writeChain;\n\n // Single-pass scan: track byte offset of each line start. Stop as soon as\n // the target checkpoint is found — no I/O or parsing for post-checkpoint data.\n const CHUNK_SIZE = 65_536;\n let fd: fsp.FileHandle | undefined;\n let fileOffset = 0; // cumulative byte position of the start of the current chunk\n let lineStartOffset = 0; // byte offset within the file where the current line begins\n let checkpointByteOffset = -1; // byte offset where we will truncate the file\n let removedCount = 0;\n let targetCheckpointSeen = false; // has the target checkpoint been found yet?\n\n try {\n fd = await fsp.open(this.filePath, 'r', 0o600);\n\n while (true) {\n const buf = Buffer.alloc(CHUNK_SIZE);\n const { bytesRead } = await fd.read(buf, 0, CHUNK_SIZE, fileOffset);\n if (bytesRead === 0) break;\n\n let chunkPos = 0;\n while (chunkPos < bytesRead) {\n const idx = buf.indexOf('\\n', chunkPos);\n if (idx === -1) {\n // No complete line in this chunk — save partial for next iteration.\n lineStartOffset = fileOffset + chunkPos;\n break;\n }\n\n if (checkpointByteOffset !== -1) {\n // Target already found — every subsequent line is removed.\n removedCount++;\n } else {\n // Only parse lines that could precede or be the checkpoint.\n const lineBytes = buf.subarray(chunkPos, idx);\n // eslint-disable-next-line no-sync\n const line = new TextDecoder('utf-8', { fatal: false }).decode(lineBytes);\n if (line.trim()) {\n try {\n const event = JSON.parse(line) as { type?: string; promptIndex?: number };\n if (event.type === 'checkpoint') {\n if (event.promptIndex === targetPromptIndex) {\n // Target found — record its byte offset and stop scanning.\n checkpointByteOffset = lineStartOffset;\n targetCheckpointSeen = true;\n } else if (event.promptIndex !== undefined && event.promptIndex > targetPromptIndex) {\n // A checkpoint with a higher promptIndex means the target is absent.\n // Truncate before this line (exclusive) — it and all following events\n // will be replaced by the new rewinded history.\n checkpointByteOffset = lineStartOffset;\n }\n } else if (targetCheckpointSeen && event.promptIndex !== undefined && event.promptIndex > targetPromptIndex) {\n // Post-target event with a later promptIndex — count as removed.\n removedCount++;\n } else if (targetCheckpointSeen && event.promptIndex === undefined) {\n // After the target checkpoint was found: remove events with no\n // promptIndex. (In the original this is the afterTarget &&\n // targetCheckpointLine !== -1 branch.)\n removedCount++;\n } else if (!targetCheckpointSeen && event.promptIndex === undefined) {\n // Past a higher checkpoint but the target checkpoint not yet found.\n // Matches original: remove events with undefined promptIndex\n // (malformed lines, file_snapshots, etc.) that appear after a\n // higher checkpoint but before the target.\n removedCount++;\n } else if (!targetCheckpointSeen && event.promptIndex !== undefined && event.promptIndex > targetPromptIndex) {\n // Past a higher checkpoint but the target not yet found.\n // Matches original: remove events with promptIndex > target that\n // appear before the target checkpoint (e.g. user_inputs belonging\n // to a later prompt).\n removedCount++;\n }\n // Events with promptIndex <= targetPromptIndex (before the target is\n // found) are implicitly kept — no action needed.\n } catch {\n // Malformed JSON — matches original: keep it.\n }\n }\n }\n\n // Move to start of next line.\n chunkPos = idx + 1;\n lineStartOffset = fileOffset + chunkPos;\n }\n\n fileOffset += bytesRead;\n if (chunkPos >= bytesRead) {\n // Finished all complete lines; prepare for next chunk.\n lineStartOffset = fileOffset;\n }\n }\n } finally {\n await fd?.close();\n }\n\n if (checkpointByteOffset === -1) return 0;\n\n // Windows EPERM fix: close the append-mode handle before replacing the\n // file. Windows rejects rename() when the destination still has an open\n // handle, even if that handle belongs to this process.\n await this.writeChain;\n await this.handle.close();\n const tmpPath = `${this.filePath}.rewind.tmp`;\n const src = await fsp.open(this.filePath, 'r', 0o600);\n try {\n const statResult = await src.stat();\n const totalSize = statResult.size;\n // checkpointByteOffset points to the start of the checkpoint line.\n // We want to keep everything up to and including that line's '\\n'.\n // Since the file ends with '\\n', keeping bytes [0 .. lineStartAfterCheckpoint]\n // means we include the trailing newline. We find that '\\n' by scanning\n // from checkpointByteOffset forward (at most one chunk's worth).\n const prefixBytes = checkpointByteOffset;\n let newlineAfterCheckpoint = prefixBytes;\n\n if (prefixBytes < totalSize) {\n const probeBuf = Buffer.alloc(Math.min(CHUNK_SIZE, totalSize - prefixBytes));\n const { bytesRead: probeRead } = await src.read(probeBuf, 0, probeBuf.length, prefixBytes);\n if (probeRead > 0) {\n const nl = probeBuf.indexOf('\\n');\n newlineAfterCheckpoint = nl !== -1 ? prefixBytes + nl + 1 : totalSize;\n }\n } else {\n newlineAfterCheckpoint = totalSize;\n }\n\n const writeFd = await fsp.open(tmpPath, 'w', 0o600);\n try {\n let readOffset = 0;\n while (readOffset < newlineAfterCheckpoint) {\n const toCopy = Math.min(CHUNK_SIZE, newlineAfterCheckpoint - readOffset);\n const copyBuf = Buffer.alloc(toCopy);\n const { bytesRead: r } = await src.read(copyBuf, 0, toCopy, readOffset);\n if (r === 0) break;\n await writeFd.write(copyBuf, 0, r);\n readOffset += r;\n }\n\n // Preserve malformed JSONL records even after the rewind target. They\n // are not replayable session events, but keeping them avoids silently\n // deleting diagnostic/corruption evidence during a truncate.\n // Stream the tail from the already-open src handle instead of\n // re-reading the entire file — the prefix was already streamed above,\n // so reading via readFile() would duplicate all of that I/O.\n let tailOffset = newlineAfterCheckpoint;\n let leftover = '';\n while (tailOffset < totalSize) {\n const toRead = Math.min(CHUNK_SIZE, totalSize - tailOffset);\n const tailBuf = Buffer.alloc(toRead);\n const { bytesRead: tr } = await src.read(tailBuf, 0, toRead, tailOffset);\n if (tr === 0) break;\n const chunk = leftover + tailBuf.subarray(0, tr).toString('utf8');\n const lastNl = chunk.lastIndexOf('\\n');\n if (lastNl === -1) {\n // No complete line in this chunk — accumulate into leftover.\n leftover = chunk;\n } else {\n for (const line of chunk.slice(0, lastNl + 1).split('\\n')) {\n if (!line.trim()) continue;\n try {\n JSON.parse(line);\n } catch {\n await writeFd.write(`${line}\\n`, undefined, 'utf8');\n }\n }\n leftover = chunk.slice(lastNl + 1);\n }\n tailOffset += tr;\n }\n // Flush trailing partial line (file may not end with \\n).\n if (leftover.trim()) {\n try {\n JSON.parse(leftover);\n } catch {\n await writeFd.write(`${leftover}\\n`, undefined, 'utf8');\n }\n }\n } finally {\n await writeFd.close();\n }\n\n await src.close();\n await fsp.rename(tmpPath, this.filePath);\n // Re-open in append mode for continued use of this file.\n this.handle = await fsp.open(this.filePath, 'a', 0o600);\n /* v8 ignore start -- defensive: close/rename/reopen of a just-written temp file */\n } catch (err) {\n await fsp.unlink(tmpPath).catch(() => undefined);\n this.handle = await fsp.open(this.filePath, 'a', 0o600).catch(() => this.handle);\n throw err;\n }\n /* v8 ignore stop */\n\n await this.append({\n type: 'rewound',\n ts: new Date().toISOString(),\n toPromptIndex: targetPromptIndex,\n revertedFiles: [],\n });\n\n this.events?.emit('session.rewound', {\n toPromptIndex: targetPromptIndex,\n revertedFiles: [],\n removedEvents: removedCount,\n });\n\n return removedCount;\n }\n\n async clearSession(): Promise<void> {\n /* v8 ignore next -- defensive: filePath is always set for a live writer */\n if (!this.filePath) return;\n // Discard any buffered events — the caller is explicitly resetting the\n // session to a clean slate. Cancel the timer so it doesn't fire and\n // append stale events to the freshly-cleared file.\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n this.writeBuffer = [];\n // Let any in-flight append land first — otherwise it would re-append\n // stale events AFTER the reset record below.\n await this.writeChain;\n const record = `${JSON.stringify({\n type: 'session_start',\n ts: new Date().toISOString(),\n id: this.id,\n model: this.meta.model ?? 'unknown',\n provider: this.meta.provider ?? 'unknown',\n })}\\n`;\n await fsp.writeFile(this.filePath, record, 'utf8');\n }\n\n /**\n * Write an in-flight marker. The agent loop should call\n * this at the start of each long-running operation; a matching\n * `clearInFlightMarker` follows on clean exit. A stale marker\n * (no end) is what `SessionRecovery.detectStale` looks for.\n */\n async writeInFlightMarker(context: string): Promise<void> {\n if (!context || context.length > 500) {\n throw new Error('In-flight context must be 1..500 chars');\n }\n await this.append({\n type: 'in_flight_start',\n ts: new Date().toISOString(),\n context,\n });\n this.events?.emit('in_flight.started', { context, ts: new Date().toISOString() });\n }\n\n /**\n * Close the in-flight marker. Idempotent in spirit\n * (you can call it after a successful iteration even if you\n * didn't open one this round) — but the session log records\n * every call so postmortem tooling can see \"the agent finished\n * cleanly X times, then died without finishing Y\".\n */\n async clearInFlightMarker(reason: 'clean' | 'aborted' | 'recovered'): Promise<void> {\n await this.append({\n type: 'in_flight_end',\n ts: new Date().toISOString(),\n reason,\n });\n this.events?.emit('in_flight.ended', { reason, ts: new Date().toISOString() });\n }\n}\n","/**\n * Session ID generation — extracted from session-store.ts.\n *\n * Pure functions: no I/O, no class state, no side effects.\n * Safe to unit-test in isolation.\n */\nimport { randomBytes } from 'node:crypto';\n\n/** Sanitize a model name for use in filenames: alphanumeric + dash + underscore. */\nexport function sanitizeModel(model: string): string {\n return model\n .replace(/[^a-zA-Z0-9_-]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n .slice(0, 40);\n}\n\n/**\n * Generate a session ID in the format:\n * `YYYY-MM-DD/HH-MM-SSZ[_model]_xxxx.jsonl`\n *\n * Examples:\n * `2026-06-06/12-30-45Z_claude-sonnet_a1b2.jsonl`\n * `2026-06-06/14-22-10Z_a1b2.jsonl` (no model)\n *\n * The date prefix becomes a subdirectory so sessions group naturally by day.\n * The model name (when available) lets you see at a glance which provider was\n * used, without opening the file. The 4-byte random suffix prevents collisions\n * within the same second.\n */\nexport function generateSessionId(startedAt: string, model?: string): string {\n const date = startedAt.slice(0, 10); // \"2026-06-06\"\n const time = startedAt.slice(11, 19).replace(/:/g, '-'); // \"12-30-45\"\n const suffix = randomBytes(2).toString('hex'); // \"a1b2\"\n const modelPart = model ? `_${sanitizeModel(model)}` : '';\n return `${date}/${time}Z${modelPart}_${suffix}`;\n}\n","import type { SessionSummary } from '../types/session.js';\n\nexport interface SessionFilterCriteria {\n since?: string | undefined;\n until?: string | undefined;\n provider?: string | undefined;\n model?: string | undefined;\n minTokens?: number | undefined;\n titleContains?: string | undefined;\n}\n\nexport function compareSessionSummaries(a: SessionSummary, b: SessionSummary): number {\n if (a.startedAt < b.startedAt) return 1;\n if (a.startedAt > b.startedAt) return -1;\n return a.id.localeCompare(b.id);\n}\n\nexport function matchesSessionFilter(summary: SessionSummary, criteria: SessionFilterCriteria): boolean {\n if (criteria.since && summary.startedAt < criteria.since) return false;\n if (criteria.until && summary.startedAt > criteria.until) return false;\n if (criteria.provider && summary.provider !== criteria.provider) return false;\n if (criteria.model && summary.model !== criteria.model) return false;\n if (criteria.minTokens !== undefined && summary.tokenTotal < criteria.minTokens) return false;\n if (criteria.titleContains) {\n const needle = criteria.titleContains.toLocaleLowerCase();\n if (!summary.title.toLocaleLowerCase().includes(needle)) return false;\n }\n return true;\n}\n","import type { SessionData, SessionEvent } from '../types/session.js';\n\ntype ToolCallEnd = SessionData['toolCallEnds'][number];\n\nexport function extractToolCallEnds(events: readonly SessionEvent[]): ToolCallEnd[] {\n const out: ToolCallEnd[] = [];\n for (const event of events) {\n if (event.type !== 'tool_call_end') continue;\n out.push({\n name: event.name,\n id: event.id,\n durationMs: event.durationMs,\n ok: event.ok ?? true,\n outputBytes: event.outputBytes ?? event.outputSize,\n outputTokens: event.outputTokens,\n outputLines: event.outputLines,\n });\n }\n return out;\n}\n","export async function mapWithConcurrency<T, R>(\n items: readonly T[],\n concurrency: number,\n mapper: (item: T, index: number) => Promise<R>,\n): Promise<R[]> {\n if (items.length === 0) return [];\n const limit = Math.max(1, Math.floor(concurrency));\n const results = new Array<R>(items.length);\n let next = 0;\n\n async function worker(): Promise<void> {\n while (true) {\n const index = next;\n next++;\n if (index >= items.length) return;\n results[index] = await mapper(items[index] as T, index);\n }\n }\n\n const workers = Array.from({ length: Math.min(limit, items.length) }, () => worker());\n await Promise.all(workers);\n return results;\n}\n","import { createReadStream, type Dirent } from 'node:fs';\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { createInterface } from 'node:readline';\nimport type { EventBus } from '../kernel/events.js';\nimport type { ContentBlock } from '../types/blocks.js';\nimport type { Message } from '../types/messages.js';\nimport type { SecretScrubber } from '../types/secret-scrubber.js';\nimport type {\n ResumedSession,\n SessionData,\n SessionEvent,\n SessionMetadata,\n SessionStore,\n SessionSummary,\n SessionWriter,\n} from '../types/session.js';\nimport { atomicWrite, ensureDir } from '../utils/atomic-write.js';\nimport { repairToolUseAdjacency } from '../utils/message-invariants.js';\nimport { toErrorMessage } from '../utils/index.js';\nimport { FileSessionWriter } from './file-session-writer.js';\nimport { userInputTitle } from './session-helpers.js';\nimport { generateSessionId } from './session-id.js';\nimport { compareSessionSummaries, matchesSessionFilter } from './session-summary.js';\nimport { extractToolCallEnds } from './session-tool-call-ends.js';\nimport { mapWithConcurrency } from './storage-concurrency.js';\n\nexport interface SessionStoreOptions {\n dir: string;\n /** Optional EventBus for emitting session diagnostics. */\n events?: EventBus | undefined;\n /**\n * Optional secret scrubber. When set, `user_input` and `llm_response` event\n * content is scrubbed before being persisted to the JSONL log and the\n * summary sidecar — so a secret a user pastes or the model echoes does not\n * sit in cleartext on disk (and does not ride along in history cloud-sync).\n * Tool output is already scrubbed upstream by the executor; this closes the\n * conversation-turn gap (finding F-06).\n */\n secretScrubber?: SecretScrubber | undefined;\n}\n\n/**\n * Cache entry for load() — stores the parsed SessionData along with the\n * file's mtimeMs and size at the time of loading. On subsequent calls,\n * if the file's mtimeMs+size match, we return the cached data without\n * re-reading or re-parsing the JSONL.\n */\ninterface LoadCacheEntry {\n mtimeMs: number;\n size: number;\n data: SessionData;\n}\n\ninterface IndexCacheEntry {\n mtimeMs: number;\n size: number;\n summaries: SessionSummary[];\n}\n\ninterface SessionFileRef {\n id: string;\n filePath: string;\n}\n\ninterface DirectorySummaryCandidate {\n summary: SessionSummary;\n needsBackfill: boolean;\n}\n\ninterface ShardManifestEntry {\n summaries: SessionSummary[];\n ids: string[];\n}\n\nexport class DefaultSessionStore implements SessionStore {\n private readonly dir: string;\n private readonly events?: EventBus | undefined;\n private readonly secretScrubber?: SecretScrubber | undefined;\n\n /**\n * In-memory cache for load() results, keyed by session ID. The cache is\n * invalidated when the file's mtimeMs or size changes (indicating the\n * file was written to). This eliminates redundant full-file reads and\n * JSON parses when the same session is loaded multiple times within the\n * store's lifetime (e.g., webui session detail views, list() fallbacks).\n *\n * Max size is capped to prevent unbounded memory growth in long-running\n * processes. When the limit is reached, the oldest entry is evicted.\n */\n private readonly _loadCache = new Map<string, LoadCacheEntry>();\n private _indexCache: IndexCacheEntry | null = null;\n private readonly shardManifestCache = new Map<string, ShardManifestEntry>();\n private static readonly LOAD_CACHE_MAX_ENTRIES = 50;\n private static readonly LIST_SCAN_CONCURRENCY = 32;\n\n constructor(opts: SessionStoreOptions) {\n this.dir = opts.dir;\n this.events = opts.events;\n this.secretScrubber = opts.secretScrubber;\n }\n\n /**\n * Clear the load() cache. Useful for testing or when the caller knows\n * the file has changed externally (e.g., another process wrote to it).\n */\n clearLoadCache(sessionId?: string): void {\n if (sessionId !== undefined) {\n this._loadCache.delete(sessionId);\n } else {\n this._loadCache.clear();\n }\n }\n\n // ── Storage event helpers ───────────────────────────────────────────────────\n\n private emitRead(\n sessionId: string,\n filePath: string,\n operation: 'load' | 'list' | 'summary' | 'index_read',\n outcome: 'success' | 'failure',\n durationMs: number,\n error?: string,\n ): void {\n this.events?.emit('storage.read', {\n sessionId,\n store: 'session',\n filePath,\n operation,\n outcome,\n durationMs,\n ...(error !== undefined ? { error } : {}),\n });\n }\n\n private emitWrite(\n sessionId: string,\n filePath: string,\n operation: 'create' | 'resume' | 'append' | 'flush' | 'close' | 'index_append' | 'compact' | 'checkpoint',\n outcome: 'success' | 'failure',\n durationMs: number,\n eventCount?: number,\n error?: string,\n ): void {\n this.events?.emit('storage.write', {\n sessionId,\n store: 'session',\n filePath,\n operation,\n outcome,\n durationMs,\n ...(eventCount !== undefined ? { eventCount } : {}),\n ...(error !== undefined ? { error } : {}),\n });\n }\n\n private emitError(\n sessionId: string,\n filePath: string,\n operation: string,\n error: string,\n recoverable: boolean,\n ): void {\n this.events?.emit('storage.error', {\n sessionId,\n store: 'session',\n filePath,\n operation,\n error,\n recoverable,\n });\n }\n\n /** Absolute path to the session index file. */\n private get indexFile(): string {\n return path.join(this.dir, '_index.jsonl');\n }\n\n /** Join session ID to its absolute path within the store directory. */\n private sessionPath(id: string, ext: '.jsonl' | '.summary.json'): string {\n return path.join(this.dir, `${id}${ext}`);\n }\n\n private shardManifestPath(shardKey: string): string {\n return shardKey ? path.join(this.dir, shardKey, '_manifest.json') : path.join(this.dir, '_manifest.json');\n }\n\n private shardKeyForSessionId(id: string): string {\n const dirName = path.dirname(id);\n return dirName === '.' ? '' : dirName;\n }\n\n private invalidateShardManifestBySessionId(id: string): void {\n this.shardManifestCache.delete(this.shardKeyForSessionId(id));\n }\n\n /**\n * Ensure the directory implied by the session ID exists. When the ID\n * contains a date prefix like `2026-06-06/...`, this creates the date\n * subdirectory so sessions group naturally by day.\n */\n private async ensureShardDir(id: string): Promise<string> {\n const dirPath = path.dirname(path.join(this.dir, id));\n await ensureDir(dirPath);\n return dirPath;\n }\n\n async create(meta: Omit<SessionMetadata, 'startedAt'>): Promise<SessionWriter> {\n const startedAt = new Date().toISOString();\n const id =\n meta.id && meta.id.length > 0\n ? meta.id\n : generateSessionId(startedAt, meta.model ?? meta.provider);\n const shardDir = await this.ensureShardDir(id);\n const file = path.join(shardDir, `${path.basename(id)}.jsonl`);\n const t0 = Date.now();\n let handle: fsp.FileHandle;\n try {\n handle = await fsp.open(file, 'a', 0o600);\n } catch (err) {\n this.emitError(id, file, 'create', toErrorMessage(err), false);\n throw new Error(\n `Failed to open session file: ${toErrorMessage(err)}`,\n { cause: err },\n );\n }\n try {\n const writer = new FileSessionWriter(id, handle, startedAt, meta, this.events, {\n dir: shardDir,\n filePath: file,\n secretScrubber: this.secretScrubber,\n onClose: (s) => this.appendToIndex(s),\n });\n this.emitWrite(id, file, 'create', 'success', Date.now() - t0);\n return writer;\n /* v8 ignore start -- defensive: FileSessionWriter ctor does not throw in practice */\n } catch (err) {\n await handle.close().catch((e) => console.warn(JSON.stringify({\n level: 'warn',\n event: 'session_store.handle_close_failed',\n message: e instanceof Error ? e.message : String(e),\n timestamp: new Date().toISOString(),\n })));\n this.emitError(id, file, 'create', toErrorMessage(err), true);\n throw err;\n }\n /* v8 ignore stop */\n }\n\n async resume(id: string): Promise<ResumedSession> {\n const file = this.sessionPath(id, '.jsonl');\n const t0 = Date.now();\n const data = await this.load(id);\n let handle: fsp.FileHandle;\n try {\n handle = await fsp.open(file, 'a', 0o600);\n /* v8 ignore start -- defensive: load() above already validated the file is readable */\n } catch (err) {\n this.emitError(id, file, 'resume', toErrorMessage(err), false);\n throw new Error(\n `Failed to open session \"${id}\" for append: ${toErrorMessage(err)}`,\n { cause: err },\n );\n }\n /* v8 ignore stop */\n try {\n const writer = new FileSessionWriter(\n id,\n handle,\n new Date().toISOString(),\n {\n id,\n model: data.metadata.model,\n provider: data.metadata.provider,\n },\n this.events,\n {\n resumed: true,\n // Shard directory (sessions/<date>/) — must match create() so the\n // .summary.json sidecar lands next to the JSONL instead of the\n // sessions root (where summaryFor() would never find it).\n dir: path.dirname(file),\n filePath: file,\n secretScrubber: this.secretScrubber,\n onClose: (s) => this.appendToIndex(s),\n },\n );\n this.emitWrite(id, file, 'resume', 'success', Date.now() - t0);\n return { writer, data };\n /* v8 ignore start -- defensive: FileSessionWriter ctor does not throw in practice */\n } catch (err) {\n await handle.close().catch((e) => console.warn(JSON.stringify({\n level: 'warn',\n event: 'session_store.handle_close_failed',\n message: e instanceof Error ? e.message : String(e),\n timestamp: new Date().toISOString(),\n })));\n this.emitError(id, file, 'resume', toErrorMessage(err), true);\n throw err;\n }\n /* v8 ignore stop */\n }\n\n async load(id: string): Promise<SessionData> {\n const file = this.sessionPath(id, '.jsonl');\n const t0 = Date.now();\n let outcome: 'success' | 'failure' = 'success';\n let errorMsg: string | undefined;\n let cacheHit = false;\n try {\n // Stat the file first to check the cache. The stat is cheap (no content\n // read) and lets us skip the full readFile + JSON parse when the file\n // hasn't changed since the last load.\n const s = await fsp.stat(file);\n const stat: { mtimeMs: number; size: number } = { mtimeMs: s.mtimeMs, size: s.size };\n\n // Check cache: if mtimeMs AND size match, the file hasn't changed.\n const cached = this._loadCache.get(id);\n if (cached && cached.mtimeMs === stat.mtimeMs && cached.size === stat.size) {\n cacheHit = true;\n // Update insertion order to prevent frequent-access sessions from being\n // evicted by the LRU eviction logic.\n this._loadCache.delete(id);\n this._loadCache.set(id, cached);\n return cached.data;\n }\n\n // Cache miss — do the full read + parse.\n // Fused single pass: parse events + build messages + extract metadata together.\n const raw = await fsp.readFile(file, 'utf8');\n const lines = raw.split('\\n').filter((l) => l.trim());\n const events: SessionEvent[] = [];\n\n // Metadata extracted in the same single pass over the raw lines.\n let sessionStartEvent: SessionEvent | undefined;\n let sessionEndEvent: SessionEvent | undefined;\n let sessionModel: string | undefined;\n let sessionProvider: string | undefined;\n let sessionPendingToolUses: string[] | undefined;\n\n // Message builder state (equivalent to what replay() maintains).\n const messages: Message[] = [];\n const openToolUses = new Set<string>();\n let usage = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };\n\n for (const line of lines) {\n try {\n const parsed: unknown = JSON.parse(line);\n if (\n parsed !== null &&\n typeof parsed === 'object' &&\n typeof (parsed as { type?: unknown | undefined }).type === 'string' &&\n typeof (parsed as { ts?: unknown | undefined }).ts === 'string'\n ) {\n const ev = parsed as SessionEvent;\n events.push(ev);\n\n // Track metadata in the same pass.\n if (ev.type === 'session_start' && !sessionStartEvent) {\n sessionStartEvent = ev;\n sessionModel = ev.model;\n sessionProvider = ev.provider;\n }\n if (ev.type === 'session_end') {\n sessionEndEvent = ev;\n sessionPendingToolUses = ev.pendingToolUses;\n }\n\n // Build messages in the same pass (replay() logic inlined).\n if (ev.type === 'user_input') {\n openToolUses.clear();\n messages.push({ role: 'user', content: ev.content, ts: ev.ts });\n } else if (ev.type === 'llm_response') {\n messages.push({ role: 'assistant', content: ev.content, ts: ev.ts });\n for (const b of ev.content) {\n if (b.type === 'tool_use') openToolUses.add(b.id);\n }\n usage = {\n input: usage.input + (ev.usage.input ?? 0),\n output: usage.output + (ev.usage.output ?? 0),\n cacheRead: (usage.cacheRead ?? 0) + (ev.usage.cacheRead ?? 0),\n cacheWrite: (usage.cacheWrite ?? 0) + (ev.usage.cacheWrite ?? 0),\n };\n } else if (ev.type === 'tool_result') {\n if (!openToolUses.has(ev.id)) {\n this.events?.emit('session.damaged', {\n sessionId: id,\n detail: `Orphan tool_result \"${ev.id}\" has no matching tool_use`,\n });\n continue;\n }\n openToolUses.delete(ev.id);\n const resultBlock: ContentBlock = {\n type: 'tool_result',\n tool_use_id: ev.id,\n content: typeof ev.content === 'string' ? ev.content : JSON.stringify(ev.content),\n is_error: ev.isError,\n };\n const last = messages[messages.length - 1];\n const lastIsToolResultUser =\n last?.role === 'user' &&\n Array.isArray(last.content) &&\n last.content.every((b) => (b as ContentBlock).type === 'tool_result');\n if (lastIsToolResultUser && Array.isArray(last.content)) {\n last.content.push(resultBlock);\n } else {\n messages.push({ role: 'user', content: [resultBlock], ts: ev.ts });\n }\n }\n }\n } catch {\n // skip malformed JSON\n }\n }\n\n // Repair tool adjacency after the single parse + replay loop.\n if (openToolUses.size > 0) {\n this.events?.emit('session.damaged', {\n sessionId: id,\n detail: `${openToolUses.size} tool_use blocks without matching results - replay repaired`,\n });\n }\n const repaired = repairToolUseAdjacency(messages);\n if (repaired.report.changed) {\n this.events?.emit('session.damaged', {\n sessionId: id,\n detail:\n `Repaired replay adjacency: removed ${repaired.report.removedToolUses.length} tool_use, ` +\n `${repaired.report.removedToolResults.length} tool_result, ` +\n `${repaired.report.removedMessages} empty messages`,\n });\n }\n\n // Build metadata from the extracted session_start/end events.\n const meta: SessionMetadata = {\n id,\n startedAt: sessionStartEvent?.ts ?? new Date(0).toISOString(),\n endedAt: sessionEndEvent?.ts,\n model: sessionModel,\n provider: sessionProvider,\n pendingToolUses: sessionPendingToolUses,\n };\n\n // Extract tool_call_end events for TUI tool entry rendering on resume.\n const toolCallEnds = extractToolCallEnds(events);\n const data: SessionData = { metadata: meta, events, messages: repaired.messages, usage, toolCallEnds };\n\n // Update the cache. Evict oldest entry if at capacity.\n if (this._loadCache.size >= DefaultSessionStore.LOAD_CACHE_MAX_ENTRIES) {\n // Map iteration order is insertion order — delete the first key.\n const oldest = this._loadCache.keys().next().value;\n if (oldest !== undefined) {\n this._loadCache.delete(oldest);\n }\n }\n this._loadCache.set(id, { mtimeMs: stat.mtimeMs, size: stat.size, data });\n\n return data;\n } catch (err) {\n outcome = 'failure';\n errorMsg = toErrorMessage(err);\n throw err;\n } finally {\n this.emitRead(id, file, 'load', outcome, Date.now() - t0, errorMsg);\n if (cacheHit) {\n this.events?.emit('storage.cache_hit', {\n sessionId: id,\n store: 'session',\n filePath: file,\n operation: 'load',\n durationMs: Date.now() - t0,\n });\n }\n }\n }\n\n /**\n * Streaming search over a session's JSONL. Walks the file once, parses\n * each event lazily, and yields only the events that match `predicate`.\n * Stops as soon as `opts.limit` matches are collected.\n *\n * Why this exists: `load()` parses the entire file into memory and\n * rebuilds `messages`/`toolCallEnds` for every caller. `search()` only\n * needs to know which events contain matching text — a per-line\n * predicate is enough. The full parse work (and the `_loadCache` poll)\n * is wasted in that case.\n *\n * Memory: O(hits) regardless of file size. Disk: one linear scan,\n * terminated at `limit` if the caller asked for one.\n *\n * Errors: missing file yields []. Corrupt lines are skipped (same\n * policy as `load()`). Aborting via `signal` rejects with `AbortError`.\n */\n async searchEvents(\n id: string,\n predicate: (event: SessionEvent, eventIndex: number, ts: string) => boolean,\n opts?: { limit?: number | undefined; signal?: AbortSignal | undefined },\n ): Promise<Array<{ event: SessionEvent; eventIndex: number; ts: string }>> {\n const file = this.sessionPath(id, '.jsonl');\n const limit = opts?.limit;\n const signal = opts?.signal;\n const out: Array<{ event: SessionEvent; eventIndex: number; ts: string }> = [];\n\n // Try to stat first so a missing file returns [] instead of throwing\n // — matches `load()` ENOENT semantics that callers already depend on.\n let stat: import('node:fs').Stats;\n try {\n stat = await fsp.stat(file);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return [];\n throw err;\n }\n if (stat.size === 0) return [];\n\n let fh: fsp.FileHandle | undefined;\n try {\n fh = await fsp.open(file, 'r');\n // Read in 64KB chunks; lines can straddle a chunk boundary so we\n // carry the trailing partial line forward between iterations.\n const CHUNK = 64 * 1024;\n const buf = Buffer.alloc(CHUNK);\n let leftover = '';\n let eventIndex = 0;\n for (let position = 0; ; position += buf.byteLength) {\n if (signal?.aborted) {\n const reason = signal.reason ?? new DOMException('Aborted', 'AbortError');\n throw reason;\n }\n const { bytesRead } = await fh.read(buf, 0, CHUNK, position);\n if (bytesRead === 0) break;\n const text = leftover + buf.subarray(0, bytesRead).toString('utf8');\n // Split into lines; the last element is either '' (file ended on a\n // newline) or a partial line — keep it as the new leftover.\n const parts = text.split('\\n');\n leftover = parts.pop() ?? '';\n for (const line of parts) {\n if (!line) continue;\n let ev: SessionEvent;\n try {\n const parsed: unknown = JSON.parse(line);\n if (\n parsed === null ||\n typeof parsed !== 'object' ||\n typeof (parsed as { type?: unknown }).type !== 'string' ||\n typeof (parsed as { ts?: unknown }).ts !== 'string'\n ) {\n // Skip lines that don't match the SessionEvent shape — same\n // tolerance as `load()` (which silently drops non-events).\n continue;\n }\n ev = parsed as SessionEvent;\n } catch {\n // Skip malformed JSON, matching `load()` behavior.\n continue;\n }\n if (predicate(ev, eventIndex, ev.ts)) {\n out.push({ event: ev, eventIndex, ts: ev.ts });\n if (limit !== undefined && out.length >= limit) {\n return out;\n }\n }\n eventIndex++;\n }\n }\n // Flush a trailing line that lacks a final newline.\n if (leftover.trim()) {\n try {\n const parsed: unknown = JSON.parse(leftover);\n if (\n parsed !== null &&\n typeof parsed === 'object' &&\n typeof (parsed as { type?: unknown }).type === 'string' &&\n typeof (parsed as { ts?: unknown }).ts === 'string'\n ) {\n const ev = parsed as SessionEvent;\n if (predicate(ev, eventIndex, ev.ts)) {\n out.push({ event: ev, eventIndex, ts: ev.ts });\n }\n }\n } catch {\n /* partial trailing line — drop */\n }\n }\n return out;\n } finally {\n if (fh) await fh.close().catch(() => undefined);\n }\n }\n\n async list(limit = 20): Promise<SessionSummary[]> {\n try {\n await ensureDir(this.dir);\n // Try the index first; fall back to directory scan if the index is\n // missing, empty, or unreadable.\n const indexed = await this.readIndex();\n if (indexed.length > 0) {\n // `readIndex()` already sorted the array by startedAt DESC, id\n // ASC, so we just slice the prefix.\n return indexed.slice(0, limit);\n }\n // Index unavailable — fall back to a directory scan. Prefer summary\n // sidecars and only backfill full JSONL-derived summaries for the page\n // we are about to return.\n return await this.listFromDirectoryScan(limit);\n } catch {\n return [];\n }\n }\n\n /**\n * List sessions matching filter criteria, using the cached index.\n * Filters are applied BEFORE sorting and slicing, so the caller gets\n * exactly `limit` matching sessions — not a slice of a larger fetch.\n *\n * This avoids the DefaultSessionReader pattern of fetching 1000 sessions\n * then linear-filtering: the index is already in memory (readIndex\n * caches it), and the filter runs over the cached array without any\n * additional disk I/O.\n */\n async listFiltered(criteria: {\n since?: string | undefined;\n until?: string | undefined;\n provider?: string | undefined;\n model?: string | undefined;\n minTokens?: number | undefined;\n titleContains?: string | undefined;\n limit?: number | undefined;\n }): Promise<SessionSummary[]> {\n const limit = criteria.limit ?? 100;\n try {\n await ensureDir(this.dir);\n const indexed = await this.readIndex();\n if (indexed.length === 0) {\n // No index — fall back to list() + in-process filter.\n const raw = await this.list(Math.max(limit, 100));\n return raw.filter((s) => matchesSessionFilter(s, criteria)).slice(0, limit);\n }\n const filtered = indexed.filter((s) => matchesSessionFilter(s, criteria));\n filtered.sort((a, b) => {\n if (a.startedAt < b.startedAt) return 1;\n if (a.startedAt > b.startedAt) return -1;\n return a.id.localeCompare(b.id);\n });\n return filtered.slice(0, limit);\n } catch {\n return [];\n }\n }\n\n // ── Session index (_index.jsonl) ─────────────────────────────────────────\n //\n // One JSON line per closed session, appended atomically on close().\n // When a session is deleted, a tombstone {action:\"delete\",id:\"...\"} is\n // appended. On read, tombstones filter out matching session entries.\n // This keeps listing O(lines-in-index) instead of O(files-on-disk).\n //\n // The index auto-compacts every N appends to prevent unbounded growth\n // from tombstones and duplicate entries (resume cycles).\n\n private indexAppendCount = 0;\n private static readonly COMPACT_EVERY = 30;\n\n /** Append a session summary to the index. */\n private async appendToIndex(summary: SessionSummary): Promise<void> {\n // Note: storage.write for this operation is emitted by FileSessionWriter.doClose()\n // so it can include the traceId. Do NOT emit here to avoid duplicates.\n try {\n await ensureDir(this.dir);\n const line = JSON.stringify(summary) + '\\n';\n await fsp.appendFile(this.indexFile, line, 'utf8');\n this._indexCache = null;\n this.invalidateShardManifestBySessionId(summary.id);\n this.indexAppendCount++;\n // Auto-compact the index periodically to remove tombstones and duplicates.\n if (this.indexAppendCount >= DefaultSessionStore.COMPACT_EVERY) {\n await this.compactIndex();\n this.indexAppendCount = 0;\n }\n } catch {\n // best-effort — error surfaced via the storage.write event in doClose()\n }\n }\n\n /** Append a tombstone entry for a deleted session. */\n private async writeTombstone(id: string): Promise<void> {\n try {\n await ensureDir(this.dir);\n const line = JSON.stringify({ action: 'delete', id }) + '\\n';\n await fsp.appendFile(this.indexFile, line, 'utf8');\n this._indexCache = null;\n this.invalidateShardManifestBySessionId(id);\n this.indexAppendCount++;\n } catch {\n // best-effort\n }\n }\n\n /**\n * Compact the index: read all entries, drop tombstones, deduplicate\n * (keep latest per session), and rewrite. Atomic via temp+rename.\n */\n private async compactIndex(): Promise<void> {\n const t0 = Date.now();\n let outcome: 'success' | 'failure' = 'success';\n let errorMsg: string | undefined;\n try {\n const entries = await this.readIndex();\n if (entries.length === 0) return;\n const tmp = `${this.indexFile}.compact.tmp`;\n const lines = entries.map((s) => JSON.stringify(s)).join('\\n') + '\\n';\n await fsp.writeFile(tmp, lines, 'utf8');\n await fsp.rename(tmp, this.indexFile);\n this._indexCache = null;\n } catch (err) {\n outcome = 'failure';\n errorMsg = toErrorMessage(err);\n } finally {\n // Compact is internal — use 'session' as the session ID placeholder.\n this.emitWrite('~compact~', this.indexFile, 'compact', outcome, Date.now() - t0, undefined, errorMsg);\n }\n }\n\n /**\n * Read the index file and return deduplicated session summaries.\n * Entries with a matching tombstone are filtered out.\n * Returns empty array when the index doesn't exist or is corrupt.\n */\n private async readIndex(): Promise<SessionSummary[]> {\n let stat: { mtimeMs: number; size: number };\n try {\n const s = await fsp.stat(this.indexFile);\n stat = { mtimeMs: s.mtimeMs, size: s.size };\n } catch {\n this._indexCache = null;\n return [];\n }\n\n if (\n this._indexCache !== null &&\n this._indexCache.mtimeMs === stat.mtimeMs &&\n this._indexCache.size === stat.size\n ) {\n return [...this._indexCache.summaries];\n }\n\n let raw: string;\n try {\n raw = await fsp.readFile(this.indexFile, 'utf8');\n } catch {\n this._indexCache = null;\n return [];\n }\n const deleted = new Set<string>();\n const seen = new Map<string, SessionSummary>();\n for (const line of raw.split('\\n')) {\n if (!line.trim()) continue;\n try {\n const entry = JSON.parse(line) as { action?: string | undefined; id?: string | undefined } & SessionSummary;\n if (entry.action === 'delete' && entry.id) {\n deleted.add(entry.id);\n seen.delete(entry.id);\n continue;\n }\n if (entry.id && !deleted.has(entry.id)) {\n // Keep the latest entry for each session (multiple appends on resume).\n seen.set(entry.id, entry as SessionSummary);\n }\n } catch {\n // skip corrupt lines\n }\n }\n const summaries = Array.from(seen.values());\n // Sort once when the index is (re)loaded so `list()` callers can\n // take a prefix without re-sorting the whole array per request.\n // Sort key mirrors the original `list()` comparator:\n // startedAt DESC, then id ASC for tie-breaks.\n summaries.sort((a, b) => {\n if (a.startedAt < b.startedAt) return 1;\n if (a.startedAt > b.startedAt) return -1;\n return a.id.localeCompare(b.id);\n });\n this._indexCache = { ...stat, summaries };\n return [...summaries];\n }\n\n /**\n * Rebuild the index from disk by scanning all sessions and writing a\n * fresh _index.jsonl. Useful after manual cleanup or index corruption.\n */\n async rebuildIndex(): Promise<number> {\n const ids = await this.collectSessionIds(this.dir);\n /* v8 ignore next -- summaryFor() never rejects for a collected id (its .jsonl exists) */\n const summaries = await Promise.all(ids.map((id) => this.summaryFor(id).catch(() => null))); /* best-effort */\n const valid = summaries.filter((s): s is SessionSummary => s !== null);\n // Atomic rewrite: write to temp, then rename.\n const tmp = `${this.indexFile}.tmp`;\n const lines = valid.map((s) => JSON.stringify(s)).join('\\n') + '\\n';\n await fsp.writeFile(tmp, lines, 'utf8');\n await fsp.rename(tmp, this.indexFile);\n this._indexCache = null;\n return valid.length;\n }\n\n private async listFromDirectoryScan(limit: number): Promise<SessionSummary[]> {\n const shardKeys = await this.collectShardKeys();\n const shardEntries = await mapWithConcurrency(\n shardKeys,\n DefaultSessionStore.LIST_SCAN_CONCURRENCY,\n async (shardKey) => await this.readOrBuildShardManifest(shardKey),\n );\n\n const out: DirectorySummaryCandidate[] = [];\n for (const entry of shardEntries) {\n for (const summary of entry.summaries) {\n out.push({ summary, needsBackfill: false });\n }\n }\n out.sort((a, b) => compareSessionSummaries(a.summary, b.summary));\n\n const selected = out.slice(0, limit);\n const summaries = await mapWithConcurrency(\n selected,\n Math.min(DefaultSessionStore.LIST_SCAN_CONCURRENCY, Math.max(1, limit)),\n async (candidate): Promise<SessionSummary | null> => candidate.summary,\n );\n return summaries.filter((s): s is SessionSummary => s !== null);\n }\n\n private async collectShardKeys(): Promise<string[]> {\n let entries: Dirent[];\n try {\n entries = await fsp.readdir(this.dir, { withFileTypes: true });\n } catch {\n return [''];\n }\n\n const shardKeys = [''];\n for (const entry of entries) {\n if (entry.name.startsWith('.') && entry.name !== '.wrongstack') continue;\n if (entry.name === 'shared' || entry.name === 'subagents' || entry.name === 'attachments') continue;\n if (entry.isDirectory()) shardKeys.push(entry.name);\n }\n return shardKeys;\n }\n\n private async readOrBuildShardManifest(shardKey: string): Promise<ShardManifestEntry> {\n const cached = this.shardManifestCache.get(shardKey);\n if (cached) return cached;\n\n const manifestPath = this.shardManifestPath(shardKey);\n try {\n const raw = await fsp.readFile(manifestPath, 'utf8');\n const parsed = JSON.parse(raw) as ShardManifestEntry;\n const entry: ShardManifestEntry = {\n summaries: Array.isArray(parsed.summaries) ? parsed.summaries : [],\n ids: Array.isArray(parsed.ids) ? parsed.ids : [],\n };\n this.shardManifestCache.set(shardKey, entry);\n return entry;\n } catch {\n // build below\n }\n\n const refs = await this.collectSessionFilesInShard(shardKey);\n const candidates = await mapWithConcurrency(\n refs,\n DefaultSessionStore.LIST_SCAN_CONCURRENCY,\n async (ref): Promise<DirectorySummaryCandidate | null> => {\n const manifest = await this.readSummaryManifest(ref.id);\n if (manifest) return { summary: manifest, needsBackfill: false };\n const summary = await this.summaryHeaderFor(ref);\n if (!summary) return null;\n const hydrated = await this.summaryFor(summary.id).catch(() => summary);\n return { summary: hydrated, needsBackfill: false };\n },\n );\n const summaries = candidates\n .filter((candidate): candidate is DirectorySummaryCandidate => candidate !== null)\n .map((candidate) => candidate.summary);\n summaries.sort(compareSessionSummaries);\n const entry: ShardManifestEntry = { summaries, ids: summaries.map((summary) => summary.id) };\n this.shardManifestCache.set(shardKey, entry);\n await atomicWrite(manifestPath, JSON.stringify(entry), { mode: 0o600 }).catch(() => undefined);\n return entry;\n }\n\n private async collectSessionFilesInShard(shardKey: string): Promise<SessionFileRef[]> {\n const dir = shardKey ? path.join(this.dir, shardKey) : this.dir;\n const entries = await this.collectSessionFiles(dir, shardKey);\n return shardKey\n ? entries.filter((entry) => entry.id.startsWith(`${shardKey}/`))\n : entries.filter((entry) => !entry.id.includes('/'));\n }\n\n private async collectSessionFiles(\n dir: string,\n prefix = '',\n depth = 0,\n ): Promise<SessionFileRef[]> {\n let entries: Dirent[];\n try {\n entries = await fsp.readdir(dir, { withFileTypes: true });\n } catch {\n return [];\n }\n\n const dirEntries: Dirent[] = [];\n const files: SessionFileRef[] = [];\n for (const entry of entries) {\n if (entry.name.startsWith('.') && entry.name !== '.wrongstack') continue;\n if (entry.name === 'shared' || entry.name === 'subagents' || entry.name === 'attachments')\n continue;\n if (entry.isDirectory()) {\n dirEntries.push(entry);\n } else if (entry.isFile() && entry.name.endsWith('.jsonl')) {\n if (entry.name === '_index.jsonl') continue;\n const base = entry.name.replace(/\\.jsonl$/, '');\n const id = prefix ? `${prefix}/${base}` : base;\n files.push({ id, filePath: path.join(dir, entry.name) });\n }\n }\n\n const childFileArrays = await Promise.all(\n dirEntries.map((entry) => {\n const childPrefix = depth === 0 ? entry.name : `${prefix}/${entry.name}`;\n return this.collectSessionFiles(path.join(dir, entry.name), childPrefix, depth + 1);\n }),\n );\n\n return [...childFileArrays.flat(), ...files];\n }\n\n /** Recursively collect session IDs from date-shard subdirectories.\n * IDs include the date-prefix path (e.g. \"2026-06-06/17-46-57Z_…\").\n * Skips `.jsonl`/`.summary.json` root files, dot-files, and\n * sub-directories that belong to fleet/subagent sessions. */\n private async collectSessionIds(\n dir: string,\n prefix = '',\n depth = 0,\n ): Promise<string[]> {\n let entries: Dirent[];\n try {\n entries = await fsp.readdir(dir, { withFileTypes: true });\n } catch {\n return [];\n }\n\n // Separate dirs and files in one pass — avoids a second iteration.\n const dirEntries: Dirent[] = [];\n const fileIds: string[] = [];\n for (const entry of entries) {\n if (entry.name.startsWith('.') && entry.name !== '.wrongstack') continue;\n if (entry.name === 'shared' || entry.name === 'subagents' || entry.name === 'attachments')\n continue;\n if (entry.isDirectory()) {\n dirEntries.push(entry);\n } else if (entry.isFile() && entry.name.endsWith('.jsonl')) {\n if (entry.name === '_index.jsonl') continue;\n const base = entry.name.replace(/\\.jsonl$/, '');\n fileIds.push(prefix ? `${prefix}/${base}` : base);\n }\n }\n\n // At depth 0 the date-shard directories are independent — parallelize across\n // them. Deeper recursion (intra-shard) is sequential since shards are small.\n const childIdArrays = await Promise.all(\n dirEntries.map((entry) => {\n const childPrefix = depth === 0 ? entry.name : `${prefix}/${entry.name}`;\n return this.collectSessionIds(path.join(dir, entry.name), childPrefix, depth + 1);\n }),\n );\n\n return [...childIdArrays.flat(), ...fileIds];\n }\n\n private async summaryFor(id: string): Promise<SessionSummary> {\n const manifest = this.sessionPath(id, '.summary.json');\n const t0 = Date.now();\n let outcome: 'success' | 'failure' = 'success';\n let errorMsg: string | undefined;\n const fromManifest = await this.readSummaryManifest(id, t0);\n if (fromManifest) return fromManifest;\n\n try {\n const full = this.sessionPath(id, '.jsonl');\n const stat = await fsp.stat(full);\n const summary = await this.summarize(id, stat.mtime.toISOString());\n await atomicWrite(manifest, JSON.stringify(summary), { mode: 0o600 }).catch((err) => {\n const msg = toErrorMessage(err);\n this.emitError(id, manifest, 'summary_fallback', msg, true);\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'session_store.manifest_write_failed',\n sessionId: id,\n message: msg,\n timestamp: new Date().toISOString(),\n }));\n });\n outcome = 'failure';\n errorMsg = 'summary fallback — manifest rebuilt';\n this.emitRead(id, manifest, 'summary', outcome, Date.now() - t0, errorMsg);\n return summary;\n } catch (err) {\n outcome = 'failure';\n errorMsg = toErrorMessage(err);\n this.emitRead(id, manifest, 'summary', outcome, Date.now() - t0, errorMsg);\n return {\n id,\n title: '(damaged)',\n startedAt: new Date().toISOString(),\n model: 'unknown',\n provider: 'unknown',\n tokenTotal: 0,\n };\n }\n }\n\n private async readSummaryManifest(\n id: string,\n startTime = Date.now(),\n ): Promise<SessionSummary | null> {\n const manifest = this.sessionPath(id, '.summary.json');\n try {\n const raw = await fsp.readFile(manifest, 'utf8');\n this.emitRead(id, manifest, 'summary', 'success', Date.now() - startTime);\n return JSON.parse(raw) as SessionSummary;\n } catch {\n return null;\n }\n }\n\n private async summaryHeaderFor(ref: SessionFileRef): Promise<SessionSummary | null> {\n let mtime = new Date(0).toISOString();\n try {\n const stat = await fsp.stat(ref.filePath);\n if (!stat.isFile()) {\n return {\n id: ref.id,\n title: '(damaged)',\n startedAt: stat.mtime.toISOString(),\n model: 'unknown',\n provider: 'unknown',\n tokenTotal: 0,\n };\n }\n mtime = stat.mtime.toISOString();\n } catch {\n return null;\n }\n\n try {\n for await (const event of this.iterSessionEvents(ref.filePath)) {\n if (event.type === 'session_start') {\n return {\n id: ref.id,\n title: '(empty session)',\n startedAt: event.ts,\n model: event.model ?? 'unknown',\n provider: event.provider ?? 'unknown',\n tokenTotal: 0,\n };\n }\n }\n return {\n id: ref.id,\n title: '(empty session)',\n startedAt: new Date(0).toISOString(),\n model: 'unknown',\n provider: 'unknown',\n tokenTotal: 0,\n };\n } catch {\n return {\n id: ref.id,\n title: '(damaged)',\n startedAt: mtime,\n model: 'unknown',\n provider: 'unknown',\n tokenTotal: 0,\n };\n }\n }\n\n /**\n * Delete a session and all associated files: JSONL, summary, plan/todos\n * sidecars, and the session directory (fleet.json, shared/, subagents/).\n *\n * Individual file deletions are best-effort (logged as structured warnings),\n * but a tombstone is always written so readIndex() filters this session out.\n * If the session directory itself can't be removed, the error is surfaced\n * to the caller so prune() can report it.\n */\n private async deleteSession(id: string): Promise<void> {\n const jsonlPath = this.sessionPath(id, '.jsonl');\n const summaryPath = this.sessionPath(id, '.summary.json');\n const shardDir = path.dirname(path.join(this.dir, id));\n const base = path.basename(id);\n const sessDir = path.join(shardDir, base);\n\n const deletions: Array<Promise<void>> = [\n fsp.unlink(jsonlPath),\n fsp.unlink(summaryPath),\n fsp.unlink(path.join(shardDir, `${base}.plan.json`)),\n fsp.unlink(path.join(shardDir, `${base}.todos.json`)),\n ];\n\n const results = await Promise.allSettled(deletions);\n for (const r of results) {\n if (r.status === 'rejected') {\n const msg = r.reason instanceof Error ? r.reason.message : String(r.reason);\n // ENOENT is expected (file may not exist — sidecars are optional).\n if ((r.reason as NodeJS.ErrnoException)?.code !== 'ENOENT') {\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'session_store.delete_failed',\n sessionId: id,\n message: msg,\n timestamp: new Date().toISOString(),\n }));\n }\n }\n }\n\n // Remove the session directory (may contain fleet.json, shared/, subagents/).\n /* v8 ignore start -- defensive: rm with force:true rarely rejects */\n await fsp.rm(sessDir, { recursive: true, force: true }).catch((err) => {\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'session_store.rmdir_failed',\n sessionId: id,\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n });\n /* v8 ignore stop */\n\n // Write an index tombstone so readIndex() filters this session out.\n await this.writeTombstone(id);\n }\n\n async delete(id: string): Promise<void> {\n await this.deleteSession(id);\n }\n\n async prune(maxAgeDays = 30): Promise<number> {\n const cutoff = Date.now() - maxAgeDays * 86_400_000;\n let deleted = 0;\n\n // Read the active session lock to avoid pruning the current session.\n let activeSessionId: string | null = null;\n try {\n const raw = await fsp.readFile(path.join(this.dir, 'active.json'), 'utf8');\n const active = JSON.parse(raw) as { sessionId?: string | undefined };\n activeSessionId = active.sessionId ?? null;\n } catch {\n // no active.json — nothing to protect\n }\n\n const isPrunableJsonl = (name: string): boolean =>\n name.endsWith('.jsonl') &&\n name !== '_index.jsonl' &&\n name !== '_mailbox.jsonl' &&\n !name.endsWith('.replay.jsonl') &&\n !name.endsWith('.audit.jsonl');\n\n const pruneFile = async (dir: string, name: string, prefix: string): Promise<void> => {\n const jsonlPath = path.join(dir, name);\n try {\n const stat = await fsp.stat(jsonlPath);\n if (stat.mtimeMs >= cutoff) return;\n /* v8 ignore start -- defensive: file vanished between readdir and stat */\n } catch {\n return;\n }\n /* v8 ignore stop */\n const base = name.replace(/\\.jsonl$/, '');\n const id = prefix ? `${prefix}/${base}` : base;\n // Never prune the currently active session.\n if (activeSessionId && id === activeSessionId) return;\n await this.deleteSession(id);\n deleted++;\n };\n\n /* v8 ignore next -- defensive: store dir is ensured before prune runs */\n const entries = await fsp.readdir(this.dir, { withFileTypes: true }).catch(() => []);\n for (const entry of entries) {\n if (entry.isFile()) {\n // Flat legacy sessions at the sessions root — pre-shard layout.\n // A shard-only scan left these accumulating forever.\n if (isPrunableJsonl(entry.name)) await pruneFile(this.dir, entry.name, '');\n continue;\n }\n /* v8 ignore next -- defensive: root entries are only files or directories */\n if (!entry.isDirectory()) continue;\n // entry.name is a date-shard like \"2026-06-06\"\n const dateDir = path.join(this.dir, entry.name);\n /* v8 ignore next -- defensive: dateDir came from readdir and is readable */\n const files = await fsp.readdir(dateDir, { withFileTypes: true }).catch(() => []);\n for (const file of files) {\n if (!file.isFile() || !isPrunableJsonl(file.name)) continue;\n await pruneFile(dateDir, file.name, entry.name);\n }\n }\n if (deleted > 0) {\n // Compact the index to remove tombstones for deleted sessions.\n /* v8 ignore next -- best-effort: compactIndex swallows its own errors */\n await this.compactIndex().catch(() => undefined); /* best-effort */\n }\n // Clean up empty date-shard directories left behind after pruning.\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const dateDir = path.join(this.dir, entry.name);\n try {\n const remaining = await fsp.readdir(dateDir);\n if (remaining.length === 0) {\n /* v8 ignore next -- best-effort: rmdir of a confirmed-empty dir does not reject */\n await fsp.rmdir(dateDir).catch(() => undefined);\n }\n } catch {\n // best-effort\n }\n }\n return deleted;\n }\n\n async clearHistory(id: string): Promise<void> {\n await this.ensureShardDir(id);\n const file = this.sessionPath(id, '.jsonl');\n const meta = this.sessionPath(id, '.summary.json');\n const record = `${JSON.stringify({\n type: 'session_start',\n ts: new Date().toISOString(),\n id,\n model: 'unknown',\n provider: 'unknown',\n })}\\n`;\n await fsp.writeFile(file, record, 'utf8');\n await fsp.unlink(meta).catch(() => undefined);\n }\n\n private async summarize(id: string, mtime: string): Promise<SessionSummary> {\n try {\n const file = this.sessionPath(id, '.jsonl');\n let title = '(empty session)';\n let startedAt = new Date(0).toISOString();\n let endedAt: string | undefined;\n let model = 'unknown';\n let provider = 'unknown';\n let tokenIn = 0;\n let tokenOut = 0;\n let iterationCount = 0;\n let toolCallCount = 0;\n let toolErrorCount = 0;\n let fileChangeCount = 0;\n const toolBreakdown: Record<string, number> = {};\n let outcome: SessionSummary['outcome'] ;\n let lastEventType: SessionEvent['type'] | undefined;\n let hasError = false;\n let sawStart = false;\n\n for await (const e of this.iterSessionEvents(file)) {\n lastEventType = e.type;\n if (e.type === 'session_start') {\n if (!sawStart) {\n sawStart = true;\n startedAt = e.ts;\n model = e.model ?? 'unknown';\n provider = e.provider ?? 'unknown';\n }\n } else if (e.type === 'session_end') {\n endedAt = e.ts;\n } else if (e.type === 'user_input') {\n if (title === '(empty session)') title = userInputTitle(e.content);\n } else if (e.type === 'llm_response') {\n tokenIn += e.usage.input ?? 0;\n tokenOut += e.usage.output ?? 0;\n } else if (e.type === 'in_flight_start') iterationCount++;\n else if (e.type === 'tool_call_start') {\n toolCallCount++;\n toolBreakdown[e.name] = (toolBreakdown[e.name] ?? 0) + 1;\n } else if (e.type === 'tool_result' && e.isError) toolErrorCount++;\n else if (e.type === 'file_snapshot') fileChangeCount += e.files.length;\n else if (e.type === 'error' || e.type === 'provider_error') hasError = true;\n }\n\n // Determine outcome from the last event.\n if (lastEventType === 'session_end') {\n outcome = 'completed';\n } else if (lastEventType === 'in_flight_start') {\n outcome = 'aborted';\n } else if (hasError) {\n outcome = 'error';\n }\n\n return {\n id,\n title,\n startedAt,\n endedAt,\n model,\n provider,\n tokenTotal: tokenIn + tokenOut,\n iterationCount: iterationCount > 0 ? iterationCount : undefined,\n toolCallCount: toolCallCount > 0 ? toolCallCount : undefined,\n toolErrorCount: toolErrorCount > 0 ? toolErrorCount : undefined,\n fileChangeCount: fileChangeCount > 0 ? fileChangeCount : undefined,\n toolBreakdown: Object.keys(toolBreakdown).length > 0 ? toolBreakdown : {},\n outcome,\n };\n } catch {\n return {\n id,\n title: '(damaged)',\n startedAt: mtime,\n model: 'unknown',\n provider: 'unknown',\n tokenTotal: 0,\n };\n }\n }\n\n private async *iterSessionEvents(file: string): AsyncGenerator<SessionEvent> {\n const stream = createReadStream(file, { encoding: 'utf8' });\n const lines = createInterface({ input: stream, crlfDelay: Infinity });\n try {\n for await (const line of lines) {\n if (!line.trim()) continue;\n try {\n const parsed: unknown = JSON.parse(line);\n if (\n parsed !== null &&\n typeof parsed === 'object' &&\n typeof (parsed as { type?: unknown | undefined }).type === 'string' &&\n typeof (parsed as { ts?: unknown | undefined }).ts === 'string'\n ) {\n yield parsed as SessionEvent;\n }\n } catch {\n // skip malformed JSON\n }\n }\n } finally {\n lines.close();\n stream.destroy();\n }\n }\n\n\n}\n\n","import * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { EventBus } from '../kernel/events.js';\nimport type { ContentBlock } from '../types/blocks.js';\nimport { atomicWrite } from '../utils/atomic-write.js';\nimport { toErrorMessage } from '../utils/error.js';\n\n/**\n * The persisted form of a single queued user message. The TUI's\n * in-memory QueueItem has a render id; that's pure UI bookkeeping, so\n * we drop it when serializing — fresh ids are assigned on rehydrate.\n */\nexport interface PersistedQueueItem {\n displayText: string;\n blocks: ContentBlock[];\n}\n\n/**\n * Side-file storage for a session's pending input queue. Lives at\n * `<sessionDir>/queue.json` next to the attachment spool. Reads are\n * tolerant (missing/malformed file → empty array); writes are atomic\n * (tmp + rename) so a crash mid-write can never leave a partial file\n * the next launch would choke on.\n *\n * The contract is \"snapshot replacement\": every mutation hands the\n * full queue and we rewrite the file. The queue is small (rarely more\n * than a handful of messages), so this is cheaper than delta logging\n * and avoids the replay complexity.\n */\nexport class QueueStore {\n private readonly file: string;\n // Use `| undefined` (not `?`) so exactOptionalPropertyTypes doesn't\n // reject assigning an optional constructor parameter to these fields.\n private readonly events: EventBus | undefined;\n private readonly traceId: string | undefined;\n\n constructor(opts: { dir: string; events?: EventBus; traceId?: string }) {\n this.file = path.join(opts.dir, 'queue.json');\n this.events = opts.events;\n this.traceId = opts.traceId;\n }\n\n async write(items: PersistedQueueItem[]): Promise<void> {\n const t0 = Date.now();\n if (items.length === 0) {\n // Empty queue → remove the file rather than write `[]`. Keeps\n // a clean idle state on disk and makes `read()` cheaper.\n await this.clear();\n return;\n }\n try {\n await atomicWrite(this.file, JSON.stringify(items), { mode: 0o600 });\n this.events?.emit('storage.write', {\n sessionId: this.traceId ?? '~boot~',\n store: 'queue',\n filePath: this.file,\n operation: 'write',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n } catch (err) {\n this.events?.emit('storage.error', {\n sessionId: this.traceId ?? '~boot~',\n store: 'queue',\n filePath: this.file,\n operation: 'write',\n outcome: 'failure',\n error: toErrorMessage(err),\n recoverable: false,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'queue_store.write_failed',\n path: this.file,\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n }\n }\n\n async read(): Promise<PersistedQueueItem[]> {\n const t0 = Date.now();\n let raw: string;\n try {\n raw = await fsp.readFile(this.file, 'utf8');\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') {\n this.events?.emit('storage.read', {\n sessionId: this.traceId ?? '~boot~',\n store: 'queue',\n filePath: this.file,\n operation: 'read',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n return [];\n }\n this.events?.emit('storage.error', {\n sessionId: this.traceId ?? '~boot~',\n store: 'queue',\n filePath: this.file,\n operation: 'read',\n outcome: 'failure',\n error: toErrorMessage(err),\n recoverable: true,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'queue_store.read_failed',\n path: this.file,\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n return [];\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n this.events?.emit('storage.read', {\n sessionId: this.traceId ?? '~boot~',\n store: 'queue',\n filePath: this.file,\n operation: 'read',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'parse_failed',\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n return [];\n }\n if (!Array.isArray(parsed)) {\n this.events?.emit('storage.read', {\n sessionId: this.traceId ?? '~boot~',\n store: 'queue',\n filePath: this.file,\n operation: 'read',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'invalid_schema',\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n return [];\n }\n this.events?.emit('storage.read', {\n sessionId: this.traceId ?? '~boot~',\n store: 'queue',\n filePath: this.file,\n operation: 'read',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n const out: PersistedQueueItem[] = [];\n for (const v of parsed) {\n if (isPersistedQueueItem(v)) out.push(v);\n }\n return out;\n }\n\n async clear(): Promise<void> {\n const t0 = Date.now();\n try {\n await fsp.unlink(this.file);\n this.events?.emit('storage.write', {\n sessionId: this.traceId ?? '~boot~',\n store: 'queue',\n filePath: this.file,\n operation: 'clear',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') return;\n this.events?.emit('storage.error', {\n sessionId: this.traceId ?? '~boot~',\n store: 'queue',\n filePath: this.file,\n operation: 'clear',\n outcome: 'failure',\n error: toErrorMessage(err),\n recoverable: true,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n // Best-effort: a permission/lock error during clear is rare and\n // the queue slash command is non-critical. Warn so it's observable\n // but don't throw so the slash command doesn't crash.\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'queue_store.clear_failed',\n path: this.file,\n message: (err as Error).message,\n timestamp: new Date().toISOString(),\n }));\n }\n }\n}\n\nfunction isPersistedQueueItem(v: unknown): v is PersistedQueueItem {\n if (typeof v !== 'object' || v === null) return false;\n const o = v as Record<string, unknown>;\n return typeof o['displayText'] === 'string' && Array.isArray(o['blocks']);\n}\n","import { randomBytes } from 'node:crypto';\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { atomicWrite } from '../utils/atomic-write.js';\nimport type {\n AddAttachmentInput,\n Attachment,\n AttachmentKind,\n AttachmentRef,\n AttachmentStore,\n} from '../types/attachment.js';\nimport type { ContentBlock } from '../types/blocks.js';\n\nexport interface AttachmentStoreOptions {\n /**\n * Directory for spooling payloads larger than `spoolThresholdBytes`.\n * When omitted, all payloads stay in memory.\n */\n spoolDir?: string | undefined;\n spoolThresholdBytes?: number | undefined;\n}\n\nconst DEFAULT_SPOOL_THRESHOLD = 256 * 1024; // 256 KB\n// Two placeholder shapes:\n// - seq-keyed `[<kind> #<seq>…]` — kind is `pasted` / `image` / `file`. A\n// cosmetic suffix after the seq (e.g. `, 123 lines`) is tolerated so the\n// TUI can render `[pasted #1, 123 lines]` while still resolving by seq.\n// - path-keyed `[file:<path>]` — resolves to the most recent file ref whose\n// stored path matches, so the TUI can show a human-readable file chip.\nconst PLACEHOLDER_RE = /\\[(pasted|image|file) #(\\d+)[^\\]]*\\]|\\[file:([^\\]]+)\\]/g;\n\n/**\n * In-memory attachment store with optional disk spool. Placeholder syntax\n * is `[<kind> #<seq>]` (seq-keyed) or `[file:<path>]` (path-keyed) where kind\n * is `pasted` / `image` / `file`. Unknown placeholders are passed through\n * as-is so users can write that literal text without losing it.\n */\nexport class DefaultAttachmentStore implements AttachmentStore {\n private readonly items = new Map<string, Attachment>();\n private readonly refs: AttachmentRef[] = [];\n private nextSeq: Record<AttachmentKind, number> = { text: 0, image: 0, file: 0 };\n private readonly spoolDir: string | undefined;\n private readonly spoolThreshold: number;\n\n constructor(opts: AttachmentStoreOptions = {}) {\n this.spoolDir = opts.spoolDir;\n this.spoolThreshold = opts.spoolThresholdBytes ?? DEFAULT_SPOOL_THRESHOLD;\n }\n\n async add(input: AddAttachmentInput): Promise<AttachmentRef> {\n const seq = ++this.nextSeq[input.kind];\n const id = `${kindPrefix(input.kind)}-${seq}-${randomBytes(3).toString('hex')}`;\n const bytes = Buffer.byteLength(input.data, input.kind === 'image' ? 'base64' : 'utf8');\n let spooledPath: string | undefined;\n let data: string | undefined = input.data;\n if (this.spoolDir && bytes >= this.spoolThreshold) {\n await fsp.mkdir(this.spoolDir, { recursive: true });\n spooledPath = path.join(this.spoolDir, `${id}.bin`);\n // atomicWrite: torn spool would silently corrupt the attachment;\n // the user would see garbled output the next time it's expanded.\n await atomicWrite(spooledPath, input.data, {\n encoding: input.kind === 'image' ? 'base64' : 'utf8',\n });\n data = undefined;\n }\n const att: Attachment = {\n id,\n kind: input.kind,\n meta: input.meta ?? {},\n data,\n path: spooledPath,\n bytes,\n createdAt: new Date().toISOString(),\n };\n this.items.set(id, att);\n const ref: AttachmentRef = { id, kind: input.kind, seq, meta: att.meta };\n this.refs.push(ref);\n return ref;\n }\n\n async get(id: string): Promise<Attachment | undefined> {\n return this.items.get(id);\n }\n\n list(): AttachmentRef[] {\n return [...this.refs];\n }\n\n async expand(text: string): Promise<ContentBlock[]> {\n const matches = [...text.matchAll(PLACEHOLDER_RE)];\n if (matches.length === 0) return text ? [{ type: 'text', text }] : [];\n const blocks: ContentBlock[] = [];\n let lastIndex = 0;\n for (const m of matches) {\n const idx = m.index ?? 0;\n const before = text.slice(lastIndex, idx);\n if (before) blocks.push({ type: 'text', text: before });\n let ref: AttachmentRef | undefined;\n if (m[3] !== undefined) {\n // Path-keyed `[file:<path>]` — most recent matching file ref wins.\n const wantPath = m[3];\n ref = findLast(this.refs, (r) => r.kind === 'file' && refPath(r) === wantPath);\n } else {\n const kind = prefixToKind(m[1] as string);\n const seq = Number(m[2]);\n ref = this.refs.find((r) => r.kind === kind && r.seq === seq);\n }\n const att = ref ? this.items.get(ref.id) : undefined;\n if (!att) {\n blocks.push({ type: 'text', text: m[0] });\n } else {\n blocks.push(await this.toBlock(att));\n }\n lastIndex = idx + m[0].length;\n }\n const tail = text.slice(lastIndex);\n if (tail) blocks.push({ type: 'text', text: tail });\n return mergeAdjacentText(blocks);\n }\n\n async clear(): Promise<void> {\n // Unlink any spooled files so we don't leak disk space.\n if (this.spoolDir) {\n const toDelete: string[] = [];\n for (const att of this.items.values()) {\n if (att.path) toDelete.push(att.path);\n }\n /* v8 ignore next -- best-effort: unlink of a just-spooled file does not reject */\n await Promise.all(toDelete.map((p) => fsp.unlink(p).catch(() => undefined)));\n }\n this.items.clear();\n this.refs.length = 0;\n this.nextSeq = { text: 0, image: 0, file: 0 };\n }\n\n private async toBlock(att: Attachment): Promise<ContentBlock> {\n if (att.kind === 'image') {\n const data =\n att.data ?? (att.path ? await fsp.readFile(att.path, { encoding: 'base64' }) : '');\n return {\n type: 'image',\n source: {\n type: 'base64',\n media_type: att.meta.mediaType ?? 'image/png',\n data,\n },\n };\n }\n const raw = att.data ?? (att.path ? await fsp.readFile(att.path, 'utf8') : '');\n const label = att.meta.filename ? `<file path=\"${att.meta.filename}\">` : '<pasted>';\n const close = att.meta.filename ? '</file>' : '</pasted>';\n return { type: 'text', text: `${label}\\n${raw}\\n${close}` };\n }\n}\n\nfunction kindPrefix(kind: AttachmentKind): string {\n return kind === 'text' ? 'pasted' : kind;\n}\n\nfunction prefixToKind(prefix: string): AttachmentKind {\n if (prefix === 'pasted') return 'text';\n if (prefix === 'image') return 'image';\n return 'file';\n}\n\n/** Path a file ref was registered under, for `[file:<path>]` lookup. */\nfunction refPath(ref: AttachmentRef): string | undefined {\n return ref.meta.filename ?? ref.meta.label;\n}\n\n/** Last element matching the predicate (Node < 20 lacks Array.findLast). */\nfunction findLast<T>(arr: readonly T[], pred: (v: T) => boolean): T | undefined {\n for (let i = arr.length - 1; i >= 0; i--) {\n if (pred(arr[i] as T)) return arr[i];\n }\n return undefined;\n}\n\nfunction mergeAdjacentText(blocks: ContentBlock[]): ContentBlock[] {\n const out: ContentBlock[] = [];\n for (const b of blocks) {\n const prev = out[out.length - 1];\n if (b.type === 'text' && prev && prev.type === 'text') {\n prev.text += b.text;\n } else {\n out.push(b);\n }\n }\n return out;\n}\n","export type MemoryScope = 'project-agents' | 'project-memory' | 'user-memory';\n\n// ── Memory categories ──────────────────────────────────────────────────\n\nexport type MemoryType = 'fact' | 'decision' | 'convention' | 'preference' | 'reference' | 'anti_pattern';\n\nexport const MEMORY_TYPE_LABELS: Record<MemoryType, string> = {\n fact: 'Fact',\n decision: 'Decision',\n convention: 'Convention',\n preference: 'Preference',\n reference: 'Reference',\n anti_pattern: 'Anti-pattern',\n};\n\nexport type MemoryPriority = 'critical' | 'high' | 'medium' | 'low';\n\nexport interface MemoryEntry {\n scope: MemoryScope;\n text: string;\n ts: string;\n /** Category — helps the agent decide whether to inject or ignore. */\n type?: MemoryType | undefined;\n /** Free-form tags for grouping (e.g. [\"build\", \"pnpm\", \"typescript\"]). */\n tags?: string[] | undefined;\n /** Priority — critical entries are always injected; low may be skipped. */\n priority?: MemoryPriority | undefined;\n /** Session or agent that created this entry. */\n source?: string | undefined;\n /** 0.0–1.0 confidence. Low-confidence entries are injected less often. */\n confidence?: number | undefined;\n /** ISO timestamp of last access (read or injection into context). */\n lastAccessed?: string | undefined;\n}\n\n// ── Memory events — emitted by DefaultMemoryStore so plugins can react ──\n\nexport interface MemoryRememberedPayload {\n scope: MemoryScope;\n text: string;\n ts: string;\n type?: MemoryType | undefined;\n tags?: string[] | undefined;\n priority?: MemoryPriority | undefined;\n}\n\nexport interface MemoryForgottenPayload {\n scope: MemoryScope;\n query: string;\n removed: number;\n}\n\nexport interface MemoryClearedPayload {\n /** Scope that was cleared, or undefined when all scopes were cleared. */\n scope?: MemoryScope | undefined;\n}\n\nexport interface MemoryConsolidatedPayload {\n scope: MemoryScope;\n /** Entries removed by deduplication. */\n removed: number;\n}\n\n// ── Relevance scoring ──────────────────────────────────────────────────\n\n/**\n * Context used to score memory relevance for context injection.\n * Passed by the system prompt builder.\n */\nexport interface MemoryRelevanceContext {\n /** Current user message or task description. */\n currentTask: string;\n /** Active skills in this session (e.g. [\"typescript-strict\", \"git-flow\"]). */\n activeSkills?: string[] | undefined;\n /** Active mode (e.g. \"Teach\", \"Brief\", \"Code Reviewer\"). */\n activeMode?: string | undefined;\n /** Available tools — memories referencing relevant tools score higher. */\n toolNames?: string[] | undefined;\n}\n\nexport interface ScoredEntry extends MemoryEntry {\n score: number;\n matchReason: string;\n}\n\n// ── Store interface ────────────────────────────────────────────────────\n\nexport interface MemoryStore {\n readAll(): Promise<string>;\n read(scope: MemoryScope): Promise<string>;\n remember(text: string, scope?: MemoryScope, metadata?: Omit<Partial<MemoryEntry>, 'scope' | 'text' | 'ts'>): Promise<void>;\n forget(query: string, scope?: MemoryScope): Promise<number>;\n consolidate(scope: MemoryScope): Promise<void>;\n clear(scope?: MemoryScope): Promise<void>;\n /** List entries, newest first. */\n list(scope?: MemoryScope, limit?: number): Promise<MemoryEntry[]>;\n /** Search by content (substring or semantic). */\n search(query: string, scope?: MemoryScope, limit?: number): Promise<MemoryEntry[]>;\n /** Access the backend for advanced queries. */\n getBackend?(): unknown;\n /** Graph-based related memory traversal. */\n findRelated?(text: string, scope?: MemoryScope, limit?: number): Promise<MemoryEntry[]>;\n /**\n * Score and rank memories by relevance to the current context.\n * Returns only entries that meet a relevance threshold.\n */\n scoreRelevant?(ctx: MemoryRelevanceContext, scope?: MemoryScope, limit?: number): Promise<ScoredEntry[]>;\n /**\n * Attach a trace ID to this store so that all subsequent `storage.*`\n * events include it for observability correlation. Mutates the store\n * in place and returns the same instance (convenience chaining).\n */\n withTraceId(traceId: string): MemoryStore;\n}\n","import { randomUUID } from 'node:crypto';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { MemoryEntry, MemoryScope } from '../types/memory.js';\nimport { MEMORY_TYPE_LABELS, type MemoryPriority, type MemoryType } from '../types/memory.js';\nimport { atomicWrite, ensureDir, withFileLock } from '../utils/atomic-write.js';\nimport type { WstackPaths } from '../utils/wstack-paths.js';\n\n// ── Backend interface ──────────────────────────────────────────────────\n\nexport interface MemoryBackend {\n readonly kind: string;\n remember(scope: MemoryScope, entry: MemoryEntry, filePath: string): Promise<void>;\n forget(scope: MemoryScope, query: string, filePath: string): Promise<number>;\n readAll(scope: MemoryScope, filePath: string): Promise<string>;\n list(scope: MemoryScope, filePath: string, limit?: number | undefined): Promise<MemoryEntry[]>;\n search(scope: MemoryScope, query: string, filePath: string, limit?: number | undefined): Promise<MemoryEntry[]>;\n /** Find memories related to the given text via graph traversal. Optional — falls back to search. */\n findRelated?(scope: MemoryScope, filePath: string, text: string, limit: number): Promise<MemoryEntry[]>;\n clear(scope: MemoryScope, filePath: string): Promise<void>;\n consolidate(scope: MemoryScope, filePath: string): Promise<number>;\n}\n\n// ── Entry serialization format ─────────────────────────────────────────\n//\n// Full format:\n// - [ISO] [TYPE|PRIORITY] mem_<id> text content #tag1 #tag2\n//\n// Examples:\n// - [2026-06-07T...] mem_1234_abcd Project uses pnpm #pnpm #build\n// - [2026-06-07T...] [convention|high] mem_5678_ef01 Use conventional commits #git #commit\n//\n// Old format (backward compatible):\n// - [ISO] mem_<id> text content\n\nconst TYPE_PRIORITY_RE = /^\\[(\\w+)\\|(\\w+)\\]\\s+/;\nconst TAG_RE = /#([\\w-]+)/g;\nconst MAX_MEMORY_CONSOLIDATE_BACKUPS = 5;\n\nfunction formatMetadata(entry: MemoryEntry): string {\n const parts: string[] = [];\n if (entry.type && entry.priority) {\n parts.push(`[${entry.type}|${entry.priority}]`);\n } else if (entry.type) {\n parts.push(`[${entry.type}]`);\n } else if (entry.priority) {\n parts.push(`[${entry.priority}]`);\n }\n if (entry.tags && entry.tags.length > 0) {\n parts.push(entry.tags.map((t) => `#${t}`).join(' '));\n }\n return parts.length > 0 ? ` ${parts.join(' ')}` : '';\n}\n\nfunction lineToEntry(line: string, scope: MemoryScope): MemoryEntry | null {\n const trimmed = line.trim();\n if (!trimmed.startsWith('- [')) return null;\n\n // Parse timestamp: `- [ISO] ...`\n const tsMatch = trimmed.match(/^-\\s*\\[([^\\]]+)\\]/);\n if (!tsMatch) return null;\n const ts = tsMatch[1] ?? '';\n\n let rest = trimmed.slice(tsMatch[0].length).trim();\n\n // Parse optional type|priority: `[convention|high]` or `[fact]`\n let type: MemoryType | undefined;\n let priority: MemoryPriority | undefined;\n const tpMatch = rest.match(TYPE_PRIORITY_RE);\n if (tpMatch) {\n const a = tpMatch[1] ?? '';\n const b = tpMatch[2] ?? '';\n if (isMemoryType(a)) {\n type = a;\n priority = isPriority(b) ? b : undefined;\n } else if (isPriority(a)) {\n priority = a;\n }\n rest = rest.slice(tpMatch[0].length).trim();\n }\n\n // Parse optional entry ID: `mem_<ts>_<rand>`\n const idMatch = rest.match(/^mem_\\d+_\\w+\\s+/);\n let text: string;\n if (idMatch) {\n text = rest.slice(idMatch[0].length).trim();\n } else {\n text = rest.trim();\n }\n\n // Extract #tags from text\n const tags: string[] = [];\n let tagMatch: RegExpExecArray | null;\n TAG_RE.lastIndex = 0;\n // biome-ignore lint/suspicious/noAssignInExpressions: standard regex loop\n while ((tagMatch = TAG_RE.exec(text)) !== null) {\n tags.push(tagMatch[1] ?? '');\n }\n // Remove tags from display text\n const cleanText = text.replace(TAG_RE, '').replace(/\\s{2,}/g, ' ').trim();\n\n if (!cleanText) return null;\n\n return {\n scope,\n text: cleanText,\n ts,\n type,\n priority,\n tags: tags.length > 0 ? tags : undefined,\n };\n}\n\nfunction isMemoryType(s: string): s is MemoryType {\n return s in MEMORY_TYPE_LABELS;\n}\n\nfunction isPriority(s: string): s is MemoryPriority {\n return s === 'critical' || s === 'high' || s === 'medium' || s === 'low';\n}\n\n// ── File-based backend ─────────────────────────────────────────────────\n\nexport interface FileMemoryBackendOptions {\n paths: WstackPaths;\n}\n\nexport class FileMemoryBackend implements MemoryBackend {\n readonly kind = 'file';\n private readonly files: Record<MemoryScope, string>;\n\n constructor(opts: FileMemoryBackendOptions) {\n this.files = {\n 'project-agents': opts.paths.inProjectAgentsFile,\n 'project-memory': opts.paths.projectMemory,\n 'user-memory': opts.paths.globalMemory,\n };\n }\n\n private resolveFile(filePath: string, scope: MemoryScope): string {\n return filePath || this.files[scope];\n }\n\n async remember(scope: MemoryScope, entry: MemoryEntry, filePath: string): Promise<void> {\n const file = this.resolveFile(filePath, scope);\n await ensureDir(path.dirname(file));\n let existing = '';\n try { existing = await fs.readFile(file, 'utf8'); } catch { /* new file */ }\n\n const id = `mem_${Date.now()}_${randomUUID().slice(0, 8)}`;\n const meta = formatMetadata(entry);\n const line = `\\n- [${entry.ts}] ${id}${meta} ${entry.text.replace(/\\n/g, ' ')}\\n`;\n const next = existing.trim()\n ? existing.replace(/\\n+$/, '') + line\n : `# Agent Memory\\n${line}`;\n await atomicWrite(file, next);\n }\n\n async forget(scope: MemoryScope, query: string, filePath: string): Promise<number> {\n const file = this.resolveFile(filePath, scope);\n return withFileLock(file, async () => {\n let existing: string;\n try { existing = await fs.readFile(file, 'utf8'); } catch { return 0; /* best-effort */ }\n\n const needle = query.toLowerCase();\n const idMatcher = /mem_\\d+_\\w+/;\n let removed = 0;\n const lines = existing.split('\\n').filter((line) => {\n const trimmed = line.trim();\n if (!trimmed.startsWith('- ')) return true;\n if (idMatcher.test(query)) {\n const entryIdMatch = /mem_\\d+_\\w+/.exec(trimmed);\n if (entryIdMatch && entryIdMatch[0] === query) { removed++; return false; }\n }\n if (trimmed.toLowerCase().includes(needle)) { removed++; return false; }\n return true;\n });\n if (removed > 0) {\n if (lines.length === 0 || (lines.length === 1 && !lines[0]?.trim())) {\n await atomicWrite(file, '');\n } else {\n await atomicWrite(file, lines.join('\\n'));\n }\n }\n return removed;\n });\n }\n\n async readAll(scope: MemoryScope, filePath: string): Promise<string> {\n const file = this.resolveFile(filePath, scope);\n try { return await fs.readFile(file, 'utf8'); } catch { return ''; /* best-effort */ }\n }\n\n async list(scope: MemoryScope, filePath: string, limit?: number): Promise<MemoryEntry[]> {\n const raw = await this.readAll(scope, filePath);\n if (!raw.trim()) return [];\n const entries = parseEntries(raw, scope);\n return limit ? entries.slice(0, limit) : entries;\n }\n\n async search(scope: MemoryScope, query: string, filePath: string, limit?: number): Promise<MemoryEntry[]> {\n const entries = await this.list(scope, filePath);\n const needle = query.toLowerCase().split(/\\s+/);\n\n // Score by word overlap + tag match\n const scored = entries.map((e) => {\n const words = e.text.toLowerCase().split(/\\s+/);\n let score = 0;\n for (const n of needle) {\n if (words.some((w) => w.includes(n))) score += 1;\n // Tag matches are weighted higher\n if (e.tags?.some((t) => t.toLowerCase().includes(n))) score += 2;\n }\n return { entry: e, score };\n });\n\n scored.sort((a, b) => b.score - a.score);\n const matched = scored.filter((s) => s.score > 0).map((s) => s.entry);\n return limit ? matched.slice(0, limit) : matched;\n }\n\n async clear(scope: MemoryScope, filePath: string): Promise<void> {\n const file = this.resolveFile(filePath, scope);\n await atomicWrite(file, '');\n }\n\n async consolidate(scope: MemoryScope, filePath: string): Promise<number> {\n const file = this.resolveFile(filePath, scope);\n let existing: string;\n try { existing = await fs.readFile(file, 'utf8'); } catch { return 0; /* best-effort */ }\n\n const seen = new Set<string>();\n let removed = 0;\n const lines = existing.split('\\n').filter((line) => {\n const trimmed = line.trim();\n if (!trimmed.startsWith('- ')) return true;\n // Normalize: strip timestamp, ID, type|priority, tags\n const norm = trimmed\n .replace(/\\[[^\\]]+\\]/g, '')\n .replace(/\\bmem_\\d+_\\w+\\s*/, '')\n .replace(/#[\\w-]+/g, '')\n .replace(/\\s+/g, ' ')\n .trim()\n .toLowerCase();\n if (seen.has(norm)) { removed++; return false; }\n seen.add(norm);\n return true;\n });\n\n const next = lines.join('\\n');\n const backup = `${file}.bak.${Date.now()}`;\n try {\n await fs.copyFile(file, backup);\n await pruneConsolidateBackups(file);\n } catch { /* best-effort */ }\n /* v8 ignore next -- best-effort: atomicWrite failure during consolidate is non-fatal */\n try { await atomicWrite(file, next); } catch { return 0; /* best-effort */ }\n return removed;\n }\n}\n\nasync function pruneConsolidateBackups(file: string): Promise<void> {\n const dir = path.dirname(file);\n const base = path.basename(file);\n const prefix = `${base}.bak.`;\n const backups = (await fs.readdir(dir))\n .filter((name) => name.startsWith(prefix))\n .sort()\n .reverse();\n\n await Promise.all(\n backups.slice(MAX_MEMORY_CONSOLIDATE_BACKUPS).map(async (name) => {\n try {\n await fs.unlink(path.join(dir, name));\n } catch {\n // best-effort\n }\n }),\n );\n}\n\n// ── Entry parsing ──────────────────────────────────────────────────────\n\nexport function parseEntries(raw: string, scope: MemoryScope = 'project-memory'): MemoryEntry[] {\n const entries: MemoryEntry[] = [];\n for (const line of raw.split('\\n')) {\n const entry = lineToEntry(line, scope);\n if (entry) entries.push(entry);\n }\n return entries.reverse(); // newest first\n}\n","import type {\n MemoryClearedPayload,\n MemoryConsolidatedPayload,\n MemoryEntry,\n MemoryForgottenPayload,\n MemoryRelevanceContext,\n MemoryRememberedPayload,\n MemoryScope,\n MemoryStore,\n ScoredEntry,\n} from '../types/memory.js';\nimport type { EventBus } from '../kernel/events.js';\nimport type { WstackPaths } from '../utils/wstack-paths.js';\nimport { toErrorMessage } from '../utils/error.js';\nimport { type MemoryBackend, FileMemoryBackend } from './memory-backend.js';\n\nconst MAX_BYTES_TOTAL = 32_000; // ~8K tokens\n\nexport interface MemoryStoreOptions {\n paths: WstackPaths;\n /**\n * Optional event bus — when provided, mutations emit events so plugins\n * and other subsystems can react to memory changes.\n */\n events?: EventBus | undefined;\n /**\n * Storage backend. Defaults to FileMemoryBackend when omitted.\n * Plugins can register a custom backend (graph, semantic, vector)\n * via the DI container to override storage behavior.\n */\n backend?: MemoryBackend | undefined;\n}\n\n/**\n * Three scopes:\n * project-agents → <project>/.wrongstack/AGENTS.md (committed)\n * project-memory → ~/.wrongstack/projects/<hash>/memory.md (per-project agent notes)\n * user-memory → ~/.wrongstack/memory.md (global personal memory)\n */\nexport class DefaultMemoryStore implements MemoryStore {\n private readonly files: Record<MemoryScope, string>;\n private readonly events?: EventBus | undefined;\n private traceId?: string | undefined;\n private readonly backend: MemoryBackend;\n\n /**\n * Per-scope serialization queue. `remember` / `forget` / `consolidate` /\n * `clear` are read-modify-write against a single file; without a lock,\n * two concurrent calls on the same scope can read the same baseline and\n * the later write silently drops the earlier entry. We chain each\n * mutation onto the prior promise for the same scope so they run in\n * issue order. Different scopes still proceed in parallel.\n *\n * The chain tracks only the last pending write. If a write fails, its\n * error is caught and swallowed so the chain stays alive for subsequent\n * calls. The error is stored in `writeErrors` so callers can learn about\n * it on the next read operation.\n */\n private readonly writeChain = new Map<MemoryScope, Promise<unknown>>();\n /** Last write error per scope — surfaced as warnings on the next readAll(). */\n private readonly writeErrors = new Map<MemoryScope, Error>();\n\n /**\n * When the global root is a temporary directory (opencode, CI sandboxes),\n * memory files are also mirrored to the project tree so they survive\n * session cleanup. The primary path stays in the temp root for isolation;\n * this backup ensures memory is never lost.\n */\n private readonly persistBackup: boolean;\n private readonly backupDir: string;\n /**\n * Per-scope tracked byte sizes — incremented on `remember()`, decremented on\n * `forget()`, recalculated after `consolidate()`. Eliminates the redundant\n * readAll() call that previously checked the file size after every write.\n */\n private readonly _trackedByteSizes: Partial<Record<MemoryScope, number>> = {};\n\n /** Result cache for scoreRelevant() — keyed by scope + context hash, TTL 30s. */\n private readonly _scoreCache = new Map<string, { entries: MemoryEntry[]; scored: ScoredEntry[]; expiresAt: number }>();\n\n /**\n * Per-entry cached lowercase strings — computed once per scoreRelevant() call,\n * stored here so repeated scoring of the same entries avoids re-computation.\n * Cleared on every mutation (remember/forget/consolidate/clear).\n */\n private _cachedLower: WeakMap<MemoryEntry, { textLower: string; tagsLower: string[] }> | null = null;\n\n constructor(opts: MemoryStoreOptions) {\n this.files = {\n 'project-agents': opts.paths.inProjectAgentsFile,\n 'project-memory': opts.paths.projectMemory,\n 'user-memory': opts.paths.globalMemory,\n };\n this.events = opts.events;\n this.backend = opts.backend ?? new FileMemoryBackend({ paths: opts.paths });\n\n // Detect temporary global roots: opencode, CI, test sandboxes.\n // When detected, mirror writes to the project's .wrongstack/ dir.\n const root = opts.paths.globalRoot.toLowerCase();\n this.persistBackup = /[/\\\\](tmp|temp|cache)[/\\\\]/.test(root);\n this.backupDir = this.persistBackup\n ? opts.paths.inProjectAgentsFile.replace(/AGENTS\\.md$/, 'memory-persist')\n : '';\n }\n\n /** Expose the backend for plugin introspection and advanced queries. */\n getBackend(): MemoryBackend {\n return this.backend;\n }\n\n private async runSerialized<T>(scope: MemoryScope, work: () => Promise<T>): Promise<T> {\n const prior = this.writeChain.get(scope) ?? Promise.resolve();\n // Chain: catch errors from the prior write, then run the next work item.\n const next = prior\n .catch((err) => {\n this.writeErrors.set(scope, err as Error);\n })\n .then(() => work());\n this.writeChain.set(scope, next as Promise<unknown>);\n try {\n return await next;\n } catch (err) {\n this.writeErrors.set(scope, err as Error);\n throw err;\n } finally {\n if (this.writeChain.get(scope) === next) {\n this.writeChain.delete(scope);\n }\n }\n }\n\n /**\n * Recalculate the tracked byte size for a scope by re-reading the file and\n * summing the serialized byte length of each line. Called after consolidate()\n * (which modifies the file) to keep the tracker accurate.\n */\n private async _recalcTrackedByteSize(scope: MemoryScope): Promise<number> {\n const raw = await this.backend.readAll(scope, this.files[scope]);\n let total = 0;\n for (const line of raw.split('\\n')) {\n if (line.trim()) total += Buffer.byteLength(line, 'utf8');\n }\n this._trackedByteSizes[scope] = total;\n return total;\n }\n\n async readAll(): Promise<string> {\n const parts: string[] = [];\n for (const scope of ['project-agents', 'project-memory', 'user-memory'] as MemoryScope[]) {\n const writeErr = this.writeErrors.get(scope);\n if (writeErr) {\n parts.push(`> ⚠️ Memory write error (${labelOf(scope)}): ${writeErr.message}`);\n }\n const t0 = Date.now();\n const filePath = this.files[scope];\n try {\n const body = await this.backend.readAll(scope, filePath);\n const dur = Date.now() - t0;\n this.events?.emit('storage.read', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'readAll',\n outcome: 'success',\n durationMs: dur,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n if (body.trim()) parts.push(`## ${labelOf(scope)}\\n\\n${body.trim()}`);\n } catch (err) {\n const dur = Date.now() - t0;\n this.events?.emit('storage.read', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'readAll',\n outcome: 'failure',\n durationMs: dur,\n error: toErrorMessage(err),\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n throw err;\n }\n }\n return parts.join('\\n\\n');\n }\n\n async read(scope: MemoryScope): Promise<string> {\n const t0 = Date.now();\n const filePath = this.files[scope];\n try {\n const body = await this.backend.readAll(scope, filePath);\n const dur = Date.now() - t0;\n this.events?.emit('storage.read', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'read',\n outcome: 'success',\n durationMs: dur,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n return body;\n } catch (err) {\n const dur = Date.now() - t0;\n this.events?.emit('storage.read', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'read',\n outcome: 'failure',\n durationMs: dur,\n error: toErrorMessage(err),\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n throw err;\n }\n }\n\n /**\n * List entries from a scope, newest first. Delegates to the backend\n * so graph/semantic backends can return enriched or filtered results.\n */\n async list(scope: MemoryScope = 'project-memory', limit?: number): Promise<MemoryEntry[]> {\n return this.backend.list(scope, this.files[scope], limit);\n }\n\n /**\n * Find memories related to the given text via graph traversal.\n * Falls back to content search when no graph backend is available.\n */\n async findRelated(text: string, scope: MemoryScope = 'project-memory', limit = 5): Promise<MemoryEntry[]> {\n if (this.backend.findRelated) {\n return this.backend.findRelated(scope, this.files[scope], text, limit);\n }\n return this.search(text, scope, limit);\n }\n\n async search(query: string, scope: MemoryScope = 'project-memory', limit?: number): Promise<MemoryEntry[]> {\n return this.backend.search(scope, query, this.files[scope], limit);\n }\n\n async remember(\n text: string,\n scope: MemoryScope = 'project-memory',\n metadata?: Omit<Partial<MemoryEntry>, 'scope' | 'text' | 'ts'>,\n ): Promise<void> {\n const ts = new Date().toISOString();\n return this.runSerialized(scope, async () => {\n const entry: MemoryEntry = { scope, text, ts, ...metadata };\n const filePath = this.files[scope];\n const t0 = Date.now();\n try {\n await this.backend.remember(scope, entry, filePath);\n // Invalidate the score cache — entries have changed.\n this._scoreCache.clear();\n const dur = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'remember',\n outcome: 'success',\n durationMs: dur,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n } catch (err) {\n const dur = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'remember',\n outcome: 'failure',\n durationMs: dur,\n error: toErrorMessage(err),\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n throw err;\n }\n\n // Size check — consolidate if the tracked byte size exceeds the cap.\n // Tracked size is updated incrementally; lazily initialized from the file\n // on first mutation if not yet tracked (handles the case where the store was\n // constructed but not yet mutated, or after a restart).\n let trackedSize = this._trackedByteSizes[scope];\n if (trackedSize === undefined) {\n trackedSize = await this._recalcTrackedByteSize(scope);\n }\n if (trackedSize > MAX_BYTES_TOTAL) {\n const removed = await this.backend.consolidate(scope, this.files[scope]);\n if (removed > 0) {\n this.events?.emit('memory.consolidated', {\n scope,\n removed,\n } satisfies MemoryConsolidatedPayload);\n // Recalculate after consolidation so the tracked size stays accurate.\n await this._recalcTrackedByteSize(scope);\n }\n }\n\n // Increment the tracked byte size for this scope.\n this._trackedByteSizes[scope] = (this._trackedByteSizes[scope] ?? 0) + Buffer.byteLength(JSON.stringify(entry), 'utf8');\n\n // Mirror to persistent backup when running in a temp sandbox.\n await this.mirrorBackup(scope);\n\n this.events?.emit('memory.remembered', {\n scope,\n text,\n ts,\n type: entry.type,\n tags: entry.tags,\n priority: entry.priority,\n } satisfies MemoryRememberedPayload);\n });\n }\n\n /**\n * Score and rank memories by relevance to the current context.\n * Returns entries with score >= MIN_RELEVANCE_SCORE, sorted highest first.\n */\n async scoreRelevant(\n ctx: MemoryRelevanceContext,\n scope: MemoryScope = 'project-memory',\n limit = 8,\n ): Promise<ScoredEntry[]> {\n const all = await this.list(scope);\n if (all.length === 0) return [];\n\n // Build a context fingerprint for cache lookup.\n const ctxHash =\n `${scope}|${ctx.currentTask}|${(ctx.activeSkills ?? []).join(',')}|${(ctx.toolNames ?? []).join(',')}`;\n const now = Date.now();\n const TTL_MS = 30_000; // 30-second cache window\n\n // Check the TTL cache first — return cached scored results if the same entries\n // and context were scored within the last 30 seconds.\n const cached = this._scoreCache.get(ctxHash);\n if (cached && cached.expiresAt > now && cached.entries === all) {\n return cached.scored.slice(0, Math.min(limit, 15));\n }\n\n const taskWords = ctx.currentTask.toLowerCase().split(/\\s+/).filter((w) => w.length > 2);\n const skillWords = (ctx.activeSkills ?? []).flatMap((s) => s.split('-'));\n const toolWords = (ctx.toolNames ?? []).flatMap((t) => t.toLowerCase().split('_'));\n\n // Pre-build per-entry lowercase caches for this scoring pass. Reused below so\n // we only call toLowerCase() once per entry instead of 3× per scoring loop.\n this._cachedLower = new WeakMap<MemoryEntry, { textLower: string; tagsLower: string[] }>();\n\n const scored: ScoredEntry[] = [];\n\n for (const entry of all) {\n let score = 0;\n const reasons: string[] = [];\n\n // Use cached lowercase strings from the WeakMap; compute and store on first use.\n let cachedLower = this._cachedLower.get(entry);\n if (!cachedLower) {\n cachedLower = {\n textLower: entry.text.toLowerCase(),\n tagsLower: (entry.tags ?? []).map((t) => t.toLowerCase()),\n };\n this._cachedLower.set(entry, cachedLower);\n }\n const { textLower, tagsLower } = cachedLower;\n\n // Word overlap with current task (primary signal)\n let taskHits = 0;\n for (const w of taskWords) {\n if (textLower.includes(w)) { taskHits++; score += 2; }\n if (tagsLower.some((t) => t.includes(w))) { taskHits++; score += 3; }\n }\n if (taskHits > 0) reasons.push(`task match (${taskHits})`);\n\n // Skill/tool relevance\n let skillHits = 0;\n for (const w of skillWords) {\n if (w.length > 2 && (textLower.includes(w) || tagsLower.some((t) => t.includes(w)))) {\n skillHits++;\n }\n }\n score += skillHits;\n if (skillHits > 0) reasons.push(`skill match (${skillHits})`);\n\n for (const w of toolWords) {\n if (w.length > 2 && (textLower.includes(w) || tagsLower.some((t) => t.includes(w)))) {\n score += 1;\n reasons.push(`tool mention: ${w}`);\n }\n }\n\n // Priority boost\n switch (entry.priority) {\n case 'critical': score += 5; reasons.push('critical'); break;\n case 'high': score += 3; reasons.push('high priority'); break;\n case 'medium': score += 1; break;\n case 'low': score -= 2; reasons.push('low priority'); break;\n }\n\n // Type boost — decisions, conventions, anti-patterns are high-value\n switch (entry.type) {\n case 'decision': score += 2; reasons.push('decision'); break;\n case 'convention': score += 2; reasons.push('convention'); break;\n case 'anti_pattern': score += 3; reasons.push('anti-pattern'); break;\n case 'preference': score += 1; reasons.push('preference'); break;\n case 'reference': break;\n case 'fact': break;\n }\n\n // Recency boost — newer entries get +1, very old get 0\n const ageDays = (now - new Date(entry.ts).getTime()) / (1000 * 60 * 60 * 24);\n if (ageDays < 1) score += 1;\n else if (ageDays > 30) score -= 1;\n\n // Confidence penalty\n if (entry.confidence !== undefined && entry.confidence < 0.5) {\n score -= 2;\n reasons.push('low confidence');\n }\n\n // Repetition avoidance — recently accessed entries get slight penalty\n if (entry.lastAccessed) {\n const hoursSinceAccess = (now - new Date(entry.lastAccessed).getTime()) / (1000 * 60 * 60);\n if (hoursSinceAccess < 1) score -= 1;\n }\n\n if (score > 0) {\n scored.push({\n ...entry,\n score,\n matchReason: reasons.join(', ') || 'keyword match',\n });\n }\n }\n\n scored.sort((a, b) => b.score - a.score);\n\n // Filter to entries that meet the minimum relevance threshold.\n // Critical or high-priority entries always pass.\n const threshold = 2;\n const relevant = scored.filter(\n (s) => s.score >= threshold || s.priority === 'critical' || s.priority === 'high',\n );\n\n // Cache the full scored result for 30 seconds — cleared on every mutation.\n this._scoreCache.set(ctxHash, { entries: all, scored: relevant, expiresAt: now + TTL_MS });\n\n return relevant.slice(0, Math.min(limit, 15));\n }\n\n async forget(query: string, scope: MemoryScope = 'project-memory'): Promise<number> {\n return this.runSerialized(scope, async () => {\n const filePath = this.files[scope];\n const t0 = Date.now();\n let removed = 0;\n try {\n removed = await this.backend.forget(scope, query, filePath);\n // Invalidate the score cache — entries have changed.\n this._scoreCache.clear();\n const dur = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'forget',\n outcome: 'success',\n durationMs: dur,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n } catch (err) {\n const dur = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'forget',\n outcome: 'failure',\n durationMs: dur,\n error: toErrorMessage(err),\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n throw err;\n }\n if (removed > 0) {\n this.events?.emit('memory.forgotten', {\n scope,\n query,\n removed,\n } satisfies MemoryForgottenPayload);\n await this.mirrorBackup(scope);\n await this._recalcTrackedByteSize(scope);\n }\n return removed;\n });\n }\n\n async consolidate(scope: MemoryScope): Promise<void> {\n return this.runSerialized(scope, async () => {\n const filePath = this.files[scope];\n const t0 = Date.now();\n let removed = 0;\n try {\n removed = await this.backend.consolidate(scope, filePath);\n // Invalidate the score cache — entries have changed.\n this._scoreCache.clear();\n const dur = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'consolidate',\n outcome: 'success',\n durationMs: dur,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n } catch (err) {\n const dur = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'consolidate',\n outcome: 'failure',\n durationMs: dur,\n error: toErrorMessage(err),\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n throw err;\n }\n if (removed > 0) {\n this.events?.emit('memory.consolidated', {\n scope,\n removed,\n } satisfies MemoryConsolidatedPayload);\n await this.mirrorBackup(scope);\n await this._recalcTrackedByteSize(scope);\n }\n });\n }\n\n async clear(scope?: MemoryScope): Promise<void> {\n if (scope) {\n await this.runSerialized(scope, async () => {\n const filePath = this.files[scope];\n const t0 = Date.now();\n try {\n await this.backend.clear(scope, filePath);\n // Invalidate the score cache — entries have changed.\n this._scoreCache.clear();\n const dur = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'clear',\n outcome: 'success',\n durationMs: dur,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n } catch (err) {\n const dur = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'clear',\n outcome: 'failure',\n durationMs: dur,\n error: toErrorMessage(err),\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n throw err;\n }\n this.events?.emit('memory.cleared', { scope } satisfies MemoryClearedPayload);\n await this.mirrorBackup(scope);\n this._trackedByteSizes[scope] = 0;\n });\n return;\n }\n await Promise.all(\n (['project-agents', 'project-memory', 'user-memory'] as MemoryScope[]).map(async (s) =>\n this.runSerialized(s, async () => {\n const filePath = this.files[s];\n const t0 = Date.now();\n try {\n await this.backend.clear(s, filePath);\n const dur = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'clear',\n outcome: 'success',\n durationMs: dur,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n } catch (err) {\n const dur = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'clear',\n outcome: 'failure',\n durationMs: dur,\n error: toErrorMessage(err),\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n throw err;\n }\n this.events?.emit('memory.cleared', { scope: s } satisfies MemoryClearedPayload);\n await this.mirrorBackup(s);\n }),\n ),\n );\n }\n\n /**\n * Return a new MemoryStore proxy that carries `traceId` on every storage\n * event. The original store is left unchanged — callers that need a\n * trace-decorated view (e.g. session-run tools) receive the proxy while\n * the singleton remains trace-free for boot-time use.\n *\n * The proxy implements the full `MemoryStore` interface; all other\n * properties (backend, etc.) are delegated to the original store.\n */\n withTraceId(traceId: string): MemoryStore {\n // Mutate the singleton's traceId so that all subsequent I/O (including\n // calls from tools that captured the original store reference) emits\n // storage events with the correct session trace ID.\n this.traceId = traceId;\n return this;\n }\n private async mirrorBackup(scope: MemoryScope): Promise<void> {\n if (!this.persistBackup || scope === 'project-agents') return;\n try {\n const content = await this.backend.readAll(scope, this.files[scope]);\n const { writeFile, mkdir } = await import('node:fs/promises');\n await mkdir(this.backupDir, { recursive: true });\n await writeFile(`${this.backupDir}/${scope}.md`, content, 'utf8');\n } catch {\n // best-effort\n }\n }\n}\n\nfunction labelOf(scope: MemoryScope): string {\n switch (scope) {\n case 'project-agents':\n return 'Project AGENTS.md';\n case 'project-memory':\n return 'Project memory';\n case 'user-memory':\n return 'User memory';\n }\n}\n","import * as fs from 'node:fs/promises';\nimport type { MemoryEntry, MemoryScope } from '../types/memory.js';\nimport { type FileMemoryBackendOptions, FileMemoryBackend } from './memory-backend.js';\nimport type { MemoryBackend } from './memory-backend.js';\n\n// ── Graph node and edge types ──────────────────────────────────────────\n\ninterface GraphNode {\n id: string;\n entry: MemoryEntry;\n firstSeen: string;\n count: number;\n /** Extracted metadata for fast lookup. */\n type?: MemoryEntry['type'] | undefined;\n tags?: string[] | undefined;\n priority?: MemoryEntry['priority'] | undefined;\n}\n\ninterface GraphEdge {\n from: string;\n to: string;\n /** Why these nodes are related. */\n relation: 'co_occurring' | 'similar' | 'same_turn' | 'explicit';\n weight: number;\n ts: string;\n}\n\n// ── Backend ────────────────────────────────────────────────────────────\n\nexport interface GraphMemoryBackendOptions extends FileMemoryBackendOptions {\n /**\n * Path to the graph metadata file (edges + node metadata).\n * Defaults to `<projectDir>/memory-graph.json`.\n */\n graphPath?: string | undefined;\n}\n\n/**\n * Graph-based memory backend that tracks relationships between entries.\n * Builds on top of FileMemoryBackend — entries are still persisted as\n * markdown bullets, but the graph layer adds:\n *\n * - Co-occurrence edges (entries from the same remember() batch)\n * - Content similarity edges (simple Jaccard on word overlap)\n * - Turn-based edges (entries created in the same LLM turn)\n * - Graph traversal queries (find related memories)\n *\n * The graph metadata persists to `<projectDir>/memory-graph.json`.\n */\nexport class GraphMemoryBackend implements MemoryBackend {\n readonly kind = 'graph';\n\n private readonly file: FileMemoryBackend;\n private readonly graphFile: string;\n\n // In-memory graph state — lazily loaded, saved on mutation.\n private nodes = new Map<string, GraphNode>();\n private edges: GraphEdge[] = [];\n private loadedScope: MemoryScope | null = null;\n private loaded = false;\n\n /**\n * Inverted index for O(1) term → node lookup during search.\n * Built incrementally on remember/forget, rebuilt on loadGraph if absent.\n * Maps lowercase term (min 3 chars) → Set of node IDs containing that term.\n */\n private invertedIndex = new Map<string, Set<string>>();\n\n /** Minimum term length to index — avoids noise from 1-2 char fragments. */\n private static readonly MIN_TERM_LEN = 3;\n\n /**\n * Promise that resolves when the current in-flight _saveGraph completes.\n * Tests call flush() to await this before deleting the backend or its temp dir.\n * Each save operation chains onto the previous one so concurrent saves are serialised.\n */\n private _saveDone: Promise<void> = Promise.resolve();\n\n constructor(opts: GraphMemoryBackendOptions) {\n this.file = new FileMemoryBackend({ paths: opts.paths });\n this.graphFile = opts.graphPath ?? `${opts.paths.projectDir}/memory-graph.json`;\n }\n\n // ── Backend interface ──────────────────────────────────────────────\n\n async remember(scope: MemoryScope, entry: MemoryEntry, filePath: string): Promise<void> {\n await this.file.remember(scope, entry, filePath);\n await this.loadGraph(scope);\n\n const nodeId = this.nodeId(entry);\n const existing = this.nodes.get(nodeId);\n if (existing) {\n existing.count++;\n existing.entry = entry;\n existing.type = entry.type;\n existing.tags = entry.tags;\n existing.priority = entry.priority;\n // Update inverted index for the modified node's text and tags\n this.updateNodeIndex(nodeId, entry);\n } else {\n this.nodes.set(nodeId, {\n id: nodeId,\n entry,\n firstSeen: entry.ts,\n count: 1,\n type: entry.type,\n tags: entry.tags,\n priority: entry.priority,\n });\n\n // Index the new node in the inverted index\n this.indexNode(nodeId, entry);\n\n // Create similarity edges — but only against the last SIMILARITY_WINDOW most\n // recent nodes instead of the full in-memory set. This converts O(N²) on\n // every remember() into O(K) where K is a small constant (100), making\n // remember() O(1) amortized regardless of how many entries are stored.\n const SIMILARITY_WINDOW = 100;\n const recentNodes = [...this.nodes.values()].slice(-SIMILARITY_WINDOW);\n for (const other of recentNodes) {\n if (other.id === nodeId) continue;\n const sim = wordOverlap(entry.text, other.entry.text);\n const tagSim = sharedTags(entry.tags ?? [], other.tags ?? []);\n const weight = Math.max(sim, tagSim * 0.5);\n if (weight > 0.15) {\n this.edges.push({\n from: nodeId,\n to: other.id,\n relation: sim >= tagSim ? 'similar' : 'same_turn',\n weight,\n ts: entry.ts,\n });\n }\n }\n }\n\n // Await the graph save to ensure flush() sees the file on disk before\n // cleanup. Unlike memory-consolidator (LLM call, 15s), this is a fast fs operation\n // and the caller's event loop is already freed by not awaiting file.remember().\n this._saveDone = this._saveGraph(scope);\n await this._saveDone;\n }\n\n async forget(scope: MemoryScope, query: string, filePath: string): Promise<number> {\n const removed = await this.file.forget(scope, query, filePath);\n if (removed > 0) {\n await this.loadGraph(scope);\n // Remove nodes whose entry text matches the query\n const n = query.toLowerCase();\n const toRemove: string[] = [];\n for (const [id, node] of this.nodes) {\n if (node.entry.text.toLowerCase().includes(n)) {\n toRemove.push(id);\n }\n }\n for (const id of toRemove) {\n // Remove from inverted index before deleting the node\n this.removeNodeFromIndex(id, this.nodes.get(id)?.entry);\n this.nodes.delete(id);\n }\n this.edges = this.edges.filter((e) => !toRemove.includes(e.from) && !toRemove.includes(e.to));\n this._saveDone = this._saveGraph(scope);\n await this._saveDone;\n }\n return removed;\n }\n\n async readAll(scope: MemoryScope, filePath: string): Promise<string> {\n return this.file.readAll(scope, filePath);\n }\n\n async list(scope: MemoryScope, filePath: string, limit?: number): Promise<MemoryEntry[]> {\n await this.loadGraph(scope);\n // Merge: file entries are canonical, graph adds metadata and dedup\n const fileEntries = await this.file.list(scope, filePath);\n const nodeMap = new Map(this.nodes.entries());\n\n // Enrich file entries with graph metadata\n const enriched = fileEntries.map((fe) => {\n const nodeId = this.nodeId(fe);\n const node = nodeMap.get(nodeId);\n if (node) {\n return {\n ...fe,\n type: node.type ?? fe.type,\n tags: node.tags ?? fe.tags,\n priority: node.priority ?? fe.priority,\n };\n }\n return fe;\n });\n\n // Add graph-only nodes not in file (shouldn't happen normally, but safety)\n const fileIds = new Set(fileEntries.map((e) => this.nodeId(e)));\n for (const [id, node] of this.nodes) {\n if (!fileIds.has(id)) {\n enriched.push(node.entry);\n }\n }\n\n enriched.sort((a, b) => b.ts.localeCompare(a.ts));\n return limit ? enriched.slice(0, limit) : enriched;\n }\n\n async search(scope: MemoryScope, query: string, _filePath: string, limit?: number): Promise<MemoryEntry[]> {\n await this.loadGraph(scope);\n const needle = query.toLowerCase().split(/\\s+/).filter((t) => t.length >= GraphMemoryBackend.MIN_TERM_LEN);\n\n // Use inverted index to find candidate nodes — O(K * avg_results) instead of O(N)\n const candidates = new Map<string, number>();\n for (const term of needle) {\n const nodeIds = this.invertedIndex.get(term);\n if (!nodeIds) continue;\n for (const nodeId of nodeIds) {\n const node = this.nodes.get(nodeId);\n if (!node || node.entry.scope !== scope) continue;\n // Count how many terms matched this node\n candidates.set(nodeId, (candidates.get(nodeId) ?? 0) + 1);\n }\n }\n\n // Also include high-priority entries even without lexical matches (priority boost > 0)\n // This preserves the original behavior where priority/count could surface entries\n // that don't match any query terms.\n for (const [nodeId, node] of this.nodes) {\n if (node.entry.scope !== scope) continue;\n if (candidates.has(nodeId)) continue; // Already in candidates\n // Include if priority boost > 0 (critical=3, high=2)\n if (node.priority === 'critical' || node.priority === 'high') {\n candidates.set(nodeId, 0); // 0 lexical matches but priority boost applies\n }\n }\n\n // Score candidates: text match (1pt/term), tag match (2pts/term), priority, count\n const scored: { entry: MemoryEntry; score: number }[] = [];\n for (const [nodeId] of candidates) {\n const node = this.nodes.get(nodeId)!;\n let score = 0;\n // Text match score: 1pt per matching term\n score += (candidates.get(nodeId) ?? 0) * 1;\n // Tag match score: 2pts per term that appears in any tag\n for (const term of needle) {\n if (node.entry.tags?.some((t) => t.toLowerCase().includes(term))) score += 2;\n }\n if (node.priority === 'critical') score += 3;\n else if (node.priority === 'high') score += 2;\n score += node.count * 0.5;\n scored.push({ entry: node.entry, score });\n }\n\n scored.sort((a, b) => b.score - a.score);\n const matched = scored.map((s) => s.entry);\n return limit ? matched.slice(0, limit) : matched;\n }\n\n async clear(scope: MemoryScope, filePath: string): Promise<void> {\n await this.file.clear(scope, filePath);\n this.nodes.clear();\n this.edges = [];\n this.invertedIndex = new Map();\n this.loadedScope = scope;\n this.loaded = true;\n // Write empty graph\n try { await fs.unlink(this.graphFile); } catch { /* ok */ }\n }\n\n async consolidate(scope: MemoryScope, filePath: string): Promise<number> {\n return this.file.consolidate(scope, filePath);\n }\n\n // ── Graph-specific queries ─────────────────────────────────────────\n\n /**\n * Find memories related to the given entry, ordered by edge weight.\n */\n async findRelated(scope: MemoryScope, _filePath: string, entryText: string, limit = 5): Promise<MemoryEntry[]> {\n await this.loadGraph(scope);\n const targetId = this.nodeId({ scope, text: entryText, ts: '' });\n const related = this.edges\n .filter((e) => e.from === targetId || e.to === targetId)\n .sort((a, b) => b.weight - a.weight)\n .slice(0, limit);\n\n const result: MemoryEntry[] = [];\n for (const edge of related) {\n const otherId = edge.from === targetId ? edge.to : edge.from;\n const node = this.nodes.get(otherId);\n if (node) result.push(node.entry);\n }\n return result;\n }\n\n /**\n * Get all edges for visualization or traversal.\n */\n getGraph(): { nodes: GraphNode[]; edges: GraphEdge[] } {\n return {\n nodes: [...this.nodes.values()],\n edges: [...this.edges],\n };\n }\n\n // ── Persistence ────────────────────────────────────────────────────\n\n private nodeId(entry: MemoryEntry): string {\n // Stable ID from scope + normalized text\n const norm = entry.text.toLowerCase().trim().replace(/\\s+/g, ' ');\n return `${entry.scope ?? 'mem'}::${simpleHash(norm)}`;\n }\n\n private async loadGraph(scope: MemoryScope): Promise<void> {\n if (this.loaded && this.loadedScope === scope) return;\n try {\n const raw = await fs.readFile(this.graphFile, 'utf8');\n const data: { nodes: Array<[string, GraphNode]>; edges: GraphEdge[] } = JSON.parse(raw);\n this.nodes = new Map(data.nodes);\n this.edges = data.edges;\n } catch {\n this.nodes = new Map();\n this.edges = [];\n }\n // Build inverted index from loaded nodes\n this.buildInvertedIndex();\n this.loadedScope = scope;\n this.loaded = true;\n }\n\n /** Fire-and-forget graph persistence. Named _saveGraph to signal it must not be awaited. */\n private async _saveGraph(scope: MemoryScope): Promise<void> {\n this.loadedScope = scope;\n this.loaded = true;\n try {\n const data = {\n nodes: [...this.nodes.entries()],\n edges: this.edges,\n };\n const dir = this.graphFile.substring(0, this.graphFile.lastIndexOf('/'));\n await fs.mkdir(dir, { recursive: true });\n // Atomic write via temp file\n const tmp = `${this.graphFile}.tmp`;\n await fs.writeFile(tmp, JSON.stringify(data));\n await fs.rename(tmp, this.graphFile);\n } catch {\n // best-effort — graph is an enhancement, not critical\n }\n }\n\n /**\n * Wait for all in-flight _saveGraph operations to complete.\n * Call this before deleting the backend or its temp directory.\n */\n async flush(): Promise<void> {\n await this._saveDone;\n }\n\n // ── Inverted Index Helpers ───────────────────────────────────────────\n\n /**\n * Build the inverted index from all currently loaded nodes.\n * Called on loadGraph() to reconstruct the index after loading from disk.\n */\n private buildInvertedIndex(): void {\n this.invertedIndex = new Map();\n for (const [nodeId, node] of this.nodes) {\n for (const term of this.extractTerms(node.entry)) {\n let nodeIds = this.invertedIndex.get(term);\n if (!nodeIds) {\n nodeIds = new Set();\n this.invertedIndex.set(term, nodeIds);\n }\n nodeIds.add(nodeId);\n }\n }\n }\n\n /**\n * Index a node in the inverted index. Adds the node's ID to all term entries.\n */\n private indexNode(nodeId: string, entry: MemoryEntry): void {\n for (const term of this.extractTerms(entry)) {\n let nodeIds = this.invertedIndex.get(term);\n if (!nodeIds) {\n nodeIds = new Set();\n this.invertedIndex.set(term, nodeIds);\n }\n nodeIds.add(nodeId);\n }\n }\n\n /**\n * Remove a node's terms from the inverted index before deleting it.\n * Used in forget() and when updating existing nodes.\n */\n private removeNodeFromIndex(nodeId: string, entry?: MemoryEntry): void {\n if (!entry) return;\n for (const term of this.extractTerms(entry)) {\n const nodeIds = this.invertedIndex.get(term);\n if (nodeIds) {\n nodeIds.delete(nodeId);\n if (nodeIds.size === 0) {\n this.invertedIndex.delete(term);\n }\n }\n }\n }\n\n /**\n * Update an existing node's entries in the inverted index.\n * Removes old terms and adds new ones.\n */\n private updateNodeIndex(nodeId: string, entry: MemoryEntry): void {\n // Remove old entries for this node\n const existing = this.nodes.get(nodeId);\n if (existing) {\n this.removeNodeFromIndex(nodeId, existing.entry);\n }\n // Add new entries\n this.indexNode(nodeId, entry);\n }\n\n /**\n * Extract searchable terms from a memory entry.\n * Returns lowercase words from text (min length) and full tag strings.\n */\n private extractTerms(entry: MemoryEntry): string[] {\n const terms: string[] = [];\n // Extract words from text (only terms >= MIN_TERM_LEN to avoid noise)\n const words = entry.text.toLowerCase().split(/\\s+/);\n for (const word of words) {\n if (word.length >= GraphMemoryBackend.MIN_TERM_LEN) {\n terms.push(word);\n }\n }\n // Index full tags as complete strings (not individual words)\n if (entry.tags) {\n for (const tag of entry.tags) {\n const lower = tag.toLowerCase();\n if (lower.length >= GraphMemoryBackend.MIN_TERM_LEN && !terms.includes(lower)) {\n terms.push(lower);\n }\n }\n }\n return terms;\n }\n}\n\n// ── Helpers ────────────────────────────────────────────────────────────\n\n/** Jaccard-style word overlap between two strings. 0.0 = no overlap, 1.0 = identical. */\nfunction wordOverlap(a: string, b: string): number {\n const wordsA = new Set(a.toLowerCase().split(/\\s+/).filter((w) => w.length > 2));\n const wordsB = new Set(b.toLowerCase().split(/\\s+/).filter((w) => w.length > 2));\n if (wordsA.size === 0 || wordsB.size === 0) return 0;\n let intersection = 0;\n for (const w of wordsA) {\n if (wordsB.has(w)) intersection++;\n }\n return intersection / Math.max(wordsA.size, wordsB.size);\n}\n\n/** Tag overlap ratio — how many tags two nodes share. */\nfunction sharedTags(a: string[], b: string[]): number {\n if (a.length === 0 || b.length === 0) return 0;\n const setB = new Set(b);\n let shared = 0;\n for (const t of a) if (setB.has(t)) shared++;\n return shared / Math.max(a.length, b.length);\n}\n\n/** Fast non-crypto hash for stable node IDs. */\nfunction simpleHash(s: string): string {\n let h = 0;\n for (let i = 0; i < s.length; i++) {\n h = ((h << 5) - h + s.charCodeAt(i)) | 0;\n }\n return Math.abs(h).toString(36);\n}\n","import { readFileSync, statSync } from 'node:fs';\nimport * as path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nexport function readBundledInstructionText(relativePath: string): string {\n for (const root of instructionRootCandidates()) {\n try {\n return readFileSync(path.join(root, relativePath), 'utf8').trimEnd();\n } catch {\n // try next candidate\n }\n }\n return '';\n}\n\nexport function renderInstructionTemplate(\n template: string,\n values: Record<string, string>,\n): string {\n return template.replace(/\\{\\{\\s*([a-zA-Z0-9_.-]+)\\s*\\}\\}/g, (match, key: string) =>\n Object.prototype.hasOwnProperty.call(values, key) ? values[key] ?? '' : match,\n );\n}\n\nfunction instructionRootCandidates(): string[] {\n const here = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(here, '../../instructions'),\n path.resolve(here, '../instructions'),\n path.resolve(here, 'instructions'),\n ];\n return candidates.sort((a, b) => Number(!isDirectory(a)) - Number(!isDirectory(b)));\n}\n\nfunction isDirectory(candidate: string): boolean {\n try {\n return statSync(candidate).isDirectory();\n } catch {\n return false;\n }\n}\n","import type { RunResult } from '../core/agent-types.js';\nimport type { Context } from '../core/context.js';\nimport type { AfterRunHook, AgentExtension } from '../extension/extension-points.js';\nimport type { MemoryEntry, MemoryStore } from '../types/memory.js';\nimport type { Provider } from '../types/provider.js';\nimport {\n readBundledInstructionText,\n renderInstructionTemplate,\n} from '../utils/instruction-file.js';\n\n// ── Types ───────────────────────────────────────────────────────────────\n\nexport interface ConsolidationOp {\n action: 'add' | 'edit' | 'delete';\n /** For add: the fact to remember. For edit: the new text replacing the old. */\n text?: string | undefined;\n /** For edit/delete: the query to match existing entries. */\n query?: string | undefined;\n /** Memory type for categorization. */\n type?: string | undefined;\n /** Tags for grouping. */\n tags?: string[] | undefined;\n /** Priority level. */\n priority?: string | undefined;\n}\n\ninterface ConsolidationResponse {\n operations: ConsolidationOp[];\n summary?: string | undefined;\n}\n\nexport interface MemoryConsolidatorOptions {\n memoryStore: MemoryStore;\n /**\n * Provider used for the consolidation LLM call. Uses the session's\n * provider by default.\n */\n provider?: Provider | undefined;\n /**\n * Model override for the consolidation call. Uses the session's model\n * by default. A smaller/faster model is recommended (e.g. haiku, flash).\n */\n model?: string | undefined;\n /**\n * Minimum session iterations before consolidation fires.\n * Sessions shorter than this are skipped (default 2).\n */\n minIterations?: number | undefined;\n /**\n * Maximum memory entries to include in the prompt as context.\n */\n maxExistingEntries?: number | undefined;\n}\n\n// ── Prompt ──────────────────────────────────────────────────────────────\n\nfunction buildConsolidationPrompt(\n finalText: string,\n iterations: number,\n existingEntries: MemoryEntry[],\n): string {\n const existingBlock =\n existingEntries.length > 0\n ? `\\n\\nExisting memory entries:\\n${existingEntries\n .map((e) => `- [${e.ts.slice(0, 10)}] ${e.text}`)\n .join('\\n')}`\n : '';\n\n return renderInstructionTemplate(readBundledInstructionText('llm/memory-consolidator.md'), {\n iterations: String(iterations),\n summary: finalText.slice(0, 3000),\n existingEntries: existingBlock,\n });\n}\n\n// ── Consolidator ────────────────────────────────────────────────────────\n\nexport class SessionMemoryConsolidator implements AgentExtension {\n name = 'session-memory-consolidator';\n owner = 'core';\n\n private readonly memoryStore: MemoryStore;\n private readonly provider?: Provider | undefined;\n private readonly model?: string | undefined;\n private readonly minIterations: number;\n private readonly maxExistingEntries: number;\n\n constructor(opts: MemoryConsolidatorOptions) {\n this.memoryStore = opts.memoryStore;\n this.provider = opts.provider;\n this.model = opts.model;\n this.minIterations = opts.minIterations ?? 2;\n this.maxExistingEntries = opts.maxExistingEntries ?? 15;\n }\n\n afterRun: AfterRunHook = (ctx: Context, result: RunResult) => {\n // Only consolidate successful sessions with meaningful output\n if (result.status !== 'done') return;\n if (!result.finalText || result.finalText.trim().length < 20) return;\n if (result.iterations < this.minIterations) return;\n\n const provider = this.provider ?? ctx.provider;\n if (!provider?.complete) return;\n\n // Capture narrowed values for the fire-and-forget closure.\n const _finalText: string = result.finalText;\n const _iterations: number = result.iterations;\n const _model: string | undefined = this.model ?? ctx.model;\n\n // Fire-and-forget: consolidation is best-effort and should never block\n // session teardown (the LLM call can take up to 15s). The catch block\n // below prevents unhandled rejections.\n void (async () => {\n try {\n // Load existing memory for dedup context\n const existingEntries = await this.memoryStore.list('project-memory', this.maxExistingEntries);\n const prompt = buildConsolidationPrompt(\n _finalText,\n _iterations,\n existingEntries,\n );\n\n // Call the LLM with a focused, one-shot prompt\n const signal = AbortSignal.timeout(15_000);\n const response = await provider.complete(\n {\n model: _model,\n system: [{ type: 'text', text: prompt }],\n messages: [\n { role: 'user', content: 'Review the session and return memory operations as JSON.' },\n ],\n maxTokens: 500,\n },\n { signal },\n );\n\n const text = response.content\n .filter((b): b is { type: 'text'; text: string } => b.type === 'text')\n .map((b) => b.text)\n .join('')\n .trim();\n if (!text) return;\n\n // Extract JSON from possible markdown wrapper\n const jsonMatch = text.match(/\\{[\\s\\S]*\\}/);\n if (!jsonMatch) return;\n\n const parsed: ConsolidationResponse = JSON.parse(jsonMatch[0]);\n if (!Array.isArray(parsed.operations) || parsed.operations.length === 0) return;\n\n // Apply operations\n let added = 0;\n let edited = 0;\n let deleted = 0;\n\n for (const op of parsed.operations) {\n switch (op.action) {\n case 'add': {\n if (op.text?.trim()) {\n await this.memoryStore.remember(op.text.trim(), undefined, {\n type: op.type as MemoryEntry['type'],\n tags: op.tags,\n priority: op.priority as MemoryEntry['priority'],\n });\n added++;\n }\n break;\n }\n case 'edit': {\n if (op.query && op.text?.trim()) {\n await this.memoryStore.forget(op.query);\n await this.memoryStore.remember(op.text.trim(), undefined, {\n type: op.type as MemoryEntry['type'],\n tags: op.tags,\n priority: op.priority as MemoryEntry['priority'],\n });\n edited++;\n }\n break;\n }\n case 'delete': {\n if (op.query) {\n const n = await this.memoryStore.forget(op.query);\n deleted += n;\n }\n break;\n }\n }\n }\n\n if (added > 0 || edited > 0 || deleted > 0) {\n const parts: string[] = [];\n if (added) parts.push(`${added} added`);\n if (edited) parts.push(`${edited} edited`);\n if (deleted) parts.push(`${deleted} deleted`);\n // Log to stderr so it surfaces in the terminal\n process.stderr.write(`[memory] Session consolidation: ${parts.join(', ')}\\n`);\n }\n } catch {\n // Silent — memory consolidation is best-effort, never blocks session cleanup\n }\n })();\n };\n}\n","import { toErrorMessage } from '../utils/index.js';\n\n/**\n * WrongStack error hierarchy.\n *\n * Every error thrown by the framework is a `WrongStackError` with a\n * machine-readable `code`, a `subsystem` tag, and a `severity` level.\n * This lets consumers (CLI, TUI, plugins, tests) branch on structured\n * data instead of parsing error messages.\n */\n\n// ── Error codes ──────────────────────────────────────────────────────\n\n/**\n * Machine-readable error codes as frozen constants.\n *\n * Use `ERROR_CODES.X` instead of raw string literals for:\n * - IDE autocomplete and compile-time validation\n * - Safe refactoring (rename updates all usages)\n * - Plugin extensibility (extend the object to add custom codes)\n *\n * The `ErrorCode` type is derived from this object, so adding a new\n * code here automatically updates the type without extra changes.\n */\nexport const ERROR_CODES = {\n // Provider\n PROVIDER_RATE_LIMITED: 'PROVIDER_RATE_LIMITED',\n PROVIDER_AUTH_FAILED: 'PROVIDER_AUTH_FAILED',\n PROVIDER_OVERLOADED: 'PROVIDER_OVERLOADED',\n PROVIDER_INVALID_REQUEST: 'PROVIDER_INVALID_REQUEST',\n PROVIDER_SERVER_ERROR: 'PROVIDER_SERVER_ERROR',\n PROVIDER_NETWORK_ERROR: 'PROVIDER_NETWORK_ERROR',\n PROVIDER_CONTEXT_OVERFLOW: 'PROVIDER_CONTEXT_OVERFLOW',\n // Tool\n TOOL_NOT_FOUND: 'TOOL_NOT_FOUND',\n TOOL_PERMISSION_DENIED: 'TOOL_PERMISSION_DENIED',\n TOOL_EXECUTION_FAILED: 'TOOL_EXECUTION_FAILED',\n TOOL_TIMEOUT: 'TOOL_TIMEOUT',\n TOOL_INPUT_INVALID: 'TOOL_INPUT_INVALID',\n // Config\n CONFIG_INVALID: 'CONFIG_INVALID',\n CONFIG_NOT_FOUND: 'CONFIG_NOT_FOUND',\n CONFIG_PARSE_FAILED: 'CONFIG_PARSE_FAILED',\n CONFIG_MIGRATION_NEEDED: 'CONFIG_MIGRATION_NEEDED',\n // Plugin\n PLUGIN_LOAD_FAILED: 'PLUGIN_LOAD_FAILED',\n PLUGIN_API_MISMATCH: 'PLUGIN_API_MISMATCH',\n PLUGIN_MISSING_DEPENDENCY: 'PLUGIN_MISSING_DEPENDENCY',\n // Agent\n AGENT_ITERATION_LIMIT: 'AGENT_ITERATION_LIMIT',\n AGENT_CONTEXT_OVERFLOW: 'AGENT_CONTEXT_OVERFLOW',\n AGENT_ABORTED: 'AGENT_ABORTED',\n AGENT_RUN_FAILED: 'AGENT_RUN_FAILED',\n // Session\n SESSION_NOT_FOUND: 'SESSION_NOT_FOUND',\n SESSION_CORRUPTED: 'SESSION_CORRUPTED',\n SESSION_WRITE_FAILED: 'SESSION_WRITE_FAILED',\n // Container / Registry\n CONTAINER_TOKEN_ALREADY_BOUND: 'CONTAINER_TOKEN_ALREADY_BOUND',\n CONTAINER_TOKEN_NOT_BOUND: 'CONTAINER_TOKEN_NOT_BOUND',\n CONTAINER_CIRCULAR_DEPENDENCY: 'CONTAINER_CIRCULAR_DEPENDENCY',\n REGISTRY_DUPLICATE: 'REGISTRY_DUPLICATE',\n REGISTRY_NOT_FOUND: 'REGISTRY_NOT_FOUND',\n REGISTRY_INVALID: 'REGISTRY_INVALID',\n // File system\n FS_READ_FAILED: 'FS_READ_FAILED',\n FS_WRITE_FAILED: 'FS_WRITE_FAILED',\n FS_MKDIR_FAILED: 'FS_MKDIR_FAILED',\n FS_DELETE_FAILED: 'FS_DELETE_FAILED',\n FS_ATOMIC_WRITE_FAILED: 'FS_ATOMIC_WRITE_FAILED',\n // SDD (Spec-Driven Development)\n SDD_VALIDATION_FAILED: 'SDD_VALIDATION_FAILED',\n SDD_PARSE_FAILED: 'SDD_PARSE_FAILED',\n SDD_INVALID_STATE: 'SDD_INVALID_STATE',\n SDD_NOT_READY: 'SDD_NOT_READY',\n // General\n VALIDATION_ERROR: 'VALIDATION_ERROR',\n UNKNOWN: 'UNKNOWN',\n} as const;\n\n/**\n * Union type derived from `ERROR_CODES`. Using `typeof ERROR_CODES[keyof typeof ERROR_CODES]`\n * instead of a string literal union means TypeScript auto-updates the type whenever\n * a new code is added to `ERROR_CODES` — no need to keep two lists in sync.\n */\nexport type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES];\n\nexport type ErrorSubsystem =\n | 'provider'\n | 'tool'\n | 'config'\n | 'plugin'\n | 'agent'\n | 'session'\n | 'sdd'\n | 'container'\n | 'fs'\n | 'general';\nexport type ErrorSeverity = 'fatal' | 'error' | 'warning';\n\n// ── Base error class ─────────────────────────────────────────────────\n\nexport class WrongStackError extends Error {\n readonly code: ErrorCode;\n readonly subsystem: ErrorSubsystem;\n readonly severity: ErrorSeverity;\n readonly recoverable: boolean;\n readonly context?: Record<string, unknown> | undefined;\n\n constructor(opts: {\n message: string;\n code: ErrorCode;\n subsystem: ErrorSubsystem;\n severity?: ErrorSeverity | undefined;\n recoverable?: boolean | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super(opts.message, { cause: opts.cause });\n this.name = 'WrongStackError';\n this.code = opts.code;\n this.subsystem = opts.subsystem;\n this.severity = opts.severity ?? 'error';\n this.recoverable = opts.recoverable ?? false;\n this.context = opts.context;\n }\n\n /**\n * Render a one-line user-facing description.\n * Subclasses should override for domain-specific formatting.\n */\n describe(): string {\n const ctx = this.context ? ` ${formatContext(this.context)}` : '';\n return `${this.code}: ${this.message}${ctx}`;\n }\n}\n\nfunction formatContext(ctx: Record<string, unknown>): string {\n const parts = Object.entries(ctx)\n .filter(([, v]) => v !== undefined)\n .slice(0, 3)\n .map(([k, v]) => `${k}=${String(v)}`);\n return parts.length > 0 ? `[${parts.join(' ')}]` : '';\n}\n\n// ── Specific error classes ───────────────────────────────────────────\n\n/**\n * Tool execution errors — thrown by ToolExecutor and individual tools.\n */\nexport class ToolError extends WrongStackError {\n readonly toolName: string;\n\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n | 'TOOL_NOT_FOUND'\n | 'TOOL_PERMISSION_DENIED'\n | 'TOOL_EXECUTION_FAILED'\n | 'TOOL_TIMEOUT'\n | 'TOOL_INPUT_INVALID'\n >;\n toolName: string;\n recoverable?: boolean | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'tool',\n recoverable: opts.recoverable,\n context: { tool: opts.toolName, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'ToolError';\n this.toolName = opts.toolName;\n }\n}\n\n/**\n * Config loading / validation errors.\n */\nexport class ConfigError extends WrongStackError {\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'CONFIG_INVALID' | 'CONFIG_NOT_FOUND' | 'CONFIG_PARSE_FAILED' | 'CONFIG_MIGRATION_NEEDED'\n >;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'config',\n severity: 'fatal',\n recoverable: false,\n context: opts.context,\n cause: opts.cause,\n });\n this.name = 'ConfigError';\n }\n}\n\n/**\n * Plugin loading / lifecycle errors.\n */\nexport class PluginError extends WrongStackError {\n readonly pluginName: string;\n\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'PLUGIN_LOAD_FAILED' | 'PLUGIN_API_MISMATCH' | 'PLUGIN_MISSING_DEPENDENCY'\n >;\n pluginName: string;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'plugin',\n severity: 'error',\n recoverable: opts.code === ERROR_CODES.PLUGIN_MISSING_DEPENDENCY,\n context: { plugin: opts.pluginName, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'PluginError';\n this.pluginName = opts.pluginName;\n }\n}\n\n/**\n * Agent runtime errors — thrown by Agent.run when a non-WrongStackError\n * escapes the inner loop, so callers always see a structured error.\n */\nexport class AgentError extends WrongStackError {\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'AGENT_ITERATION_LIMIT' | 'AGENT_CONTEXT_OVERFLOW' | 'AGENT_ABORTED' | 'AGENT_RUN_FAILED'\n >;\n recoverable?: boolean | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'agent',\n severity: opts.code === ERROR_CODES.AGENT_ABORTED ? 'warning' : 'error',\n recoverable: opts.recoverable ?? opts.code === ERROR_CODES.AGENT_ITERATION_LIMIT,\n context: opts.context,\n cause: opts.cause,\n });\n this.name = 'AgentError';\n }\n}\n\n/**\n * Wrap an arbitrary thrown value into a `WrongStackError` so the caller\n * always gets a structured error. Pass-throughs WrongStackError instances\n * unchanged; raw `Error`s and primitives get an `AGENT_RUN_FAILED` wrapper\n * with the original preserved as `cause`.\n */\nexport function toWrongStackError(\n err: unknown,\n code: Extract<ErrorCode, 'AGENT_RUN_FAILED' | 'AGENT_ABORTED' | 'UNKNOWN'> = ERROR_CODES.AGENT_RUN_FAILED,\n): WrongStackError {\n if (err instanceof WrongStackError) return err;\n const message = toErrorMessage(err);\n return new AgentError({\n message,\n code: code === 'UNKNOWN' ? ERROR_CODES.AGENT_RUN_FAILED : code,\n cause: err,\n });\n}\n\n/**\n * Session storage errors.\n */\nexport class SessionError extends WrongStackError {\n readonly sessionId?: string | undefined;\n\n constructor(opts: {\n message: string;\n code: Extract<ErrorCode, 'SESSION_NOT_FOUND' | 'SESSION_CORRUPTED' | 'SESSION_WRITE_FAILED'>;\n sessionId?: string | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'session',\n severity: opts.code === ERROR_CODES.SESSION_WRITE_FAILED ? 'error' : 'warning',\n recoverable: opts.code !== ERROR_CODES.SESSION_CORRUPTED,\n context: { sessionId: opts.sessionId, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'SessionError';\n this.sessionId = opts.sessionId;\n }\n}\n\n/**\n * SDD (Spec-Driven Development) errors — spec validation, parsing, and\n * state machine violations in the AISpecBuilder, TaskFlow, and TaskTracker.\n */\nexport class SddError extends WrongStackError {\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'SDD_VALIDATION_FAILED' | 'SDD_PARSE_FAILED' | 'SDD_INVALID_STATE' | 'SDD_NOT_READY'\n >;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'sdd',\n severity: opts.code === ERROR_CODES.SDD_PARSE_FAILED ? 'warning' : 'error',\n recoverable: opts.code === ERROR_CODES.SDD_NOT_READY,\n context: opts.context,\n cause: opts.cause,\n });\n this.name = 'SddError';\n }\n}\n\n/**\n * File system operation errors.\n */\nexport class FsError extends WrongStackError {\n readonly path?: string | undefined;\n\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'FS_READ_FAILED' | 'FS_WRITE_FAILED' | 'FS_MKDIR_FAILED' | 'FS_DELETE_FAILED' | 'FS_ATOMIC_WRITE_FAILED'\n >;\n path?: string | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'fs',\n severity: 'error',\n recoverable: opts.code !== ERROR_CODES.FS_READ_FAILED,\n context: { path: opts.path, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'FsError';\n this.path = opts.path;\n }\n}\n\n/**\n * HTTP fetch error — thrown when a network request returns a non-OK status.\n * Carries the response status so {@link classifyToolError} can branch on it\n * (429 → transient, 404 → not_found, 401 → permission) without duck-typing\n * the error via `'response' in err`.\n *\n * P3 #18 (before-release.md): the previous `'response' in err` check caught\n * any Error with a `response` property, including custom errors, proxy\n * objects, or mocked errors in tests. `instanceof FetchError` is reliable.\n *\n * Tools and providers that make HTTP requests and need the executor to\n * classify their failures should throw `new FetchError({ status, message })`\n * instead of a bare `Error` with an ad-hoc `response` field.\n */\nexport class FetchError extends WrongStackError {\n readonly status: number;\n\n constructor(opts: {\n message: string;\n status: number;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: ERROR_CODES.VALIDATION_ERROR,\n subsystem: 'general',\n severity: 'error',\n recoverable: opts.status === 429 || opts.status >= 500,\n context: { status: opts.status, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'FetchError';\n this.status = opts.status;\n }\n}\n\n/**\n * Tool input validation error — thrown when a tool's input fails a validation\n * check that the JSON Schema cannot express (e.g. `old_string === new_string`\n * in edit, or a cross-field invariant). Use this instead of a bare\n * `throw new Error('...validation...')` so {@link classifyToolError} can\n * match on `instanceof` rather than a locale-dependent message substring.\n *\n * P2 #6 (before-release.md): the previous `err.message.includes('validation')`\n * check misclassified any error whose message happened to contain \"validation\"\n * (e.g. a third-party \"input validation timeout\") as a VALIDATION error.\n *\n * Named `ToolValidationError` (not `ValidationError`) to avoid colliding with\n * the existing `ValidationError` interface exported by json-schema-validate.ts\n * (a validation-result shape, not an Error subclass).\n */\nexport class ToolValidationError extends WrongStackError {\n constructor(opts: {\n message: string;\n /** Field path or tool name that failed validation, for diagnostics. */\n field?: string | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: ERROR_CODES.VALIDATION_ERROR,\n subsystem: 'general',\n severity: 'error',\n recoverable: false,\n context: { field: opts.field, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'ToolValidationError';\n }\n}\n\n// ── Type guards ──────────────────────────────────────────────────────\n\nexport function isWrongStackError(err: unknown): err is WrongStackError {\n return err instanceof WrongStackError;\n}\n\nexport function isToolError(err: unknown): err is ToolError {\n return err instanceof ToolError;\n}\n\nexport function isConfigError(err: unknown): err is ConfigError {\n return err instanceof ConfigError;\n}\n\nexport function isPluginError(err: unknown): err is PluginError {\n return err instanceof PluginError;\n}\n\nexport function isSessionError(err: unknown): err is SessionError {\n return err instanceof SessionError;\n}\n\nexport function isAgentError(err: unknown): err is AgentError {\n return err instanceof AgentError;\n}\n\nexport function isFsError(err: unknown): err is FsError {\n return err instanceof FsError;\n}\n\nexport function isToolValidationError(err: unknown): err is ToolValidationError {\n return err instanceof ToolValidationError;\n}\n\nexport function isFetchError(err: unknown): err is FetchError {\n return err instanceof FetchError;\n}\n\nexport function isSddError(err: unknown): err is SddError {\n return err instanceof SddError;\n}\n","import type { Config, ConfigStore } from '../types/config.js';\nimport { ConfigError, ERROR_CODES } from '../types/errors.js';\nimport { toErrorMessage } from '../utils/error.js';\n\n\n/**\n * Strip fields that originated from environment variables so they are never\n * persisted back to disk. This prevents an env-sourced secret (e.g.\n * WRONGSTACK_API_KEY) from being accidentally written to ~/.wrongstack/config.json.\n */\nfunction stripEphemeralFields(cfg: Partial<Config>): Partial<Config> {\n const env = (cfg as Partial<Config & { _envSource?: Set<string> | undefined}>)._envSource;\n if (!env?.size) return cfg;\n const out: Partial<Config> = { ...cfg };\n for (const field of env) {\n delete (out as Record<string, unknown>)[field];\n }\n delete (out as Record<string, unknown>)._envSource;\n return out;\n}\n\n/**\n * Reference implementation of `ConfigStore`. Stores a single frozen Config\n * and notifies watchers synchronously on every update. Updates use a deep\n * clone so callers can mutate their `partial` argument freely without\n * tainting state.\n *\n * For the CLI: instantiate once at boot, pass the store (not the Config)\n * to subsystems that care about runtime changes (provider switching,\n * extension reload).\n */\nexport class DefaultConfigStore implements ConfigStore {\n private current: Readonly<Config>;\n private watchers = new Set<(next: Readonly<Config>, prev: Readonly<Config>) => void>();\n\n constructor(initial: Config) {\n this.current = deepFreeze(structuredClone(initial));\n }\n\n get(): Readonly<Config> {\n return this.current;\n }\n\n getSection<K extends keyof Config>(key: K): Readonly<Config[K]> {\n return this.current[key] as Readonly<Config[K]>;\n }\n\n getExtension(pluginName: string): Readonly<Record<string, unknown>> {\n const ext = this.current.extensions?.[pluginName];\n return ext ? (ext as Readonly<Record<string, unknown>>) : FROZEN_EMPTY;\n }\n\n update(partial: Partial<Config>): Readonly<Config> {\n // Strip env-sourced fields before persisting to prevent secrets leaking\n // from in-memory env-derived config values into the on-disk config file.\n const scrubbed = stripEphemeralFields(partial);\n // Shallow merge — top-level fields replace, nested objects do too unless\n // the caller passes a fully-formed sub-object. That matches the JSON\n // config user mental model (replace `tools.maxIterations` by passing\n // the whole `tools` block, or by patching `extensions.<name>`).\n const next = deepFreeze(structuredClone({ ...this.current, ...scrubbed })) as Readonly<Config>;\n\n if (next.version !== 1) {\n throw new ConfigError({\n message: `ConfigStore.update: version must remain 1, got ${String(next.version)}`,\n code: ERROR_CODES.CONFIG_INVALID,\n context: { field: 'version', actual: next.version },\n });\n }\n\n const prev = this.current;\n this.current = next;\n // Notify watchers AFTER mutating `current` so re-entrant watcher reads\n // see the new state. Watcher exceptions are caught individually so one\n // misbehaving subscriber can't block the others.\n for (const w of this.watchers) {\n try {\n w(next, prev);\n } catch (err) {\n // A plugin watcher that crashes on /model switch or similar would\n // otherwise leave the system in a quietly-inconsistent state. We\n // still don't propagate (one bad subscriber must not break the\n // others), but we surface the error so it's discoverable.\n console.error(JSON.stringify({\n level: 'error',\n event: 'config_store.watcher_threw',\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n }\n }\n return next;\n }\n\n watch(cb: (next: Readonly<Config>, prev: Readonly<Config>) => void): () => void {\n this.watchers.add(cb);\n return () => this.watchers.delete(cb);\n }\n}\n\nconst FROZEN_EMPTY: Readonly<Record<string, unknown>> = Object.freeze({});\n\nfunction deepFreeze<T>(obj: T): T {\n /* v8 ignore start -- defensive: callers (and the recursion guard below) only pass unfrozen objects */\n if (obj === null || typeof obj !== 'object') return obj;\n if (Object.isFrozen(obj)) return obj;\n /* v8 ignore stop */\n for (const key of Object.keys(obj as object)) {\n const v = (obj as Record<string, unknown>)[key];\n if (v !== null && typeof v === 'object' && !Object.isFrozen(v)) {\n deepFreeze(v);\n }\n }\n return Object.freeze(obj);\n}\n","import { createCipheriv, createDecipheriv, randomBytes, scryptSync } from 'node:crypto';\nimport * as fs from 'node:fs';\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { Logger } from '../types/logger.js';\nimport type { RotatableSecretVault, SecretVault } from '../types/secret-vault.js';\nimport { ConfigError, ERROR_CODES } from '../types/errors.js';\nimport {\n ENCRYPTED_PREFIX_PATTERN,\n encryptedPrefixForVersion,\n} from '../types/secret-vault.js';\nimport { atomicWrite } from '../utils/atomic-write.js';\n\nexport interface SecretVaultOptions {\n /** Absolute path to the key file. Created with mode 0o600 if missing. */\n keyFile: string;\n}\n\nconst KEY_BYTES = 32;\nconst IV_BYTES = 12;\nconst TAG_BYTES = 16;\nconst ALGO = 'aes-256-gcm';\n// Desired file mode for the key file on POSIX systems.\nconst KEY_FILE_MODE = 0o600;\n\n/**\n * Key file format v2+: 4-byte magic + 1-byte version + 32-byte key = 37 bytes.\n * The magic header distinguishes versioned key files from legacy 32-byte raw keys.\n */\nconst KEY_FILE_MAGIC = Buffer.from('WSKV', 'ascii');\nconst VERSIONED_KEY_FILE_SIZE = KEY_FILE_MAGIC.length + 1 + KEY_BYTES; // 37 bytes\n\n// ── WS-03: opt-in passphrase-wrapped key file (KEK) ─────────────────────────\n//\n// When WRONGSTACK_VAULT_PASSPHRASE is set, the data key is NOT stored in the\n// clear. Instead the key file holds the data key encrypted (AES-256-GCM) under\n// a key-encryption-key (KEK) derived from the passphrase with scrypt. This adds\n// at-rest protection beyond the file's 0o600 perms: an attacker who copies\n// ~/.wrongstack/.key + config.json off the disk still cannot decrypt without the\n// passphrase. When the env var is unset, behavior is byte-for-byte identical to\n// before (legacy raw / versioned formats) — this is purely additive and opt-in.\n//\n// Wrapped format v3: magic 'WSKW' (4) + keyVersion (1) + salt (16) + iv (12) +\n// tag (16) + ciphertext (32) = 81 bytes.\nconst KEK_MAGIC = Buffer.from('WSKW', 'ascii');\nconst KEK_SALT_BYTES = 16;\nconst WRAPPED_KEY_FILE_SIZE =\n KEK_MAGIC.length + 1 + KEK_SALT_BYTES + IV_BYTES + TAG_BYTES + KEY_BYTES; // 81 bytes\n// scrypt cost parameters. N=2^15 keeps derivation ~50-100ms — strong against\n// offline brute force while imperceptible for a one-time-per-process unlock.\nconst SCRYPT_N = 1 << 15;\nconst SCRYPT_R = 8;\nconst SCRYPT_P = 1;\nconst SCRYPT_MAXMEM = 64 * 1024 * 1024; // headroom above N*r*128 so derivation never throws\n\n/** Read the optional vault passphrase from the environment. Empty = unset. */\nfunction getVaultPassphrase(): string | undefined {\n const v = process.env['WRONGSTACK_VAULT_PASSPHRASE'];\n return v && v.length > 0 ? v : undefined;\n}\n\n/** True if `buf` is a passphrase-wrapped (v3) key file. */\nfunction isWrappedKeyFile(buf: Buffer): boolean {\n return buf.length === WRAPPED_KEY_FILE_SIZE && buf.subarray(0, KEK_MAGIC.length).equals(KEK_MAGIC);\n}\n\n/** Derive the 32-byte KEK from a passphrase + salt via scrypt. */\nfunction deriveKEK(passphrase: string, salt: Buffer): Buffer {\n return scryptSync(passphrase, salt, KEY_BYTES, {\n N: SCRYPT_N,\n r: SCRYPT_R,\n p: SCRYPT_P,\n maxmem: SCRYPT_MAXMEM,\n });\n}\n\n/** Serialize a data key into the wrapped (v3) on-disk format under `passphrase`. */\nfunction wrapDataKey(dataKey: Buffer, keyVersion: number, passphrase: string): Buffer {\n const salt = randomBytes(KEK_SALT_BYTES);\n const iv = randomBytes(IV_BYTES);\n const kek = deriveKEK(passphrase, salt);\n const cipher = createCipheriv(ALGO, kek, iv);\n const ct = Buffer.concat([cipher.update(dataKey), cipher.final()]);\n const tag = cipher.getAuthTag();\n const out = Buffer.alloc(WRAPPED_KEY_FILE_SIZE);\n let off = 0;\n KEK_MAGIC.copy(out, off); off += KEK_MAGIC.length;\n out[off] = keyVersion & 0xff; off += 1;\n salt.copy(out, off); off += KEK_SALT_BYTES;\n iv.copy(out, off); off += IV_BYTES;\n tag.copy(out, off); off += TAG_BYTES;\n ct.copy(out, off);\n return out;\n}\n\n/**\n * Parse a wrapped (v3) key file and return the data key + version. Throws a\n * clear ConfigError when the passphrase is missing or wrong (GCM auth failure).\n */\nfunction unwrapDataKey(buf: Buffer, keyFile: string): { key: Buffer; version: number } {\n const passphrase = getVaultPassphrase();\n if (!passphrase) {\n throw new ConfigError({\n message:\n `SecretVault: key file ${keyFile} is passphrase-protected — set the ` +\n `WRONGSTACK_VAULT_PASSPHRASE environment variable to unlock it.`,\n code: ERROR_CODES.CONFIG_INVALID,\n context: { keyFile },\n });\n }\n let off = KEK_MAGIC.length;\n const version = buf[off]!; off += 1;\n const salt = buf.subarray(off, off + KEK_SALT_BYTES); off += KEK_SALT_BYTES;\n const iv = buf.subarray(off, off + IV_BYTES); off += IV_BYTES;\n const tag = buf.subarray(off, off + TAG_BYTES); off += TAG_BYTES;\n const ct = buf.subarray(off, off + KEY_BYTES);\n const kek = deriveKEK(passphrase, salt);\n const decipher = createDecipheriv(ALGO, kek, iv);\n decipher.setAuthTag(tag);\n try {\n const key = Buffer.concat([decipher.update(ct), decipher.final()]);\n return { key: Buffer.from(key), version };\n } catch {\n throw new ConfigError({\n message:\n `SecretVault: failed to unlock key file ${keyFile} — wrong ` +\n `WRONGSTACK_VAULT_PASSPHRASE (key unwrap authentication failed).`,\n code: ERROR_CODES.CONFIG_INVALID,\n context: { keyFile },\n });\n }\n}\n\n/**\n * Check and warn if the key file has incorrect permissions on POSIX.\n * On Windows this is a no-op (mode bits don't apply).\n */\nfunction checkKeyFilePermissions(keyFile: string): void {\n if (process.platform === 'win32') return; // No mode bits on Windows\n try {\n const stat = fs.statSync(keyFile);\n const actualMode = stat.mode & 0o777;\n if (actualMode !== KEY_FILE_MODE) {\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'vault.key_file_wrong_permissions',\n message: `Key file ${keyFile} has mode ${actualMode.toString(8)} — expected ${KEY_FILE_MODE.toString(8)}. Run: chmod ${KEY_FILE_MODE.toString(8)} ${keyFile}`,\n keyFile,\n expectedMode: KEY_FILE_MODE,\n actualMode,\n timestamp: new Date().toISOString(),\n }));\n }\n } catch {\n // stat can fail for reasons other than the file not existing;\n // if it does, the ENOENT path handles it.\n }\n}\n\n/**\n * Default vault: AES-256-GCM with a key stored at `keyFile` (mode 0o600).\n * The key is loaded lazily on first encrypt/decrypt; if it does not exist,\n * a fresh one is generated. Decryption of plaintext values is a no-op so\n * legacy configs continue to work.\n *\n * Key file format:\n * - Legacy (v1): exactly 32 raw bytes\n * - Versioned (v2+): 4-byte magic `WSKV` + 1-byte version + 32-byte key (37 bytes)\n *\n * Encrypted value format: `enc:v<N>:<iv>:<tag>:<ciphertext>` where N is the\n * key version. After rotation, encrypt() emits the new version prefix.\n */\nexport class DefaultSecretVault implements RotatableSecretVault {\n private readonly keyFile: string;\n private key?: Buffer | undefined;\n private _keyVersion: number = 1;\n\n constructor(opts: SecretVaultOptions) {\n this.keyFile = opts.keyFile;\n }\n\n /** Current key version. Starts at 1; incremented by rotateKey(). */\n get keyVersion(): number {\n // Ensure key is loaded so version is accurate\n if (!this.key) this.loadOrCreateKey();\n return this._keyVersion;\n }\n\n isEncrypted(value: string): boolean {\n return typeof value === 'string' && ENCRYPTED_PREFIX_PATTERN.test(value);\n }\n\n encrypt(plaintext: string): string {\n if (this.isEncrypted(plaintext)) return plaintext;\n const key = this.loadOrCreateKey();\n const iv = randomBytes(IV_BYTES);\n const cipher = createCipheriv(ALGO, key, iv);\n const ct = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);\n const tag = cipher.getAuthTag();\n const prefix = encryptedPrefixForVersion(this._keyVersion);\n return `${prefix}${iv.toString('base64')}:${tag.toString('base64')}:${ct.toString('base64')}`;\n }\n\n decrypt(value: string): string {\n if (!this.isEncrypted(value)) return value;\n // Strip the versioned prefix (enc:v1:, enc:v2:, etc.)\n const prefixMatch = value.match(ENCRYPTED_PREFIX_PATTERN);\n if (!prefixMatch) {\n throw new ConfigError({\n message: 'SecretVault: malformed encrypted value',\n code: ERROR_CODES.CONFIG_PARSE_FAILED,\n context: { field: 'encrypted_value' },\n });\n }\n const rest = value.slice(prefixMatch[0].length);\n const parts = rest.split(':');\n if (parts.length !== 3) {\n throw new ConfigError({\n message: 'SecretVault: malformed encrypted value',\n code: ERROR_CODES.CONFIG_PARSE_FAILED,\n context: { field: 'encrypted_value' },\n });\n }\n const [ivB64, tagB64, ctB64] = parts as [string, string, string];\n const iv = Buffer.from(ivB64, 'base64');\n const tag = Buffer.from(tagB64, 'base64');\n const ct = Buffer.from(ctB64, 'base64');\n if (iv.length !== IV_BYTES) throw new ConfigError({\n message: 'SecretVault: bad IV length',\n code: ERROR_CODES.CONFIG_PARSE_FAILED,\n context: { expected: IV_BYTES, actual: iv.length },\n });\n if (tag.length !== TAG_BYTES) throw new ConfigError({\n message: 'SecretVault: bad tag length',\n code: ERROR_CODES.CONFIG_PARSE_FAILED,\n context: { expected: TAG_BYTES, actual: tag.length },\n });\n const key = this.loadOrCreateKey();\n const decipher = createDecipheriv(ALGO, key, iv);\n decipher.setAuthTag(tag);\n const pt = Buffer.concat([decipher.update(ct), decipher.final()]);\n return pt.toString('utf8');\n }\n\n /**\n * Generate a new encryption key, write it to disk, and increment the key version.\n * After rotation, encrypt() emits the new version prefix (e.g. enc:v2:).\n * The caller must re-encrypt existing config values (see rotateConfigKeys()).\n */\n rotateKey(): { oldVersion: number; newVersion: number } {\n const oldVersion = this._keyVersion;\n const newKey = randomBytes(KEY_BYTES);\n const newVersion = oldVersion + 1;\n\n fs.mkdirSync(path.dirname(this.keyFile), { recursive: true });\n const passphrase = getVaultPassphrase();\n if (passphrase) {\n // Keep the rotated key passphrase-wrapped (v3) so rotation never\n // downgrades a protected key file to plaintext.\n fs.writeFileSync(this.keyFile, wrapDataKey(newKey, newVersion, passphrase), { mode: 0o600 });\n } else {\n // Write versioned key file: WSKV + version byte + key\n const keyFileBuf = Buffer.alloc(VERSIONED_KEY_FILE_SIZE);\n KEY_FILE_MAGIC.copy(keyFileBuf, 0);\n keyFileBuf[KEY_FILE_MAGIC.length] = newVersion;\n newKey.copy(keyFileBuf, KEY_FILE_MAGIC.length + 1);\n fs.writeFileSync(this.keyFile, keyFileBuf, { mode: 0o600 });\n }\n checkKeyFilePermissions(this.keyFile);\n\n this.key = newKey;\n this._keyVersion = newVersion;\n return { oldVersion, newVersion };\n }\n\n /**\n * If WRONGSTACK_VAULT_PASSPHRASE is set but the key on disk is still stored\n * unwrapped (legacy v1 / versioned v2), re-write it in passphrase-wrapped (v3)\n * form. The data key is preserved, so all existing ciphertext keeps\n * decrypting. Best-effort: a write failure leaves the working unwrapped file\n * in place and is not fatal to load.\n */\n private migrateToWrappedIfPassphrase(): void {\n const passphrase = getVaultPassphrase();\n if (!passphrase || !this.key) return;\n try {\n fs.writeFileSync(this.keyFile, wrapDataKey(this.key, this._keyVersion, passphrase), {\n mode: 0o600,\n });\n checkKeyFilePermissions(this.keyFile);\n } catch {\n // Non-fatal: the at-rest upgrade failed, but the loaded key is valid.\n }\n }\n\n private loadOrCreateKey(): Buffer {\n // readFileSync blocks the event loop, but this is a one-time cost per\n // process: the key is cached after the first load and reused for every\n // subsequent encrypt/decrypt. For CLI usage (single run → exit) this is\n // negligible. For server contexts (eternal autonomy, MCP server mode),\n // the first encrypt/decrypt call causes a brief (<1ms) event loop stall.\n // Prefer calling vault.encrypt('') during boot to warm the cache if this\n // is a concern in your deployment.\n if (this.key) return this.key;\n try {\n const buf = fs.readFileSync(this.keyFile);\n\n // Passphrase-wrapped (v3): unwrap with WRONGSTACK_VAULT_PASSPHRASE.\n // Checked first because its size/magic are distinct from the others.\n if (isWrappedKeyFile(buf)) {\n const { key, version } = unwrapDataKey(buf, this.keyFile);\n this.key = key;\n this._keyVersion = version;\n checkKeyFilePermissions(this.keyFile);\n return this.key;\n }\n\n // Detect key file format:\n if (buf.length === KEY_BYTES) {\n // Legacy v1: raw 32-byte key\n this.key = buf;\n this._keyVersion = 1;\n checkKeyFilePermissions(this.keyFile);\n // Upgrade to passphrase-wrapped at rest if a passphrase is configured.\n this.migrateToWrappedIfPassphrase();\n return this.key;\n }\n\n if (buf.length === VERSIONED_KEY_FILE_SIZE) {\n // Versioned v2+: WSKV magic + version byte + 32-byte key\n const magic = buf.subarray(0, KEY_FILE_MAGIC.length);\n if (!magic.equals(KEY_FILE_MAGIC)) {\n throw new ConfigError({\n message: `SecretVault: key file ${this.keyFile} has invalid magic header`,\n code: ERROR_CODES.CONFIG_INVALID,\n context: { keyFile: this.keyFile },\n });\n }\n const version = buf[KEY_FILE_MAGIC.length]!;\n const key = buf.subarray(KEY_FILE_MAGIC.length + 1);\n if (key.length !== KEY_BYTES) {\n throw new ConfigError({\n message: `SecretVault: key file ${this.keyFile} has wrong key size (${key.length} bytes, expected ${KEY_BYTES})`,\n code: ERROR_CODES.CONFIG_INVALID,\n context: { keyFile: this.keyFile, expectedBytes: KEY_BYTES, actualBytes: key.length },\n });\n }\n this.key = Buffer.from(key);\n this._keyVersion = version;\n checkKeyFilePermissions(this.keyFile);\n // Upgrade to passphrase-wrapped at rest if a passphrase is configured.\n this.migrateToWrappedIfPassphrase();\n return this.key;\n }\n\n // Wrong size — neither legacy nor versioned format\n throw new ConfigError({\n message:\n `SecretVault: key file ${this.keyFile} is ${buf.length} bytes ` +\n `(expected ${KEY_BYTES} for v1 or ${VERSIONED_KEY_FILE_SIZE} for v2+). ` +\n `Remove it manually to generate a new key.`,\n code: ERROR_CODES.CONFIG_INVALID,\n context: { keyFile: this.keyFile, expectedBytes: KEY_BYTES, actualBytes: buf.length },\n });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;\n }\n // Create a fresh key. Use sync APIs so the constructor-free getter\n // remains synchronous from the caller's perspective.\n fs.mkdirSync(path.dirname(this.keyFile), { recursive: true });\n const key = randomBytes(KEY_BYTES);\n // When a passphrase is configured, a brand-new key is written wrapped (v3)\n // from the start; otherwise the legacy raw-32-byte format is preserved.\n const passphrase = getVaultPassphrase();\n const initialBytes = passphrase ? wrapDataKey(key, 1, passphrase) : key;\n // Use exclusive-create flag 'wx' to prevent races: if two processes race\n // to create the key file, only one succeeds and the loser gets EEXIST.\n try {\n fs.writeFileSync(this.keyFile, initialBytes, { mode: 0o600, flag: 'wx' });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'EEXIST') throw err;\n // Another process won the race — re-read what they wrote.\n const buf = fs.readFileSync(this.keyFile);\n if (isWrappedKeyFile(buf)) {\n const { key: winnerKey, version } = unwrapDataKey(buf, this.keyFile);\n this.key = winnerKey;\n this._keyVersion = version;\n checkKeyFilePermissions(this.keyFile);\n return this.key;\n }\n if (buf.length === KEY_BYTES) {\n // Legacy v1 format\n this.key = buf;\n this._keyVersion = 1;\n checkKeyFilePermissions(this.keyFile);\n return this.key;\n }\n if (buf.length === VERSIONED_KEY_FILE_SIZE) {\n // Versioned format\n const magic = buf.subarray(0, KEY_FILE_MAGIC.length);\n if (!magic.equals(KEY_FILE_MAGIC)) {\n throw new ConfigError({\n message: `SecretVault: key file ${this.keyFile} has invalid magic header`,\n code: ERROR_CODES.CONFIG_INVALID,\n context: { keyFile: this.keyFile },\n });\n }\n const version = buf[KEY_FILE_MAGIC.length]!;\n const winnerKey = buf.subarray(KEY_FILE_MAGIC.length + 1);\n this.key = Buffer.from(winnerKey);\n this._keyVersion = version;\n checkKeyFilePermissions(this.keyFile);\n return this.key;\n }\n throw new ConfigError({\n message:\n `SecretVault: key file ${this.keyFile} is ${buf.length} bytes ` +\n `(expected ${KEY_BYTES} for v1 or ${VERSIONED_KEY_FILE_SIZE} for v2+). ` +\n `Remove it manually to generate a new key.`,\n code: ERROR_CODES.CONFIG_INVALID,\n context: { keyFile: this.keyFile, expectedBytes: KEY_BYTES, actualBytes: buf.length },\n });\n }\n this.key = key;\n this._keyVersion = 1;\n return key;\n }\n}\n\n/**\n * Walk a Config-shaped object and decrypt any apiKey-like fields in place,\n * returning a new object. Used by the config loader so the rest of the\n * system never has to know about the wire format.\n *\n * @param warn — callback for decryption warnings. Defaults to `console.warn`\n * for backward compatibility; pass `logger.warn` when a structured logger\n * is available (preferred in long-running/server contexts).\n */\nexport function decryptConfigSecrets<T>(\n cfg: T,\n vault: SecretVault,\n opts?: { warn?: (msg: string) => void },\n): T {\n const warn = opts?.warn ?? ((msg: string) => console.warn(msg));\n // A single corrupted/malformed encrypted field should not kill the entire\n // config load. Swallow per-field decrypt errors (zero the field so callers\n // see \"missing key\" instead of holding ciphertext) and surface a warning.\n return walk(cfg, vault, (v, key) => {\n try {\n return vault.decrypt(v);\n } catch (err) {\n warn(\n `[secret-vault] Failed to decrypt \"${key}\": ${err instanceof Error ? err.message : err}`,\n );\n return '';\n }\n });\n}\n\nexport function encryptConfigSecrets<T>(\n cfg: T,\n vault: SecretVault,\n _opts?: { warn?: (msg: string) => void },\n): T {\n return walk(cfg, vault, (v) => vault.encrypt(v));\n}\n\nfunction walk<T>(node: T, vault: SecretVault, transform: (s: string, key: string) => string): T {\n if (node === null || node === undefined) return node;\n if (typeof node !== 'object') return node;\n if (Array.isArray(node)) {\n return node.map((item) => walk(item, vault, transform)) as never as T;\n }\n const out: Record<string, unknown> = Object.create(null);\n for (const [k, v] of Object.entries(node as Record<string, unknown>)) {\n if (typeof v === 'string' && isSecretField(k)) {\n out[k] = transform(v, k);\n } else if (typeof v === 'object' && v !== null) {\n out[k] = walk(v, vault, transform);\n } else {\n out[k] = v;\n }\n }\n return out as T;\n}\n\n/**\n * A key is treated as secret-bearing if its name (case-insensitive) contains\n * one of these tokens. Captures common variants like `apiKey`, `authToken`,\n * `refreshToken`, `sessionKey`, `password`, `client_secret`, `bearer`, etc.\n * Use a named field with `isSecret: false` annotation if you must opt out —\n * see `NON_SECRET_OVERRIDES` below.\n */\nconst SECRET_KEY_PATTERN =\n /(?:apikey|api_key|authtoken|auth_token|bearer|secret|password|passwd|pwd|refreshtoken|refresh_token|sessionkey|session_key|access[_-]?token|private[_-]?key)/i;\n\n// Field names that contain the literal substring \"key\" but are not secrets.\n// Keep this list short; the substring rule itself is intentionally narrow.\nconst NON_SECRET_OVERRIDES = new Set(['publickey', 'public_key']);\n\nexport function isSecretField(name: string): boolean {\n const lc = name.toLowerCase();\n if (NON_SECRET_OVERRIDES.has(lc)) return false;\n return SECRET_KEY_PATTERN.test(lc);\n}\n\n/**\n * Re-write `~/.wrongstack/config.json` (or any path) with all secret-bearing\n * fields encrypted. Used by the `wstack auth` subcommand.\n */\nexport async function rewriteConfigEncrypted(\n configPath: string,\n vault: SecretVault,\n patch?: Record<string, unknown>,\n): Promise<void> {\n let current: Record<string, unknown> = {};\n try {\n const raw = await fsp.readFile(configPath, 'utf8');\n current = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n // start from empty\n }\n const merged = deepMerge(current, patch ?? {});\n const encrypted = encryptConfigSecrets(merged, vault);\n await fsp.mkdir(path.dirname(configPath), { recursive: true });\n // atomicWrite: torn write here would erase every saved encrypted API key.\n await atomicWrite(configPath, JSON.stringify(encrypted, null, 2), { mode: 0o600 });\n await restrictFilePermissions(configPath);\n}\n\n/**\n * Scan a config file on disk for plaintext secret-bearing fields and\n * rewrite the file with them encrypted in place. Returns a count of how\n * many fields were migrated. Idempotent — calling on a fully-encrypted\n * file is a no-op and writes nothing. Used by the CLI on every boot so\n * users who had plaintext keys before the vault landed are upgraded\n * transparently.\n */\nexport async function migratePlaintextSecrets(\n configPath: string,\n vault: SecretVault,\n logger?: Pick<Logger, 'warn'>,\n): Promise<{ migrated: number; file: string }> {\n let raw: string;\n try {\n raw = await fsp.readFile(configPath, 'utf8');\n } catch {\n return { migrated: 0, file: configPath };\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return { migrated: 0, file: configPath };\n }\n const counter = { n: 0 };\n const migrated = walkCount(parsed, vault, counter);\n if (counter.n === 0) return { migrated: 0, file: configPath };\n // atomicWrite: runs on every boot for legacy users — torn write = wipe.\n await atomicWrite(configPath, JSON.stringify(migrated, null, 2), { mode: 0o600 });\n await restrictFilePermissions(\n configPath,\n logger ? { warn: (msg) => logger.warn(msg) } : undefined,\n );\n return { migrated: counter.n, file: configPath };\n}\n\n/**\n * Rotate the vault's encryption key and re-encrypt all secret-bearing\n * fields in a config file. This is the atomic key rotation operation:\n *\n * 1. Read the config file\n * 2. Decrypt all encrypted values with the old key\n * 3. Generate a new key (vault.rotateKey())\n * 4. Re-encrypt all values with the new key (new version prefix)\n * 5. Write the config file atomically\n *\n * Returns the number of fields re-encrypted and the version transition.\n * If the config file doesn't exist or has no encrypted fields, returns\n * { rotated: 0 } without modifying the key.\n */\nexport async function rotateConfigKeys(\n configPath: string,\n vault: RotatableSecretVault,\n logger?: Pick<Logger, 'warn' | 'info'>,\n): Promise<{ rotated: number; oldVersion: number; newVersion: number; file: string }> {\n const log = logger?.info ?? (() => {});\n const warn = logger?.warn ?? ((msg: string) => console.warn(msg));\n\n // Read the config file\n let raw: string;\n try {\n raw = await fsp.readFile(configPath, 'utf8');\n } catch {\n // No config file — just rotate the key without re-encrypting anything\n const { oldVersion, newVersion } = vault.rotateKey();\n log(`[secret-vault] Key rotated (v${oldVersion} → v${newVersion}) — no config file to re-encrypt`);\n return { rotated: 0, oldVersion, newVersion, file: configPath };\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n warn(`[secret-vault] Config file ${configPath} is not valid JSON — skipping rotation`);\n return { rotated: 0, oldVersion: vault.keyVersion, newVersion: vault.keyVersion, file: configPath };\n }\n\n // Count encrypted fields and decrypt them\n const counter = { n: 0, failed: [] as string[] };\n const decrypted = walkDecryptCount(parsed, vault, counter);\n\n // Abort BEFORE rotating if any encrypted field could not be decrypted with\n // the current key. Rotation would discard the old key while these fields\n // still hold old-key ciphertext, and walkReencrypt skips already-encrypted\n // values — so they would become permanently undecryptable. Surface the\n // corruption and leave the key intact for the operator to investigate.\n if (counter.failed.length > 0) {\n throw new Error(\n `[secret-vault] Aborting key rotation: ${counter.failed.length} field(s) could not be decrypted ` +\n `with the current key and would be permanently lost on rotation: ${counter.failed.join(', ')}. ` +\n `Restore or remove these fields before rotating.`,\n );\n }\n\n if (counter.n === 0) {\n // No encrypted fields — just rotate the key\n const { oldVersion, newVersion } = vault.rotateKey();\n log(`[secret-vault] Key rotated (v${oldVersion} → v${newVersion}) — no encrypted fields to re-encrypt`);\n return { rotated: 0, oldVersion, newVersion, file: configPath };\n }\n\n // Rotate the key (generates new key, increments version)\n const { oldVersion, newVersion } = vault.rotateKey();\n\n // Re-encrypt all secret fields with the new key\n const reencrypted = walkReencrypt(decrypted, vault);\n\n // Write the config file atomically\n await atomicWrite(configPath, JSON.stringify(reencrypted, null, 2), { mode: 0o600 });\n await restrictFilePermissions(configPath, { warn });\n\n log(`[secret-vault] Key rotated (v${oldVersion} → v${newVersion}) — re-encrypted ${counter.n} field(s)`);\n return { rotated: counter.n, oldVersion, newVersion, file: configPath };\n}\n\n/**\n * Walk a config object, decrypt all encrypted values, and count them.\n * Returns a new object with decrypted values.\n *\n * `counter.failed` collects the key paths of any field that is encrypted but\n * could NOT be decrypted with the current key. These are left as-is (old\n * ciphertext). The caller MUST treat a non-empty `failed` list as a hard stop\n * before rotating: rotation discards the old key, and `walkReencrypt` skips\n * already-encrypted values, so a retained old-key ciphertext would become\n * permanently undecryptable. Surfacing it is strictly safer than entombing it.\n */\nfunction walkDecryptCount<T>(\n node: T,\n vault: SecretVault,\n counter: { n: number; failed: string[] },\n pathPrefix = '',\n): T {\n if (node === null || node === undefined) return node;\n if (typeof node !== 'object') return node;\n if (Array.isArray(node)) {\n return node.map((item, i) =>\n walkDecryptCount(item, vault, counter, `${pathPrefix}[${i}]`),\n ) as never as T;\n }\n const out: Record<string, unknown> = Object.create(null);\n for (const [k, v] of Object.entries(node as Record<string, unknown>)) {\n const keyPath = pathPrefix ? `${pathPrefix}.${k}` : k;\n if (typeof v === 'string' && vault.isEncrypted(v)) {\n try {\n out[k] = vault.decrypt(v);\n counter.n++;\n } catch {\n // Decryption failed — record the path and keep the old ciphertext.\n // The caller aborts rotation when counter.failed is non-empty, so\n // the old key is never discarded while this value still depends on it.\n counter.failed.push(keyPath);\n out[k] = v;\n }\n } else if (typeof v === 'object' && v !== null) {\n out[k] = walkDecryptCount(v, vault, counter, keyPath);\n } else {\n out[k] = v;\n }\n }\n return out as T;\n}\n\n/**\n * Walk a config object and re-encrypt all secret-bearing fields.\n * Unlike encryptConfigSecrets, this encrypts ALL string values that\n * were previously decrypted (they're now plaintext), not just those\n * matching the secret field pattern. This ensures we re-encrypt values\n * that were successfully decrypted in walkDecryptCount.\n */\nfunction walkReencrypt<T>(node: T, vault: SecretVault): T {\n if (node === null || node === undefined) return node;\n if (typeof node !== 'object') return node;\n if (Array.isArray(node)) {\n return node.map((item) => walkReencrypt(item, vault)) as never as T;\n }\n const out: Record<string, unknown> = Object.create(null);\n for (const [k, v] of Object.entries(node as Record<string, unknown>)) {\n if (typeof v === 'string' && isSecretField(k) && v.length > 0 && !vault.isEncrypted(v)) {\n // This was a decrypted secret — re-encrypt it\n out[k] = vault.encrypt(v);\n } else if (typeof v === 'object' && v !== null) {\n out[k] = walkReencrypt(v, vault);\n } else {\n out[k] = v;\n }\n }\n return out as T;\n}\n\n/**\n * Restrict a file to owner-only access. On POSIX this is chmod 0o600.\n * On Windows, chmod is a no-op — we use icacls to remove inherited\n * permissions and grant only the current user. Failures are logged\n * but not thrown so callers are not blocked on unsupported platforms.\n */\nasync function restrictFilePermissions(\n filePath: string,\n opts?: { warn?: (msg: string) => void },\n): Promise<void> {\n const warn = opts?.warn ?? ((msg: string) => console.warn(msg));\n if (process.platform === 'win32') {\n try {\n const { execFile } = await import('node:child_process');\n const { promisify } = await import('node:util');\n const execFileAsync = promisify(execFile);\n const user = windowsAccountName();\n if (!user) {\n warn(\n `[secret-vault] Could not determine the current Windows user for ${filePath}; skipping icacls hardening.`,\n );\n return;\n }\n // Remove inherited ACEs, grant full control only to current user.\n await execFileAsync('icacls', [filePath, '/inheritance:r', '/grant:r', `${user}:(F)`]);\n } catch {\n // Best-effort: icacls may not be available in all environments.\n warn(\n `[secret-vault] Could not restrict permissions on ${filePath} — config file may be readable by other users on this system.`,\n );\n }\n } else {\n try {\n await fsp.chmod(filePath, 0o600);\n } catch {\n // Best-effort\n }\n }\n}\n\nfunction windowsAccountName(): string | undefined {\n const username = process.env.USERNAME || process.env.USER;\n if (!username || username.includes('\\0')) return undefined;\n const domain = process.env.USERDOMAIN;\n if (domain && !domain.includes('\\0')) return `${domain}\\\\${username}`;\n return username;\n}\n\nfunction walkCount<T>(node: T, vault: SecretVault, counter: { n: number }): T {\n if (node === null || node === undefined) return node;\n if (typeof node !== 'object') return node;\n if (Array.isArray(node)) {\n return node.map((item) => walkCount(item, vault, counter)) as never as T;\n }\n const out: Record<string, unknown> = Object.create(null);\n for (const [k, v] of Object.entries(node as Record<string, unknown>)) {\n if (typeof v === 'string' && isSecretField(k) && !vault.isEncrypted(v) && v.length > 0) {\n out[k] = vault.encrypt(v);\n counter.n++;\n } else if (typeof v === 'object' && v !== null) {\n out[k] = walkCount(v, vault, counter);\n } else {\n out[k] = v;\n }\n }\n return out as T;\n}\n\n/** Keys that, when written into a plain object, can poison the prototype\n * chain. We never want user config to carry these. */\nimport { deepMerge } from '../utils/deep-merge.js';\n","import { expectDefined } from '../utils/expect-defined.js';\nexport type ContextWindowModeId = 'balanced' | 'frugal' | 'deep' | 'archival';\n\nexport type ContextWindowAggressiveOn = 'hard' | 'soft' | 'warn';\n\nexport interface ContextWindowThresholds {\n warn: number;\n soft: number;\n hard: number;\n}\n\nexport interface ContextWindowMode {\n id: ContextWindowModeId;\n name: string;\n description: string;\n thresholds: ContextWindowThresholds;\n aggressiveOn: ContextWindowAggressiveOn;\n preserveK: number;\n eliseThreshold: number;\n targetLoad: number;\n}\n\nexport interface ContextWindowPolicy extends ContextWindowMode {}\n\nexport interface ContextWindowConfigLike {\n mode?: ContextWindowModeId | string | undefined;\n warnThreshold?: number | undefined;\n softThreshold?: number | undefined;\n hardThreshold?: number | undefined;\n preserveK?: number | undefined;\n eliseThreshold?: number | undefined;\n}\n\nexport const DEFAULT_CONTEXT_WINDOW_MODE_ID: ContextWindowModeId = 'balanced';\n\nexport const CONTEXT_WINDOW_MODES: readonly ContextWindowMode[] = Object.freeze([\n {\n id: 'balanced',\n name: 'Balanced',\n description: 'Default rolling compaction: recent work stays verbatim, old tool output is trimmed.',\n thresholds: { warn: 0.6, soft: 0.75, hard: 0.9 },\n aggressiveOn: 'soft',\n preserveK: 10,\n eliseThreshold: 2000,\n targetLoad: 0.65,\n },\n {\n id: 'frugal',\n name: 'Frugal',\n description: 'Token-saver mode: compacts early and keeps a tighter verbatim tail.',\n thresholds: { warn: 0.45, soft: 0.6, hard: 0.75 },\n aggressiveOn: 'warn',\n preserveK: 6,\n eliseThreshold: 700,\n targetLoad: 0.5,\n },\n {\n id: 'deep',\n name: 'Deep',\n description: 'Long-reasoning mode: delays compaction and keeps more recent turns intact.',\n thresholds: { warn: 0.72, soft: 0.86, hard: 0.96 },\n aggressiveOn: 'hard',\n preserveK: 18,\n eliseThreshold: 5000,\n targetLoad: 0.78,\n },\n {\n id: 'archival',\n name: 'Archival',\n description: 'Decision-preserving mode: compacts steadily while keeping summaries prominent.',\n thresholds: { warn: 0.55, soft: 0.7, hard: 0.84 },\n aggressiveOn: 'soft',\n preserveK: 8,\n eliseThreshold: 1200,\n targetLoad: 0.58,\n },\n]);\n\nexport function listContextWindowModes(): ContextWindowMode[] {\n return CONTEXT_WINDOW_MODES.map((m) => ({ ...m, thresholds: { ...m.thresholds } }));\n}\n\nexport function getContextWindowMode(id: string | null | undefined): ContextWindowMode | null {\n if (!id) return null;\n const mode = CONTEXT_WINDOW_MODES.find((m) => m.id === id);\n return mode ? { ...mode, thresholds: { ...mode.thresholds } } : null;\n}\n\nexport function isContextWindowModeId(id: string): id is ContextWindowModeId {\n return CONTEXT_WINDOW_MODES.some((m) => m.id === id);\n}\n\nexport function resolveContextWindowPolicy(\n config: ContextWindowConfigLike = {},\n overrideMode?: string | null | undefined,\n): ContextWindowPolicy {\n const requested = overrideMode ?? config.mode ?? DEFAULT_CONTEXT_WINDOW_MODE_ID;\n const mode = getContextWindowMode(requested) ?? expectDefined(getContextWindowMode(DEFAULT_CONTEXT_WINDOW_MODE_ID));\n\n if (mode.id !== DEFAULT_CONTEXT_WINDOW_MODE_ID) {\n return mode;\n }\n\n return {\n ...mode,\n thresholds: {\n warn: config.warnThreshold ?? mode.thresholds.warn,\n soft: config.softThreshold ?? mode.thresholds.soft,\n hard: config.hardThreshold ?? mode.thresholds.hard,\n },\n preserveK: config.preserveK ?? mode.preserveK,\n eliseThreshold: config.eliseThreshold ?? mode.eliseThreshold,\n };\n}\n\nexport function formatContextWindowModeList(activeId?: string | null): string {\n return CONTEXT_WINDOW_MODES.map((m) => {\n const marker = m.id === activeId ? '*' : ' ';\n return `${marker} ${m.id.padEnd(9)} ${m.name} - ${m.description}`;\n }).join('\\n');\n}\n","import type { ContextWindowModeId } from './context-window.js';\nimport type { HookEvent, ShellHook } from './hooks.js';\nimport type { WireFamily } from './models-registry.js';\nimport type { CacheTtl, Capabilities, ReasoningEffort } from './provider.js';\nimport type { Permission } from './tool.js';\n\n/**\n * Runtime reasoning controls the user can set per-session/project. Mapped into\n * the provider `Request.reasoning` field by the model-runtime request\n * middleware, gated by the active model's `reasoningConfig` capabilities so\n * unsupported values are omitted (and warned) instead of triggering provider\n * 400s. See `resolveReasoningForRequest()` in packages/core.\n */\nexport interface ModelRuntimeReasoningConfig {\n /**\n * Whether to send explicit reasoning enable/disable.\n * - 'auto' → do not send explicit fields; provider/model default wins\n * - 'on' → send `reasoning.enabled = true`\n * - 'off' → send `reasoning.enabled = false` only when the model supports disable\n */\n mode?: 'auto' | 'on' | 'off' | undefined;\n /** Reasoning effort. Only sent when the model advertises `effortSupported`. */\n effort?: ReasoningEffort | undefined;\n /** Preserve thinking across turns. Only sent when `preserveThinking !== 'unsupported'`. */\n preserve?: boolean | undefined;\n}\n\n/**\n * Runtime prompt-cache controls mapped into `Request.cache`. Currently only the\n * Anthropic TTL toggle (5m vs 1h) is exposed; other providers ignore it.\n */\nexport interface ModelRuntimeCacheConfig {\n ttl?: CacheTtl | undefined;\n}\n\n/**\n * Shared runtime controls applied to every provider request, regardless of host\n * (REPL / TUI / WebUI). The CLI installs a single request-pipeline middleware\n * that reads these and mutates the outgoing `Request`.\n */\nexport interface ModelRuntimeConfig {\n reasoning?: ModelRuntimeReasoningConfig | undefined;\n cache?: ModelRuntimeCacheConfig | undefined;\n /**\n * Generic generation parameters mapped directly onto `Request` fields.\n * Only sent when the active model's `Capabilities` advertise support.\n */\n parameters?: ModelRuntimeParametersConfig | undefined;\n}\n\n/**\n * Generic generation parameters the user can set per-session / per-project.\n * Each field maps to a `Request` field of the same name and is gated by the\n * corresponding `Capabilities` flag so unsupported models don't receive\n * parameters they'd reject.\n */\nexport interface ModelRuntimeParametersConfig {\n /** Top-K sampling (Anthropic, Gemini). Gated by `capabilities.topK`. */\n topK?: number | undefined;\n /** Frequency penalty (OpenAI, Gemini). Gated by `capabilities.frequencyPenalty`. */\n frequencyPenalty?: number | undefined;\n /** Presence penalty (OpenAI, Gemini). Gated by `capabilities.presencePenalty`. */\n presencePenalty?: number | undefined;\n /** Random seed (OpenAI, Gemini). Gated by `capabilities.seed`. */\n seed?: number | undefined;\n /** End-user identifier for abuse monitoring. */\n user?: string | undefined;\n /** Log probabilities (OpenAI, Gemini). Gated by `capabilities.logprobs`. */\n logprobs?: boolean | undefined;\n /** Number of top logprobs to return (OpenAI). Only when `logprobs` is true. */\n topLogprobs?: number | undefined;\n}\n\n/**\n * HQ client connection settings. Same-machine clients can auto-discover the\n * local HQ auth file; remote clients use this config-backed URL/token pair.\n */\nexport interface HqClientConfig {\n /** Enable HQ publishing. Env WRONGSTACK_HQ_ENABLED still overrides at runtime. */\n enabled?: boolean | undefined;\n /** HQ HTTP base URL, e.g. http://host:3499. */\n url?: string | undefined;\n /** Client token for /ws/client. Stored encrypted by SecretVault when persisted. */\n token?: string | undefined;\n /** Optional HQ data dir for same-machine auth.json discovery. */\n dataDir?: string | undefined;\n /** Send raw content previews to HQ instead of redacted previews. */\n rawContent?: boolean | undefined;\n /** Override project display name in HQ. */\n projectAlias?: string | undefined;\n}\n\n/**\n * Token-saving mode tier levels. Controls how aggressively the system prompt\n * is compacted to reduce per-request token consumption.\n *\n * - 'off' — Full prompt, all tools, complete guidance (no reduction)\n * - 'minimal' — TIER1 tools only (~10), stripped guidance (~3-4k tokens saved)\n * - 'light' — Core + memory tools (~14), common patterns, minimal guidance\n * - 'medium' — Most development tools (~24), some guidance (default when `true`)\n * - 'aggressive' — Maximum savings before tools become unusable (~4-5k tokens saved)\n */\nexport type TokenSavingTier = 'off' | 'minimal' | 'light' | 'medium' | 'aggressive';\n\n/**\n * Normalize a TokenSavingTier value, handling backward-compatible boolean inputs.\n * - `true` → 'medium' (existing behavior)\n * - `false` → 'off'\n * - string values are returned as-is after validation\n * - `undefined` → 'off'\n */\nexport function normalizeTokenSavingTier(\n val?: TokenSavingTier | boolean,\n): TokenSavingTier {\n if (val === undefined) return 'off';\n if (typeof val === 'boolean') return val ? 'medium' : 'off';\n const validTiers = new Set<TokenSavingTier>([\n 'off',\n 'minimal',\n 'light',\n 'medium',\n 'aggressive',\n ]);\n return validTiers.has(val) ? val : 'off';\n}\n\nexport const DEFAULT_TUI_THINKING_WORD = 'thinking';\nexport const MAX_TUI_THINKING_WORD_LENGTH = 16;\n\n/**\n * Normalize the configurable statusline word shown while the TUI is working.\n * The value must be a single short word; invalid values fall back to the default.\n */\nexport function normalizeTuiThinkingWord(value: unknown): string {\n if (typeof value !== 'string') return DEFAULT_TUI_THINKING_WORD;\n const word = value.trim();\n if (word.length === 0 || word.length > MAX_TUI_THINKING_WORD_LENGTH) {\n return DEFAULT_TUI_THINKING_WORD;\n }\n if (!/^[\\p{L}\\p{N}_-]+$/u.test(word)) return DEFAULT_TUI_THINKING_WORD;\n return word;\n}\n\nexport interface ContextConfig {\n /** Context-window policy mode. Controls compaction thresholds and preservation depth. */\n mode?: ContextWindowModeId | undefined;\n warnThreshold: number;\n softThreshold: number;\n hardThreshold: number;\n /** Enable automatic compaction when thresholds are crossed (default: true). */\n autoCompact?: boolean | undefined;\n /**\n * Model used for LLM-assisted summarization in IntelligentCompactor.\n * Falls back to the main model when omitted.\n */\n summarizerModel?: string | undefined;\n /**\n * Override the effective context window size (in tokens). Use this when\n * you want the compactor to trigger earlier than the provider's actual\n * maxContext. Defaults to the provider's reported maxContext.\n */\n effectiveMaxContext?: number | undefined;\n maxSessionTokens?: number | undefined;\n maxDailyTokens?: number | undefined;\n preserveK: number;\n eliseThreshold: number;\n /** Compactor strategy: 'hybrid' (default, fast rules), 'intelligent' (LLM summarization), 'selective' (LLM-driven selection). */\n strategy?: 'hybrid' | 'intelligent' | 'selective' | undefined;\n /** Enable LLM-driven selective compaction (default: false for backward compat). */\n llmSelector?: boolean | undefined;\n}\n\n/**\n * Runtime configuration for the process circuit breaker (the one owned by the\n * ProcessRegistry that gates `bash`/`exec`). Toggle via `/settings breaker`.\n *\n * The breaker itself is a low-level primitive (`packages/tools/.../circuit-breaker.ts`)\n * that is on by default; this section controls whether the registry actually\n * participates in it and how it auto-recovers.\n */\nexport interface CircuitBreakerRuntimeConfig {\n /**\n * Enable circuit-breaker protection. When false (the default), the breaker\n * is bypassed — `bash`/`exec` calls always proceed regardless of failure\n * history. When true, the breaker trips on repeated failures / slow calls /\n * bursts and blocks further calls until it recovers.\n */\n enabled?: boolean | undefined;\n /**\n * When the breaker trips, automatically kill all tracked processes AND\n * reset the breaker to closed after this delay (ms). 0 = disabled (manual\n * recovery only via `/kill reset`). Only effective when `enabled` is true.\n * While armed, the statusline shows a live countdown to the kill/reset.\n */\n autoKillResetMs?: number | undefined;\n}\n\n/**\n * Adaptive concurrency controller configuration. When enabled, the controller\n * automatically adjusts `maxConcurrent` based on rate-limit (429) errors:\n * - On 429: halves `maxConcurrent` (floor at 1)\n * - On sustained success (no 429 for `recoveryIntervalMs`): increases `maxConcurrent` by 1\n */\nexport interface AdaptiveConcurrencyConfig {\n /** Enable adaptive concurrency. Default: false (disabled). */\n enabled?: boolean | undefined;\n /**\n * Minimum concurrency floor. The controller never drops below this.\n * Default: 1.\n */\n minConcurrent?: number | undefined;\n /**\n * Maximum concurrency ceiling. The controller never exceeds this.\n * Default: 16 (matches MultiAgentCoordinator default).\n */\n maxConcurrent?: number | undefined;\n /**\n * Multiplicative decrease factor when a 429 is hit.\n * `newConcurrency = floor(currentConcurrency * decreaseFactor)`.\n * Default: 0.5 (halves concurrency).\n */\n decreaseFactor?: number | undefined;\n /**\n * Number of consecutive successful requests before increasing concurrency by 1.\n * Default: 10.\n */\n successThreshold?: number | undefined;\n /**\n * How often (ms) to check for recovery and bump concurrency.\n * Default: 30_000 (30 seconds).\n */\n recoveryIntervalMs?: number | undefined;\n}\n\nexport interface ToolsConfig {\n defaultExecutionStrategy: 'parallel' | 'sequential' | 'smart';\n maxIterations: number;\n iterationTimeoutMs: number;\n sessionTimeoutMs: number;\n perIterationOutputCapBytes: number;\n /**\n * Per-tool prose budget for the tool's top-level description and usage hint.\n * Missing entries default to \"extend\".\n */\n descriptionMode?: ToolDescriptionModeConfig | undefined;\n /**\n * Per-tool on-screen result rendering mode (terminal / WebUI / TUI).\n * Missing entries default to \"extend\". Independent of `descriptionMode`:\n * `/tool <name> result simple` toggles this without touching the\n * LLM-side description length.\n */\n resultRenderMode?: ToolResultRenderModeConfig | undefined;\n /**\n * Tool names to disable. Disabled tools are excluded from the tool registry\n * (`ToolRegistry.list()` / `get()`), so they do NOT appear in the system\n * prompt's \"## Tool usage\" block — reducing per-request token consumption.\n * Override per-session with `/tool enable <name>` or re-enable all via\n * `/tool enable-all`.\n */\n disabledTools?: string[] | undefined;\n /**\n * When true (default), the agent automatically extends its iteration\n * limit by 100 when hit. Set to false to require user confirmation.\n */\n autoExtendLimit?: boolean | undefined;\n /**\n * When true, file tools (read/write/edit/grep/glob/install) are confined to\n * the project root and `set_working_dir` may not leave it. Default: false —\n * tools may access paths outside the project root, still subject to each\n * tool's permission tier (writes/edits prompt for confirmation). Toggle via\n * `/settings` (\"Filesystem access\").\n */\n restrictToProjectRoot?: boolean | undefined;\n /**\n * Per-command policy for the `exec` tool's allowlist. The tool ships a\n * curated default allowlist of dev/build commands; this extends or trims it.\n *\n * SECURITY: `allow` EXPANDS what the agent may execute, so it is honored only\n * from TRUSTED config (`~/.wrongstack/config.json`) — the config loader\n * strips `tools.exec.allow` from the untrusted, repo-committed\n * `<project>/.wrongstack/config.json`. `deny` only ever REMOVES commands, so\n * it is honored from any source.\n */\n exec?: ExecToolConfig | undefined;\n}\n\n/** Allow/deny extension of the `exec` tool's built-in command allowlist. */\nexport interface ExecToolConfig {\n /**\n * Extra command names to add to the allowlist (e.g. `[\"make\", \"dotnet\"]`).\n * Trusted sources only — stripped from in-project repo config.\n */\n allow?: string[] | undefined;\n /**\n * Command names to remove from the allowlist. Honored from any source —\n * removing a command can only narrow what runs, so it is always safe.\n */\n deny?: string[] | undefined;\n}\n\nexport type ToolDescriptionMode = 'extend' | 'simple';\nexport type ToolDescriptionModeConfig = Record<string, ToolDescriptionMode | undefined>;\n\n/**\n * Per-tool on-screen result rendering mode. Independent of\n * {@link ToolDescriptionMode}: `descriptionMode` controls the prose the\n * model sees in the system prompt, `resultRenderMode` controls how the\n * tool's RESULT is printed to the user (terminal / WebUI / TUI).\n *\n * - `simple` — meta only (filename, line count, exit code). Body is hidden\n * by default; the user can still expand on demand where the renderer\n * supports it.\n * - `extend` — full preview, up to 10 lines for read-like tools.\n *\n * The two modes are toggled independently via `/tool <name> desc simple`\n * and `/tool <name> result simple`. The legacy `/tool <name> simple`\n * command sets BOTH at once for backward compatibility.\n */\nexport type ToolResultRenderMode = 'extend' | 'simple';\nexport type ToolResultRenderModeConfig = Record<string, ToolResultRenderMode | undefined>;\n\nexport interface ProviderApiKey {\n /** Short human-readable label (e.g. \"personal\", \"work\", \"rate-limit-backup\"). */\n label: string;\n /**\n * The key itself. The field name contains `apiKey` so the secret-vault\n * walker will encrypt it on write and decrypt it on read.\n */\n apiKey: string;\n /** ISO-8601 timestamp the key was added. */\n createdAt: string;\n /**\n * How this credential was obtained.\n * - `api_key` — manually pasted API key (default)\n * - `oauth` — OAuth 2.0 device-code / authorization-code flow\n * - `session_token` — extracted from browser session (ChatGPT web, etc.)\n */\n authMethod?: 'api_key' | 'oauth' | 'session_token' | undefined;\n /** ISO-8601 expiry. When set, the token manager will refresh before this time. */\n expiresAt?: string | undefined;\n /**\n * OAuth refresh token. Stored encrypted by the secret-vault walker because\n * the field name contains `Token` (case-insensitive match by vault).\n */\n refreshToken?: string | undefined;\n /** Token type as returned by the OAuth endpoint (e.g. \"bearer\"). */\n tokenType?: string | undefined;\n /** OAuth scope string (e.g. \"openai.models.read openai.models.use\"). */\n scope?: string | undefined;\n /**\n * ChatGPT account id, extracted from the OAuth access-token JWT\n * (`https://api.openai.com/auth`.chatgpt_account_id). Sent as the\n * `chatgpt-account-id` header by the `openai-codex` wire family. Cached\n * here for display/diagnostics; the provider re-derives it from the live\n * token at request time so it can never go stale after a refresh.\n */\n accountId?: string | undefined;\n}\n\nexport interface ProviderConfig {\n type: string;\n /**\n * Legacy single-key field. Still honored as a read fallback when `apiKeys`\n * is empty (for configs not yet migrated to multi-key format). After key\n * management operations (`writeKeysBack`), this field is **cleared** to\n * prevent accidental serialization of the plaintext key. Consumers that\n * need the active API key should use `resolveActiveApiKey()` (cli) or\n * resolve from `apiKeys[]` directly — never read `cfg.apiKey` in new code.\n */\n apiKey?: string | undefined;\n /** Multiple keys for the same provider — pick one with `activeKey`. */\n apiKeys?: ProviderApiKey[] | undefined;\n /** Label of the entry in `apiKeys` to use. Defaults to the first one. */\n activeKey?: string | undefined;\n baseUrl?: string | undefined;\n headers?: Record<string, string>;\n model?: string | undefined;\n quirks?: Record<string, unknown>;\n capabilities?: Record<string, unknown>;\n /**\n * Optional wire-family override. When present, the provider can be\n * constructed without consulting the models.dev catalog — useful for\n * self-hosted endpoints, internal proxies, or for working offline.\n */\n family?: WireFamily | undefined;\n /** Custom env var names to probe when `apiKey` is missing. */\n envVars?: string[] | undefined;\n /** Optional list of models the user wants visible for this provider. */\n models?: string[] | undefined;\n /**\n * Provider-relative custom model definitions (maps modelId → definition).\n * Each entry adds/overrides a model for this provider with optional\n * capability overrides. The model id is the key, not a fully qualified id.\n */\n customModels?: Record<string, CustomModelDefinition>;\n /**\n * Per-provider OAuth configuration. When present, `wstack auth login <id>`\n * uses this instead of prompting for a raw API key. Set by the catalog or\n * by the user via `/settings`.\n */\n oauthConfig?: {\n /** OAuth client id registered with the provider. */\n clientId?: string | undefined;\n /** Device authorization endpoint (RFC 8628). */\n deviceCodeEndpoint?: string | undefined;\n /** Token endpoint for code exchange and refresh. */\n tokenEndpoint?: string | undefined;\n /** Authorization server URL shown to the user for opening in browser. */\n authorizationEndpoint?: string | undefined;\n /** Default OAuth scopes to request. */\n scopes?: string[] | undefined;\n } | undefined;\n}\n\n/**\n * One entry in the per-task model matrix. Pins a catalog role, a phase, or\n * the `*` default to a specific model (and, optionally, a specific provider).\n * Resolved at subagent-spawn time so e.g. `security-scanner` can run a\n * different model than `documentation` while the leader stays on its own.\n */\nexport interface ModelMatrixEntry {\n /** Provider registry id (e.g. \"anthropic\", \"minimax\", \"zai\"). When omitted,\n * the leader's provider is used with this entry's model. */\n provider?: string | undefined;\n /** Model id to run for the matched role/phase/default. */\n model?: string | undefined;\n /**\n * Named fallback profile to use for the matched role/phase/default. When\n * `model` is omitted, the first model in the profile becomes the primary and\n * the remaining entries become that subagent's fallback chain.\n */\n fallbackProfile?: string | undefined;\n}\n\nexport interface MCPServerConfig {\n /** Human-readable description shown in `wstack mcp list`. */\n description?: string | undefined;\n name: string;\n transport: 'stdio' | 'sse' | 'streamable-http';\n command?: string | undefined;\n args?: string[] | undefined;\n env?: Record<string, string>;\n url?: string | undefined;\n headers?: Record<string, string>;\n enabled?: boolean | undefined;\n allowedTools?: string[] | undefined;\n permission?: Permission | undefined;\n startupTimeoutMs?: number | undefined;\n requestTimeoutMs?: number | undefined;\n /**\n * Lazy connect: when true, the server process is NOT spawned at boot. Its\n * tools are registered from a cached manifest (discovered on the first ever\n * connect) and the server only spawns when one of its tools is actually\n * called, then auto-sleeps after an idle period. Default (false/undefined) =\n * eager connect at boot.\n */\n lazy?: boolean | undefined;\n}\n\nexport interface LogConfig {\n level: 'error' | 'warn' | 'info' | 'debug' | 'trace';\n file?: string | undefined;\n}\n\nexport interface PluginConfig {\n name: string;\n enabled?: boolean | undefined;\n options?: Record<string, unknown>;\n}\n\n/**\n * Optional subsystems that the CLI can boot without. The core flow\n * (provider + agent loop + bundled tools + session) always works; these\n * just add capabilities. `--no-features` flips all of these off, which\n * is the minimum viable WrongStack: a single provider, a fixed config,\n * no network calls at startup.\n */\nexport interface FeaturesConfig {\n /** Load MCP servers declared in `mcpServers`. */\n mcp: boolean;\n /** Load + initialise npm plugins declared in `plugins`. */\n plugins: boolean;\n /** Register `remember` / `forget` tools backed by memory store. */\n memory: boolean;\n /**\n * Automatically consolidate session learnings into long-term memory\n * after each completed run. The agent extracts key facts, conventions,\n * and decisions via a lightweight LLM call and persists them.\n * Enabled by default when `memory` is on; set to false to opt out.\n */\n memoryConsolidation?: boolean | undefined;\n /** Fetch the models.dev catalog at startup. When false, the provider\n * must declare its `family` explicitly in `providers[<id>]`. */\n modelsRegistry: boolean;\n /** Discover + load skills from disk. */\n skills: boolean;\n /**\n * Enable the prompt library (`/prompt`, `/prompts`, `/prompt-gen`, the WebUI\n * modal and the bundled 168-prompt dataset). Defaults to on; set to false to\n * disable the subsystem entirely (the loader is withheld so every surface\n * reports it unavailable).\n */\n prompts?: boolean | undefined;\n /**\n * Token-saving mode tier. Controls how aggressively the system prompt\n * is compacted to reduce per-request token consumption.\n *\n * - 'off' — Full prompt, all tools, complete guidance\n * - 'minimal' — TIER1 tools only, stripped guidance (~3-4k tokens saved)\n * - 'light' — Core + memory tools, common patterns, minimal guidance\n * - 'medium' — Most development tools, some guidance\n * - 'aggressive' — Maximum savings before tools become unusable (~4-5k tokens)\n *\n * Boolean values are accepted for backward compatibility:\n * - `true` → 'medium'\n * - `false` → 'off'\n *\n * Enable via CLI: `--token-saving-tier <level>` or `--token-saving-mode` (maps to 'medium').\n * Configure via: `features.tokenSavingMode: \"minimal\"` in config.\n */\n tokenSavingMode?: TokenSavingTier | boolean | undefined;\n /**\n * Allow tools to read/write paths outside the project root directory.\n * When true (default), tools can access any path on the filesystem.\n * When false, tools are restricted to the project root directory.\n */\n allowOutsideProjectRoot?: boolean | undefined;\n /**\n * Auto-bootstrap the mailbox HTTP bridge from any WrongStack surface\n * (REPL/TUI/WebUI/eternal). When 'auto' (the default), the first\n * surface to come up for a given project joins or spawns the bridge\n * so external agents can connect without the user running\n * `wstack mailbox serve` themselves. 'off' disables this — operators\n * must start the bridge explicitly (e.g. via the `/mailbox-serve`\n * slash command or the standalone `wstack mailbox serve` subcommand).\n * The per-project lock + token-persistence model means a second\n * surface on the same project joins the first's bridge rather than\n * spawning a duplicate.\n */\n mailboxBridge?: 'auto' | 'off' | undefined;\n}\n\nexport interface AutonomyConfig {\n /** Default autonomy mode at startup. Default: \"off\". */\n defaultMode?: 'off' | 'suggest' | 'auto' | undefined;\n /** ms to wait before auto-proceeding in 'auto' mode. Default: 45000. */\n autoProceedDelayMs?: number | undefined;\n /** Maximum consecutive auto-proceed turns before pausing. 0 = unlimited. Default: 50. */\n autoProceedMaxIterations?: number | undefined;\n /** Template used for YOLO+auto suggestions. Must include {{suggestion}}. */\n autonomyNextPrompt?: string | undefined;\n /** Animate the terminal/window title while the agent is active. Default: true. */\n terminalTitleAnimation?: boolean | undefined;\n /** Persisted YOLO preference mirrored into top-level config.yolo at runtime. Default: false. */\n yolo?: boolean | undefined;\n /** Stream fleet/subagent output into the main TUI chat. Default: true. */\n streamFleet?: boolean | undefined;\n /** Ring terminal bell when an agent run completes. Default: false. */\n chime?: boolean | undefined;\n /** Ask for confirmation before interrupt/exit. Default: true. */\n confirmExit?: boolean | undefined;\n /** Terminal mouse tracking preference. Default: false. */\n mouseMode?: boolean | undefined;\n /** Enable prompt refinement before sending. Default: true. */\n enhance?: boolean | undefined;\n /** Prompt-refinement preview countdown in ms. Default: 60000. */\n enhanceDelayMs?: number | undefined;\n /** Prompt-refinement language mode. Default: \"original\". */\n enhanceLanguage?: 'original' | 'english' | undefined;\n /** TUI statusline density. Default: \"detailed\". */\n statuslineMode?: 'minimum' | 'detailed' | undefined;\n /** Single short word shown in the TUI rainbow working-state chip. Default: \"thinking\". */\n thinkingWord?: string | undefined;\n}\n\n/**\n * Automatic codebase symbol-index maintenance. Keeps the `codebase-search`\n * index (SQLite, `~/.wrongstack/projects/<hash>/codebase-index/index.db`) fresh\n * without the user having to call `codebase-index` by hand.\n */\nexport interface IndexingConfig {\n /** Run a blocking incremental index at session start (with a visible summary). Default: true. */\n onSessionStart: boolean;\n /** Reindex files the agent writes/edits via tools, in the background. Default: true. */\n onEdit: boolean;\n /** Watch the project root for external editor changes and reindex them. Default: true. */\n watchExternal: boolean;\n /** Debounce window (ms) coalescing rapid edits to the same file. Default: 400. */\n debounceMs: number;\n /**\n * Watchdog timeout (ms) for a full index run. A run exceeding this is\n * aborted (so it can never wedge the indexing mutex or freeze the terminal)\n * and counts toward the indexing circuit breaker. Default: 120000.\n */\n indexTimeoutMs?: number | undefined;\n}\n\n/**\n * Saved launch preferences — restored on next boot so the pre-launch prompt\n * can offer a one-line \"Continue with last settings? [Y/n]\" instead of\n * re-asking every question from scratch.\n */\nexport interface LaunchConfig {\n /** Interactive mode: 'tui' (Ink TUI) or 'repl' (readline REPL). */\n mode?: 'tui' | 'repl' | undefined;\n /** Start with Director mode on (fleet manifest + multi-agent orchestration). */\n director?: boolean | undefined;\n /**\n * Launch-time autonomy mode (binary choice from pre-launch prompt).\n * 'off' = stops after each turn; 'auto' = self-driving.\n * Distinct from `AutonomyConfig.defaultMode` which also supports 'suggest'.\n */\n autonomy?: 'off' | 'auto' | undefined;\n}\n\n/**\n * Controls how much detail is persisted to the per-session JSONL log\n * (`~/.wrongstack/projects/<hash>/sessions/<id>.jsonl`).\n */\nexport interface SessionLoggingConfig {\n /**\n * How much detail to write to the persistent session log.\n *\n * - \"minimal\" → Only events required for resume/rewind/recovery\n * - \"standard\" → (default) + high-value lightweight audit events\n * (compaction, tool timing, retries, errors, etc.)\n * - \"full\" → Also persist full request payloads (very large).\n * Consider enabling a separate replay log instead.\n */\n auditLevel?: 'minimal' | 'standard' | 'full' | undefined;\n\n /**\n * Sampling configuration for high-volume events (especially relevant at\n * `auditLevel: \"full\"`).\n */\n sampling?: {\n /** Controls sampling of `tool_progress` events. */\n toolProgress?: {\n /**\n * Sample rate for noisy progress events (`log`, `partial_output`).\n * - 1 = no sampling (every message is logged)\n * - 8 = default (first message + every 8th)\n */\n sampleRate?: number | undefined;\n };\n };\n}\n\nexport type SyncCategory = 'settings' | 'skills' | 'prompts' | 'memory' | 'history';\n\nexport interface SyncConfig {\n enabled: boolean;\n repo: string;\n /** GitHub token (fine-grained PAT). Encrypted at rest via SecretVault. */\n githubToken: string;\n categories: SyncCategory[];\n lastSyncedAt?: string | undefined;\n}\n\n/**\n * Per-model capability overrides the user can define in their config.\n * Used to add models not in the models.dev catalog, or override catalog\n * facts when the real backend differs (e.g. local Ollama models, proxies).\n */\nexport interface CustomModelDefinition {\n /** Provider this model belongs to. Defaults to the owning ProviderConfig. */\n provider?: string | undefined;\n /** Optional display name. */\n name?: string | undefined;\n /** Capability overrides — only specified fields are overlaid. */\n capabilities?: Partial<Capabilities> | undefined;\n /**\n * Max output tokens. If not specified, the provider family default\n * or catalog entry is used.\n */\n maxOutput?: number | undefined;\n}\n\nexport interface Config {\n version: 1;\n provider: string;\n model: string;\n apiKey?: string | undefined;\n baseUrl?: string | undefined;\n /**\n * Maximum number of subagent tasks the fleet coordinator dispatches\n * simultaneously. Extra tasks queue until a slot frees. Default: 4.\n * Overridden by WRONGSTACK_MAX_CONCURRENT env var and --max-concurrent\n * CLI flag. Change at runtime with /fleet concurrency <n>.\n */\n maxConcurrent?: number | undefined;\n providers?: Record<string, ProviderConfig>;\n /**\n * Top-level custom models (maps modelId → definition). Merged with\n * per-provider `customModels` at resolution time. The key is the\n * model id — not a fully qualified name. When the same model id\n * appears in both places, the top-level one wins.\n */\n models?: Record<string, CustomModelDefinition>;\n /**\n * Per-task model matrix. Keys are catalog roles (e.g. \"security-scanner\"),\n * phase names (e.g. \"review\"), or the `*` default. Resolution precedence at\n * subagent spawn: exact role → the role's phase → `*` → leader model. Set via\n * the `/setmodel` slash command; persisted to ~/.wrongstack/config.json.\n */\n modelMatrix?: Record<string, ModelMatrixEntry>;\n /**\n * User-curated model references shown/prioritized by model commands and used\n * by smart fallback derivation. Entries are `model`, `provider/model`, or\n * `provider model`.\n */\n favoriteModels?: string[] | undefined;\n /**\n * When true, auto-derived fallback chains are restricted to `favoriteModels`.\n * Explicit fallback profiles/chains are always honored as written.\n */\n favoriteModelsOnly?: boolean | undefined;\n context: ContextConfig;\n tools: ToolsConfig;\n mcpServers?: Record<string, MCPServerConfig>;\n /**\n * Per-agent ACP invocation overrides, keyed by catalog agent id\n * (`claude-code`, `codex-cli`, `gemini-cli`, …). Lets a user correct an\n * agent's ACP entry command — e.g. point `claude-code` at the right\n * adapter — without a code change. Consumed by `/acp`, `/ensemble`, and\n * `wstack acp`. SECURITY: this is an arbitrary-command exec surface, so it\n * is in the in-project config DENY list — only honoured from the user's\n * `~/.wrongstack/config.json`, never from a repo-committed config.\n */\n acp?: {\n agents?: Record<\n string,\n { command: string; args?: string[]; env?: Record<string, string> }\n >;\n };\n /**\n * Ordered list of fallback model references tried, in order, when the\n * primary model is overloaded (HTTP 429/529/5xx) and its own retries are\n * exhausted. Each entry is a model reference: a bare model id (same\n * provider), `provider/model`, or `provider model`. The primary is always\n * re-tried first at the start of every user turn. See `createFallbackModelExtension`.\n */\n fallbackModels?: string[] | undefined;\n /**\n * Named fallback chains. A profile's first entry can be used as a primary\n * model by `/setmodel`, while the whole ordered list is used for failover.\n */\n fallbackProfiles?: Record<string, string[]> | undefined;\n /**\n * When `true` (the default) and `fallbackModels` is empty, a fallback chain\n * is derived automatically from the other keyed providers/models so 429s\n * recover out of the box. Set `false` to disable the smart default and only\n * use an explicit `fallbackModels` list. Toggle via `/fallback auto on|off`.\n */\n fallbackAuto?: boolean | undefined;\n /**\n * Lifecycle shell hooks, keyed by event. Each command receives the hook\n * `HookInput` JSON on stdin; a JSON `HookOutcome` on stdout (and exit code 2\n * = block) steers the agent. In-process hooks are registered separately via\n * the plugin API. Disabled entirely under `--bare` / `--no-hooks`.\n */\n hooks?: Partial<Record<HookEvent, ShellHook[]>>;\n plugins?: (string | PluginConfig)[] | undefined;\n log: LogConfig;\n features: FeaturesConfig;\n yolo?: boolean | undefined;\n /** When true, show lightweight LLM-predicted next steps after each turn (/next). */\n nextPrediction?: boolean | undefined;\n cwd?: string | undefined;\n /** Autonomy mode configuration (auto-proceed delay, etc.). */\n autonomy?: AutonomyConfig | undefined;\n /** Show rotating launch hints on startup. Default: true. Set to false to suppress. */\n hints?: boolean | undefined;\n /** Raw SSE stream debugging — hex-dump every byte received from providers to stderr. */\n debugStream?: boolean | undefined;\n /**\n * Where settings are persisted. 'global' → ~/.wrongstack/config.json\n * (default). 'project' → <project>/.wrongstack/config.json.\n * When 'project', safe settings are saved per-project.\n */\n configScope?: 'global' | 'project' | undefined;\n /** Automatic codebase symbol-index maintenance (session-start + live updates). */\n indexing?: IndexingConfig | undefined;\n /**\n * Process circuit-breaker protection (gates `bash`/`exec` on repeated\n * failures). Default off — toggle with `/settings breaker on|off`.\n */\n circuitBreaker?: CircuitBreakerRuntimeConfig | undefined;\n /**\n * Adaptive concurrency controller — automatically adjusts `maxConcurrent` based on\n * rate-limit (429) errors. On 429: decreases concurrency. On sustained success:\n * gradually increases concurrency back up. Default off.\n */\n adaptiveConcurrency?: AdaptiveConcurrencyConfig | undefined;\n /** Saved launch preferences — restored on next boot for one-line confirmation. */\n launch?: LaunchConfig | undefined;\n\n /**\n * Session logging & audit configuration.\n * Controls what gets written to the persistent JSONL transcript.\n */\n session?: SessionLoggingConfig | undefined;\n /**\n * Runtime reasoning / cache controls applied to every provider request\n * (REPL/TUI/WebUI). Mapped into `Request.reasoning` and `Request.cache` by a\n * single request-pipeline middleware, gated by the active model's\n * capabilities. See `ModelRuntimeConfig`.\n */\n modelRuntime?: ModelRuntimeConfig | undefined;\n /** HQ client publishing settings, used by CLI/REPL/TUI/WebUI consistently. */\n hq?: HqClientConfig | undefined;\n /**\n * Cloud sync configuration. Stored separately in sync.json to avoid\n * accidentally committing the GitHub token to project configs.\n */\n sync?: SyncConfig | undefined;\n /**\n * Per-plugin namespaced config sections. Each plugin reads its own\n * subtree via `ConfigStore.getExtension(pluginName)`. Plugins should\n * declare a `configSchema` so the loader validates this section\n * automatically before `setup()` runs.\n *\n * Example:\n * extensions: {\n * 'wstack-auth': { tokenUrl: 'https://...', refreshBefore: 300 },\n * 'wstack-metrics': { sink: 'prometheus', port: 9090 },\n * }\n */\n extensions?: Record<string, Record<string, unknown>>;\n}\n\nexport interface ConfigLoader {\n load(opts?: { cliFlags?: Partial<Config> | undefined; cwd?: string | undefined }): Promise<Config>;\n /** Load and decrypt the sync config from ~/.wrongstack/sync.json. */\n loadSyncConfig(): Promise<SyncConfig | null>;\n /** Persist sync config to ~/.wrongstack/sync.json with encrypted token. */\n persistSyncConfig(cfg: SyncConfig): Promise<void>;\n}\n\n/**\n * Subscribable view over Config. Plugins and CLI subsystems use this instead\n * of holding a frozen Config reference, so they can react to runtime updates\n * (e.g. `/model` switching the active provider, secrets rotation, dynamic\n * extension reload).\n *\n * The store enforces immutability — `get()` always returns a frozen object.\n * Updates happen through `update(partial)`, which produces a new Config\n * (structurally cloned, then frozen) and notifies watchers.\n */\nexport interface ConfigStore {\n get(): Readonly<Config>;\n /**\n * Get a typed top-level section. Convenience for consumers that only\n * care about one slice (e.g. `tools` or `context`).\n */\n getSection<K extends keyof Config>(key: K): Readonly<Config[K]>;\n /**\n * Return the extension namespace for `pluginName`, or an empty record\n * when none is configured. The returned object is frozen.\n */\n getExtension(pluginName: string): Readonly<Record<string, unknown>>;\n /**\n * Apply a partial update. Returns the new Config. Watchers are notified\n * synchronously after the update completes. Throws if the result fails\n * any registered invariants (currently: version must stay 1).\n */\n update(partial: Partial<Config>): Readonly<Config>;\n /** Subscribe to changes. Returns an unsubscribe function. */\n watch(cb: (next: Readonly<Config>, prev: Readonly<Config>) => void): () => void;\n}\n","/**\n * Shared configuration constants used across execution, storage, CLI, and WebUI.\n * Centralized here to avoid cross-domain import cycles.\n */\n\n/** Default tools config — mirrors values baked into BEHAVIOR_DEFAULTS. */\nexport const DEFAULT_TOOLS_CONFIG = Object.freeze({\n defaultExecutionStrategy: 'smart',\n maxIterations: 100,\n iterationTimeoutMs: 300_000,\n sessionTimeoutMs: 1_800_000,\n perIterationOutputCapBytes: 100_000,\n descriptionMode: Object.freeze({}) as Record<string, 'extend' | 'simple' | undefined>,\n disabledTools: Object.freeze([]) as readonly string[],\n autoExtendLimit: true,\n restrictToProjectRoot: false,\n});\n\n/** Default context config — mirrors BEHAVIOR_DEFAULTS.context. */\nexport const DEFAULT_CONTEXT_CONFIG = Object.freeze({\n preserveK: 10,\n eliseThreshold: 2000,\n});\n\n/** Default autonomy config — auto-proceed delay etc. */\nexport const DEFAULT_AUTONOMY_CONFIG = Object.freeze({\n autoProceedDelayMs: 45_000,\n});\n\n/**\n * Default process circuit-breaker config. Protection is OFF by default — the\n * breaker only gates `bash`/`exec` once the user opts in via `/settings breaker on`.\n * The auto kill/reset delay is only consulted when protection is enabled.\n */\nexport const DEFAULT_CIRCUIT_BREAKER_CONFIG = Object.freeze({\n enabled: false,\n autoKillResetMs: 60_000,\n});\n\n/** Default session logging / audit configuration. */\nexport const DEFAULT_SESSION_LOGGING_CONFIG = Object.freeze({\n auditLevel: 'standard' as const,\n sampling: {\n toolProgress: {\n sampleRate: 8,\n },\n },\n});\n\n/** Default retention window for local session pruning. */\nexport const DEFAULT_SESSION_PRUNE_DAYS = 30;\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { decryptConfigSecrets } from '../security/secret-vault.js';\nimport { atomicWrite, withFileLock } from '../utils/atomic-write.js';\nimport { toErrorMessage } from '../utils/error.js';\nimport {\n DEFAULT_CONTEXT_WINDOW_MODE_ID,\n isContextWindowModeId,\n listContextWindowModes,\n} from '../types/context-window.js';\nimport {\n DEFAULT_TUI_THINKING_WORD,\n type Config,\n type ConfigLoader,\n type SyncConfig,\n} from '../types/config.js';\nimport type { SecretVault } from '../types/secret-vault.js';\nimport { ConfigError, ERROR_CODES } from '../types/errors.js';\nimport { safeParse } from '../utils/safe-json.js';\nimport { deepMerge as deepMergeCore, type DeepMergeOptions } from '../utils/deep-merge.js';\nimport type { WstackPaths } from '../utils/wstack-paths.js';\nimport {\n DEFAULT_AUTONOMY_CONFIG,\n DEFAULT_CIRCUIT_BREAKER_CONFIG,\n DEFAULT_TOOLS_CONFIG,\n DEFAULT_CONTEXT_CONFIG,\n DEFAULT_SESSION_LOGGING_CONFIG,\n} from '../types/default-config.js';\nimport type { EventBus } from '../kernel/events.js';\n\n/**\n * Surface the OS error code (EACCES, ENOSPC, …) alongside the message in\n * storage.* event payloads. Codes are stable and locale-independent, so\n * they are what dashboards and alerts key on; the message is supplementary.\n */\nfunction storageErrorString(err: unknown): string {\n if (err instanceof Error) {\n const code = (err as NodeJS.ErrnoException).code;\n return code ? `${code}: ${err.message}` : err.message;\n }\n /* v8 ignore next -- defensive: callers only pass fs Error instances */\n return String(err);\n}\n\n/**\n * Defaults express *behavior*, not identity. Provider and model are NOT\n * hardcoded — they must be resolved at runtime from config + env + the\n * ModelsRegistry. A bare Config returned by this loader will throw when\n * the agent tries to construct a provider, with a message that points\n * users at `wstack init`.\n */\nconst BEHAVIOR_DEFAULTS: Omit<Config, 'provider' | 'model'> = {\n version: 1,\n context: {\n mode: DEFAULT_CONTEXT_WINDOW_MODE_ID,\n warnThreshold: 0.6,\n softThreshold: 0.75,\n hardThreshold: 0.9,\n autoCompact: true,\n preserveK: DEFAULT_CONTEXT_CONFIG.preserveK,\n eliseThreshold: DEFAULT_CONTEXT_CONFIG.eliseThreshold,\n strategy: 'hybrid',\n },\n tools: {\n defaultExecutionStrategy: DEFAULT_TOOLS_CONFIG.defaultExecutionStrategy,\n maxIterations: DEFAULT_TOOLS_CONFIG.maxIterations,\n iterationTimeoutMs: DEFAULT_TOOLS_CONFIG.iterationTimeoutMs,\n sessionTimeoutMs: DEFAULT_TOOLS_CONFIG.sessionTimeoutMs,\n perIterationOutputCapBytes: DEFAULT_TOOLS_CONFIG.perIterationOutputCapBytes,\n descriptionMode: DEFAULT_TOOLS_CONFIG.descriptionMode,\n disabledTools: DEFAULT_TOOLS_CONFIG.disabledTools as string[],\n autoExtendLimit: DEFAULT_TOOLS_CONFIG.autoExtendLimit,\n restrictToProjectRoot: DEFAULT_TOOLS_CONFIG.restrictToProjectRoot,\n },\n log: { level: 'info' },\n features: {\n mcp: true,\n plugins: true,\n memory: true,\n modelsRegistry: true,\n skills: true,\n prompts: true,\n tokenSavingMode: 'off',\n allowOutsideProjectRoot: true,\n },\n mcpServers: {},\n fallbackAuto: true,\n maxConcurrent: 4,\n yolo: false,\n nextPrediction: false,\n hints: true,\n debugStream: false,\n configScope: 'global',\n indexing: {\n onSessionStart: true,\n onEdit: true,\n watchExternal: true,\n debounceMs: 400,\n },\n session: { ...DEFAULT_SESSION_LOGGING_CONFIG },\n autonomy: {\n defaultMode: 'off',\n autoProceedDelayMs: DEFAULT_AUTONOMY_CONFIG.autoProceedDelayMs,\n autoProceedMaxIterations: 50,\n autonomyNextPrompt: 'auto {{suggestion}}',\n terminalTitleAnimation: true,\n yolo: false,\n streamFleet: true,\n chime: false,\n confirmExit: true,\n mouseMode: false,\n enhance: true,\n enhanceDelayMs: 60_000,\n enhanceLanguage: 'original',\n statuslineMode: 'detailed',\n thinkingWord: DEFAULT_TUI_THINKING_WORD,\n },\n circuitBreaker: { ...DEFAULT_CIRCUIT_BREAKER_CONFIG },\n modelRuntime: {\n // `effort` is intentionally undefined by default. Leaving it unset lets\n // each model use its provider-recommended reasoning effort (or none at\n // all) instead of forcing an opinionated value that may be unsupported,\n // silently omitted, and surfaced as a per-request warning. Users who\n // want a specific effort can opt in via `/settings` or the WebUI panel.\n reasoning: { mode: 'auto' },\n cache: {},\n },\n};\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction cloneJsonValue<T>(value: T): T {\n return structuredClone(value);\n}\n\nfunction fillMissingDefaults(\n target: Record<string, unknown>,\n defaults: Record<string, unknown>,\n): { value: Record<string, unknown>; changed: boolean } {\n const value = cloneJsonValue(target);\n const changed = fillMissingDefaultsInPlace(value, defaults);\n return { value, changed };\n}\n\nfunction fillMissingDefaultsInPlace(\n target: Record<string, unknown>,\n defaults: Record<string, unknown>,\n): boolean {\n let changed = false;\n for (const [key, defaultValue] of Object.entries(defaults)) {\n if (!Object.prototype.hasOwnProperty.call(target, key)) {\n target[key] = cloneJsonValue(defaultValue);\n changed = true;\n continue;\n }\n const current = target[key];\n if (isPlainRecord(current) && isPlainRecord(defaultValue)) {\n changed = fillMissingDefaultsInPlace(current, defaultValue) || changed;\n }\n }\n return changed;\n}\n\n/** Parse a boolean-ish env var: \"0\"/\"false\"/\"no\"/\"off\" → false, anything else → true. */\nfunction envBool(v: string): boolean {\n return !/^(0|false|no|off)$/i.test(v.trim());\n}\n\nfunction envBoolOptional(v: string | undefined): boolean {\n return v !== undefined && envBool(v);\n}\n\nconst LOG_LEVELS = new Set<Config['log']['level']>(['error', 'warn', 'info', 'debug', 'trace']);\n\nfunction envLogLevel(v: string): Config['log']['level'] {\n return LOG_LEVELS.has(v as Config['log']['level']) ? (v as Config['log']['level']) : 'info';\n}\n\nconst ENV_MAP: Record<string, (cfg: PartialConfig, val: string) => void> = {\n WRONGSTACK_PROVIDER: (c, v) => {\n c.provider = v;\n if (c._envSource === undefined) c._envSource = new Set();\n c._envSource.add('provider');\n },\n WRONGSTACK_MODEL: (c, v) => {\n c.model = v;\n if (c._envSource === undefined) c._envSource = new Set();\n c._envSource.add('model');\n },\n WRONGSTACK_API_KEY: (c, v) => {\n c.apiKey = v;\n if (c._envSource === undefined) c._envSource = new Set();\n c._envSource.add('apiKey');\n },\n WRONGSTACK_BASE_URL: (c, v) => {\n c.baseUrl = v;\n if (c._envSource === undefined) c._envSource = new Set();\n c._envSource.add('baseUrl');\n },\n WRONGSTACK_LOG_LEVEL: (c, v) => {\n /* v8 ignore next -- defensive: config defaults always seed c.log before env handlers run */\n if (!c.log) c.log = { level: 'info' };\n c.log.level = envLogLevel(v);\n },\n WRONGSTACK_INDEX_ON_START: (c, v) => {\n c.indexing = { ...defaultIndexing, ...c.indexing, onSessionStart: envBool(v) };\n },\n WRONGSTACK_INDEX_ON_EDIT: (c, v) => {\n c.indexing = { ...defaultIndexing, ...c.indexing, onEdit: envBool(v) };\n },\n WRONGSTACK_INDEX_WATCH: (c, v) => {\n c.indexing = { ...defaultIndexing, ...c.indexing, watchExternal: envBool(v) };\n },\n};\n\nconst defaultIndexing = {\n onSessionStart: true,\n onEdit: true,\n watchExternal: true,\n debounceMs: 400,\n} as const;\n\ntype PartialConfig = Partial<Config> & {\n providers?: Record<\n string,\n { apiKey?: string | undefined; baseUrl?: string | undefined; type?: string | undefined }\n >;\n /** Fields that came from environment variables — must not be persisted. */\n _envSource?: Set<string> | undefined;\n};\n\n/**\n * Top-level config keys a REPO-COMMITTED `<project>/.wrongstack/config.json`\n * (the `inProjectConfig` layer) IS permitted to set. The in-project config\n * is attacker-controllable (it ships inside a cloned/pulled repository), so\n * every other field is denied by default. Anything not in this list is\n * stripped by `stripUnsafeInProjectFields()` before the merge.\n *\n * Why an allow-list and not a deny-list? A deny-list of N known-bad keys is\n * structurally incomplete: any new field added to `Config` without a matching\n * edit to the deny list silently becomes attacker-controllable, and the next\n * field that carries an executable string or a credential immediately turns\n * `<project>/.wrongstack/config.json` into an RCE / secret-exfiltration\n * vector the moment someone clones a malicious repo. An allow-list inverts\n * that — new fields are denied by default and must be explicitly added, so a\n * forgotten update is a safe default instead of an unsafe one.\n *\n * Each entry below is a benign user-preference that a project author may\n * legitimately want to pin for everyone who works in the repo:\n *\n * - `version` — schema marker required for any config merge.\n * - `model` — model id (also settable via env / CLI).\n * - `cwd` — working-directory hint (UX, not a permission).\n * - `context` — compaction thresholds, mode, preserveK.\n * - `tools` — iteration / timeouts / restrictToProjectRoot.\n * - `features` — feature toggles (display-only side effects).\n * - `autonomy` — autoProceedDelayMs, thinkingWord.\n * - `indexing` — onSessionStart / onEdit / debounceMs.\n * - `session` — audit level + sampling.\n * - `log` — log level.\n * - `launch` — saved launch prefs.\n * - `nextPrediction` — toggle `/next` after-turn suggestions.\n * - `hints` — toggle startup hints.\n * - `debugStream` — verbose SSE dump (noisy, not security-sensitive).\n * - `configScope` — where settings persist.\n * - `maxConcurrent` — fleet concurrency limit.\n * - `fallbackModels` — model references tried on 429/5xx.\n * - `fallbackProfiles` — named fallback chains.\n * - `favoriteModels` — model references preferred for display/routing.\n * - `favoriteModelsOnly` — restrict auto-derived chains to favorite models.\n * - `fallbackAuto` — derived-fallback toggle.\n * - `models` — custom model definitions (data, not code).\n * - `modelMatrix` — per-task model matrix.\n * - `circuitBreaker` — process circuit-breaker config (process gating).\n * - `adaptiveConcurrency` — adaptive concurrency controller.\n * - `modelRuntime` — runtime reasoning/cache/parameters.\n *\n * Fields deliberately NOT in the allow-list (and therefore always stripped\n * from `<project>/.wrongstack/config.json`) — see `KNOWN_DENIED_IN_PROJECT`\n * below for the reason each is unsafe.\n */\nconst IN_PROJECT_ALLOWED_KEYS: ReadonlySet<string> = new Set([\n 'version',\n 'model',\n 'cwd',\n 'context',\n 'tools',\n 'features',\n 'autonomy',\n 'indexing',\n 'session',\n 'log',\n 'launch',\n 'nextPrediction',\n 'hints',\n 'debugStream',\n 'configScope',\n 'maxConcurrent',\n 'fallbackModels',\n 'fallbackProfiles',\n 'favoriteModels',\n 'favoriteModelsOnly',\n 'fallbackAuto',\n 'models',\n 'modelMatrix',\n 'circuitBreaker',\n 'adaptiveConcurrency',\n 'modelRuntime',\n]);\n\n/**\n * Top-level config keys that exist on `Config` but MUST NEVER be settable\n * from a repo-committed `<project>/.wrongstack/config.json`. Each entry pairs\n * the field name with the specific way a malicious repo would abuse it. This\n * list is documentation + exhaustiveness checking; the runtime enforcement\n * is the *allow-list* above (anything not in the allow-list is stripped).\n *\n * - `provider` — set provider id to a custom / evil implementation →\n * intercepts every prompt and response.\n * - `apiKey` — overrides the user's API key with attacker-controlled\n * value, exfiltrating prompts to the attacker.\n * - `baseUrl` — redirects the provider endpoint so the user's real\n * decrypted API key is sent to the attacker's server.\n * - `providers` — per-provider `apiKey`/`baseUrl`/`oauthConfig` map,\n * same endpoint-redirect + secret-exfiltration vector.\n * - `mcpServers` — arbitrary `command` + `args` + `env` spawned at boot.\n * - `hooks` — shell command arrays attached to lifecycle events.\n * - `plugins` — npm package names dynamically loaded into the agent\n * process at boot.\n * - `sync` — carries `githubToken` (credential) and the repo\n * the user's sync push targets.\n * - `yolo` — flips off every permission confirmation prompt so a\n * malicious agent turn can run `bash` / `write` /\n * `install` without user approval.\n * - `extensions` — per-plugin namespaced config; the LSP plugin's\n * `servers[].command` is spawned on autoStart, and\n * arbitrary plugin configs can carry their own\n * credential / command fields → RCE / secret exposure.\n * - `hq` — carries `token` (HQ client credential) and `url`\n * (HQ endpoint, similar to `baseUrl`).\n */\nconst KNOWN_DENIED_IN_PROJECT: ReadonlyArray<{ key: string; reason: string }> = [\n { key: 'provider', reason: 'Provider id override; can intercept prompts/responses.' },\n { key: 'apiKey', reason: 'Overrides user API key; exfiltrates prompts.' },\n { key: 'baseUrl', reason: 'Redirects provider endpoint; leaks real API key.' },\n { key: 'providers', reason: 'Per-provider apiKey/baseUrl/oauthConfig; same redirect/exfil.' },\n { key: 'mcpServers', reason: 'Arbitrary command/args/env spawned at boot (RCE).' },\n { key: 'hooks', reason: 'Shell command arrays on lifecycle events (RCE).' },\n { key: 'plugins', reason: 'Dynamic npm package load at boot (RCE).' },\n { key: 'sync', reason: 'Carries githubToken credential and target repo.' },\n { key: 'yolo', reason: 'Disables all permission confirmation prompts.' },\n { key: 'extensions', reason: 'Per-plugin config can carry command/credential fields.' },\n { key: 'hq', reason: 'Carries HQ client token credential and endpoint URL.' },\n { key: 'acp', reason: 'Per-agent ACP command/args/env override → arbitrary command exec (RCE).' },\n];\n\n/**\n * Every top-level key that exists on the `Config` interface. This is the\n * *ground truth* used by `assertInProjectAllowListComplete()` to detect when\n * a new field has been added to `Config` without a corresponding decision\n * about whether it is safe for an attacker-controllable source to set it.\n *\n * Each entry must appear in EXACTLY ONE of:\n * - `IN_PROJECT_ALLOWED_KEYS` — explicitly safe for in-project config\n * - `KNOWN_DENIED_IN_PROJECT` — explicitly documented as unsafe\n *\n * The drift-check function below throws at runtime / test time when this\n * invariant is violated, so a forgotten update fails loudly instead of\n * silently widening the attack surface.\n */\nconst KNOWN_CONFIG_TOP_LEVEL_KEYS: ReadonlySet<string> = new Set([\n 'version',\n 'provider',\n 'model',\n 'apiKey',\n 'baseUrl',\n 'maxConcurrent',\n 'providers',\n 'models',\n 'modelMatrix',\n 'context',\n 'tools',\n 'mcpServers',\n 'fallbackModels',\n 'fallbackProfiles',\n 'favoriteModels',\n 'favoriteModelsOnly',\n 'fallbackAuto',\n 'hooks',\n 'plugins',\n 'log',\n 'features',\n 'yolo',\n 'nextPrediction',\n 'cwd',\n 'autonomy',\n 'hints',\n 'debugStream',\n 'configScope',\n 'indexing',\n 'circuitBreaker',\n 'adaptiveConcurrency',\n 'launch',\n 'session',\n 'modelRuntime',\n 'hq',\n 'sync',\n 'extensions',\n 'acp',\n]);\n\n/**\n * Assert that the allow-list and deny-list together cover every top-level\n * field of `Config`. Throws on drift so the failure is loud at test time and\n * at first boot, not a silent widening of the attack surface. Exported so\n * tests (and any consumer building tooling on top of this) can call it\n * explicitly; `stripUnsafeInProjectFields()` also calls it lazily on its\n * first invocation so the guarantee is structural, not test-only.\n *\n * The check is two-sided:\n * 1. Every key in `KNOWN_CONFIG_TOP_LEVEL_KEYS` is either allowed or\n * explicitly documented as denied (catches: \"added a new field but\n * forgot to decide\").\n * 2. Every entry in `KNOWN_DENIED_IN_PROJECT` actually exists on Config\n * (catches: \"left a stale denied-field entry behind after a rename\").\n * 3. The two lists are disjoint (catches: \"put the same field in both\n * lists; allow-list silently wins and the deny docs lie\").\n */\nexport function assertInProjectAllowListComplete(): void {\n const missingFromBoth: string[] = [];\n for (const key of KNOWN_CONFIG_TOP_LEVEL_KEYS) {\n if (IN_PROJECT_ALLOWED_KEYS.has(key)) continue;\n const denied = KNOWN_DENIED_IN_PROJECT.find((d) => d.key === key);\n if (!denied) missingFromBoth.push(key);\n }\n const staleDenials = KNOWN_DENIED_IN_PROJECT\n .filter((d) => !KNOWN_CONFIG_TOP_LEVEL_KEYS.has(d.key))\n .map((d) => d.key);\n const duplicate = KNOWN_DENIED_IN_PROJECT\n .filter((d) => IN_PROJECT_ALLOWED_KEYS.has(d.key))\n .map((d) => d.key);\n\n const problems: string[] = [];\n if (missingFromBoth.length > 0) {\n problems.push(\n `new Config field(s) not classified as allowed or denied for in-project config: ` +\n missingFromBoth.join(', ') +\n '. Add each to IN_PROJECT_ALLOWED_KEYS (if safe) or KNOWN_DENIED_IN_PROJECT (with a reason).',\n );\n }\n if (staleDenials.length > 0) {\n problems.push(\n `KNOWN_DENIED_IN_PROJECT references keys that no longer exist on Config: ` +\n staleDenials.join(', ') +\n '. Remove them or restore the field on Config.',\n );\n }\n if (duplicate.length > 0) {\n problems.push(\n `field(s) appear in BOTH IN_PROJECT_ALLOWED_KEYS and KNOWN_DENIED_IN_PROJECT: ` +\n duplicate.join(', ') +\n '. The allow-list wins at runtime; remove from one of the two.',\n );\n }\n if (problems.length > 0) {\n throw new Error(\n `stripUnsafeInProjectFields drift check failed:\\n - ${problems.join('\\n - ')}`,\n );\n }\n}\n\nlet driftChecked = false;\n\n/**\n * Remove forbidden top-level keys from a repo-committed in-project config\n * before it is merged. Returns a new object; the original is not mutated.\n * Emits a warning (and a `config.read` failure-style event) naming the\n * stripped keys so the behavior is observable rather than silent.\n *\n * On first invocation, runs `assertInProjectAllowListComplete()` to verify\n * the allow-list + deny-list together still cover every top-level field of\n * `Config`. The check is idempotent and the result is memoized so the cost\n * is paid at most once per process. The assertion throws on drift, which\n * surfaces the issue at boot in production and at first test invocation in\n * CI — both observable, never silent.\n */\nexport function stripUnsafeInProjectFields(\n inProject: PartialConfig,\n sourcePath: string,\n warn: (msg: string) => void = (msg) => console.warn(msg),\n): PartialConfig {\n if (!driftChecked) {\n assertInProjectAllowListComplete();\n driftChecked = true;\n }\n const stripped: string[] = [];\n const out: PartialConfig = {};\n for (const [k, v] of Object.entries(inProject)) {\n if (IN_PROJECT_ALLOWED_KEYS.has(k)) {\n (out as Record<string, unknown>)[k] = v;\n continue;\n }\n stripped.push(k);\n }\n\n // Nested strip: `tools` is allow-listed (it carries benign limits), but\n // `tools.exec.allow` EXPANDS what the agent may execute — never honor that\n // from an attacker-controllable repo config. Remove it while preserving\n // `tools.exec.deny` (removing commands only narrows, so it is always safe).\n // Clone the affected objects so the caller's input is not mutated.\n const outTools = (out as Record<string, unknown>)['tools'];\n if (outTools && typeof outTools === 'object') {\n const execCfg = (outTools as Record<string, unknown>)['exec'];\n if (execCfg && typeof execCfg === 'object' && 'allow' in (execCfg as Record<string, unknown>)) {\n const clonedExec = { ...(execCfg as Record<string, unknown>) };\n delete clonedExec['allow'];\n (out as Record<string, unknown>)['tools'] = {\n ...(outTools as Record<string, unknown>),\n exec: clonedExec,\n };\n stripped.push('tools.exec.allow');\n }\n }\n\n if (stripped.length > 0) {\n warn(\n JSON.stringify({\n level: 'warn',\n event: 'config.in_project_unsafe_fields_ignored',\n path: sourcePath,\n ignoredKeys: stripped,\n message:\n `Ignored ${stripped.length} field(s) from the repo-committed config ` +\n `\"${sourcePath}\": ${stripped.join(', ')}. ` +\n `Only a small allow-list of benign preferences (model, context, tools limits, ` +\n `features, …) may be set by <project>/.wrongstack/config.json. ` +\n `Everything else must live in your personal ~/.wrongstack/config.json.`,\n timestamp: new Date().toISOString(),\n }),\n );\n }\n return out;\n}\n\n/**\n * Compare two absolute filesystem paths for identity. Normalizes separators and\n * `.`/`..` segments via `path.resolve`, and folds case on win32 (and darwin,\n * whose default APFS/HFS+ volumes are case-insensitive) so the same file\n * reached through differently-cased drive/dir spellings still compares equal —\n * the same Windows path-casing hazard that bit the core token symbols.\n */\nfunction samePath(a: string, b: string): boolean {\n let ra = path.resolve(a);\n let rb = path.resolve(b);\n if (process.platform === 'win32' || process.platform === 'darwin') {\n ra = ra.toLowerCase();\n rb = rb.toLowerCase();\n }\n return ra === rb;\n}\n\n/**\n * Config-layer deep merge — delegates to the shared utility with\n * `arrayMode: 'concat-primitives'` and optional debug logging for\n * non-primitive array replacements.\n */\nfunction deepMerge<T>(base: T, patch: Partial<T>): T {\n const opts: DeepMergeOptions = { arrayMode: 'concat-primitives' };\n if (envBoolOptional(process.env.WRONGSTACK_DEBUG_CONFIG)) {\n opts.onNonPrimitiveArrayReplace = (key, existingLen, patchLen) => {\n console.warn(\n `[config] Non-primitive array for \"${key}\" replaced (global + local config merge). ` +\n `Global entries: ${existingLen}, local entries: ${patchLen}.`,\n );\n };\n }\n return deepMergeCore(base as Record<string, unknown>, patch as Record<string, unknown>, opts) as T;\n}\n\n/**\n * A single config source. Higher priority wins in merges.\n * Sources are applied in priority order (lowest first), so a source\n * with priority=10 overrides one with priority=1.\n */\nexport interface ConfigSource {\n /** Unique name for debugging and error messages. */\n name: string;\n /** Lower numbers merge first, higher numbers override lower. Default: 50. */\n priority?: number | undefined;\n /**\n * Read the raw config patch. Return an empty object if unavailable.\n * Errors are surfaced but do not abort loading — the source is skipped.\n */\n read(): Promise<Partial<Config>>;\n}\n\nexport interface ConfigLoaderOptions {\n paths: WstackPaths;\n strict?: boolean | undefined;\n vault?: SecretVault | undefined;\n /** Extra sources merged after the built-in layers. */\n sources?: ConfigSource[] | undefined;\n events?: EventBus;\n traceId?: string;\n}\n\ninterface MemoizedConfigSource {\n mtimeMs: number | null;\n value: PartialConfig;\n}\n\nexport class DefaultConfigLoader implements ConfigLoader {\n private readonly paths: WstackPaths;\n private readonly strict: boolean;\n private readonly vault: SecretVault | undefined;\n private readonly extraSources: ConfigSource[];\n private readonly events: EventBus | undefined;\n private readonly traceId: string | undefined;\n private readonly jsonCache = new Map<string, MemoizedConfigSource>();\n\n constructor(opts: ConfigLoaderOptions) {\n this.paths = opts.paths;\n this.strict = opts.strict ?? false;\n this.vault = opts.vault;\n this.extraSources = opts.sources ?? [];\n this.events = opts.events;\n this.traceId = opts.traceId;\n }\n\n async load(\n opts: { cliFlags?: Partial<Config> | undefined; cwd?: string | undefined } = {},\n ): Promise<Config> {\n let cfg: PartialConfig = { ...BEHAVIOR_DEFAULTS } as PartialConfig;\n\n // Materialize behavior/settings defaults into the trusted global config\n // before env vars or CLI flags are applied, so first boot creates a real\n // ~/.wrongstack/config.json without persisting ephemeral overrides.\n await this.ensureGlobalDefaults();\n\n // Layer 2, 3 & 3b: global + project-local + in-project config — read in parallel.\n // inProjectConfig (<project>/.wrongstack/config.json) merges AFTER\n // projectLocalConfig so it takes priority (user-intended > auto-cached).\n //\n // When the project root *is* the user's home (e.g. launching from `~`),\n // `<projectRoot>/.wrongstack/config.json` resolves to the very same file as\n // the trusted global config. Reading it again as the untrusted in-project\n // layer would strip `provider`/`apiKey`/… from the user's *own* file and\n // emit a spurious `config.in_project_unsafe_fields_ignored` warning — even\n // though the trusted global layer already merged those fields. Skip the\n // in-project read entirely on collision so trust isn't applied to a file\n // the user fully controls.\n const inProjectCollides =\n samePath(this.paths.inProjectConfig, this.paths.globalConfig) ||\n samePath(this.paths.inProjectConfig, this.paths.projectLocalConfig);\n const [global, local, inProject] = await Promise.all([\n this.readJson(this.paths.globalConfig),\n this.readJson(this.paths.projectLocalConfig),\n inProjectCollides\n ? Promise.resolve({} as PartialConfig)\n : this.readJson(this.paths.inProjectConfig),\n ]);\n cfg = deepMerge(cfg, global);\n cfg = deepMerge(cfg, local);\n // The in-project config is repo-committed and therefore attacker-\n // controllable. Strip credential/endpoint/code-execution fields before\n // merging so a malicious repo cannot redirect the provider endpoint\n // (API-key exfiltration) or auto-run an MCP server / hook (RCE) on launch.\n cfg = deepMerge(cfg, stripUnsafeInProjectFields(inProject, this.paths.inProjectConfig));\n\n // Layer 4: env vars\n for (const [key, fn] of Object.entries(ENV_MAP)) {\n const v = process.env[key];\n if (v) fn(cfg, v);\n }\n\n // Layer 5: extra sources — sorted by priority (lowest first).\n // When priorities tie, sort by name for deterministic order.\n const sorted = [...this.extraSources].sort((a, b) => {\n const pd = (a.priority ?? 50) - (b.priority ?? 50);\n if (pd !== 0) return pd;\n return a.name.localeCompare(b.name);\n });\n for (const src of sorted) {\n try {\n const patch = await src.read();\n if (patch && Object.keys(patch).length > 0) {\n cfg = deepMerge(cfg, patch);\n }\n } catch (err) {\n // Best-effort: skip failing sources so one bad source doesn't block boot.\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'config.source_load_failed',\n source: src.name,\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n }\n }\n\n // Layer 6: CLI flags\n if (opts.cliFlags) {\n cfg = deepMerge(cfg, opts.cliFlags);\n }\n\n // Decrypt apiKey-like fields if a vault is configured.\n if (this.vault) {\n cfg = decryptConfigSecrets(cfg, this.vault);\n }\n\n // Multi-key resolution: when a provider has `apiKeys[]` configured,\n // mirror the active entry into `apiKey` so downstream construction\n // code (provider registry, wire adapters) needs no changes. Honors\n // `activeKey` (by label), else falls back to the first entry. A\n // pre-existing `apiKey` set by env/CLI flags wins so an explicit\n // override still beats the saved list.\n if (cfg.providers) {\n for (const pcfg of Object.values(cfg.providers)) {\n if (!pcfg || typeof pcfg !== 'object') continue;\n const rawKeys = (pcfg as { apiKeys?: unknown | undefined }).apiKeys;\n if (!Array.isArray(rawKeys) || rawKeys.length === 0) continue;\n // Each apiKeys entry came from arbitrary JSON. Filter to entries\n // that actually have a string apiKey + label so a malformed array\n // (null entry, missing field) doesn't crash the .find / chosen.apiKey\n // path below.\n const keys = rawKeys.filter(\n (k): k is { label: string; apiKey: string } =>\n !!k &&\n typeof k === 'object' &&\n typeof (k as { label?: unknown | undefined }).label === 'string' &&\n typeof (k as { apiKey?: unknown | undefined }).apiKey === 'string',\n );\n if (keys.length === 0) continue;\n const existing = (pcfg as { apiKey?: string | undefined }).apiKey;\n if (existing && existing.length > 0) continue;\n const activeLabel = (pcfg as { activeKey?: string | undefined }).activeKey;\n const chosen = activeLabel\n ? (keys.find((k) => k.label === activeLabel) ?? keys[0])\n : keys[0];\n if (chosen?.apiKey) {\n (pcfg as { apiKey?: string | undefined }).apiKey = chosen.apiKey;\n }\n }\n }\n\n this.validateBehavior(cfg);\n if (this.strict) {\n this.validateIdentity(cfg);\n }\n // In strict mode, validateIdentity has confirmed provider/model are set;\n // it's safe to assert the full Config contract. In non-strict mode the\n // caller (e.g. early-boot wizard) accepts a Partial and constructs the\n // provider later, so we deliberately return without the cast.\n return Object.freeze(cfg) as Config;\n }\n\n private async ensureGlobalDefaults(): Promise<void> {\n const fp = this.paths.globalConfig;\n const t0 = Date.now();\n try {\n await withFileLock(fp, async () => {\n let parsed: Record<string, unknown>;\n try {\n const raw = await fs.readFile(fp, 'utf8');\n const result = safeParse<unknown>(raw);\n if (!result.ok || !isPlainRecord(result.value)) {\n // readJson() below owns the user-visible parse warning. Do not\n // overwrite a malformed config while trying to seed defaults.\n return;\n }\n parsed = result.value;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n this.events?.emit('storage.error', {\n sessionId: '~config~',\n store: 'config',\n filePath: fp,\n operation: 'ensure_defaults',\n outcome: 'failure',\n error: storageErrorString(err),\n recoverable: false,\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'config.defaults_read_failed',\n path: fp,\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n return;\n }\n parsed = {};\n }\n\n const { value, changed } = fillMissingDefaults(\n parsed,\n BEHAVIOR_DEFAULTS as Record<string, unknown>,\n );\n if (!changed) return;\n\n await atomicWrite(fp, JSON.stringify(value, null, 2), { mode: 0o600 });\n this.events?.emit('storage.write', {\n sessionId: '~config~',\n store: 'config',\n filePath: fp,\n operation: 'ensure_defaults',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n });\n } catch (err) {\n this.events?.emit('storage.error', {\n sessionId: '~config~',\n store: 'config',\n filePath: fp,\n operation: 'ensure_defaults',\n outcome: 'failure',\n error: storageErrorString(err),\n recoverable: false,\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'config.defaults_write_failed',\n path: fp,\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n }\n }\n\n /**\n * Persist a sync config to ~/.wrongstack/sync.json, with the token encrypted\n * by the vault (if provided). The file is isolated from the main config\n * hierarchy to prevent accidental commits.\n */\n async persistSyncConfig(cfg: SyncConfig): Promise<void> {\n let toWrite = { ...cfg };\n if (this.vault && toWrite.githubToken && !toWrite.githubToken.startsWith('enc:')) {\n // Re-encrypt if plaintext (e.g. came from in-memory configStore update\n // rather than direct /sync enable call). Idempotent for already-encrypted.\n toWrite = { ...toWrite, githubToken: this.vault.encrypt(toWrite.githubToken) };\n }\n const fp = this.paths.syncConfig;\n const t0 = Date.now();\n try {\n await atomicWrite(fp, JSON.stringify(toWrite, null, 2), { mode: 0o600 });\n this.events?.emit('storage.write', {\n sessionId: '~config~',\n store: 'config',\n filePath: fp,\n operation: 'persist_sync',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n } catch (err) {\n this.events?.emit('storage.error', {\n sessionId: '~config~',\n store: 'config',\n filePath: fp,\n operation: 'persist_sync',\n outcome: 'failure',\n error: storageErrorString(err),\n recoverable: false,\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n throw err;\n }\n }\n\n /**\n * Read ~/.wrongstack/sync.json (encrypted GitHub token storage) and decrypt\n * the token if a vault is available. Returns null if the file doesn't exist.\n * This is separate from main config loading because sync.json is intentionally\n * isolated — it should never be part of project-local or env-driven config.\n */\n async loadSyncConfig(): Promise<SyncConfig | null> {\n const fp = this.paths.syncConfig;\n const t0 = Date.now();\n try {\n const raw = await fs.readFile(fp, 'utf8');\n const parsed = safeParse<SyncConfig>(raw);\n if (!parsed.ok || !parsed.value) {\n this.events?.emit('storage.read', {\n sessionId: '~config~',\n store: 'config',\n filePath: fp,\n operation: 'load_sync',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'parse error or empty file',\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return null;\n }\n\n // Decrypt the token if vault is available (field name matches secret pattern)\n if (this.vault) {\n const decrypted = decryptConfigSecrets({ sync: parsed.value } as PartialConfig, this.vault);\n const result = (decrypted as { sync: SyncConfig }).sync ?? null;\n this.events?.emit('storage.read', {\n sessionId: '~config~',\n store: 'config',\n filePath: fp,\n operation: 'load_sync',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return result;\n }\n this.events?.emit('storage.read', {\n sessionId: '~config~',\n store: 'config',\n filePath: fp,\n operation: 'load_sync',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return parsed.value;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return null;\n // Non-ENOENT failures (EACCES, ENOSPC, etc.) — emit storage.read failure, then return null\n this.events?.emit('storage.read', {\n sessionId: '~config~',\n store: 'config',\n filePath: fp,\n operation: 'load_sync',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: storageErrorString(err),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'config.sync_load_failed',\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n return null;\n }\n }\n\n private async readJson(file: string): Promise<PartialConfig> {\n const t0 = Date.now();\n let mtimeMs: number | null = null;\n try {\n const stat = await fs.stat(file);\n mtimeMs = stat.mtimeMs;\n const cached = this.jsonCache.get(file);\n if (cached && cached.mtimeMs === mtimeMs) {\n return structuredClone(cached.value);\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n this.jsonCache.set(file, { mtimeMs: null, value: {} });\n return {};\n }\n this.events?.emit('storage.read', {\n sessionId: '~config~',\n store: 'config',\n filePath: file,\n operation: 'read_json',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: storageErrorString(err),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'config.read_failed',\n path: file,\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n return {};\n }\n\n let raw: string;\n try {\n raw = await fs.readFile(file, 'utf8');\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n this.events?.emit('storage.read', {\n sessionId: '~config~',\n store: 'config',\n filePath: file,\n operation: 'read_json',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: storageErrorString(err),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'config.read_failed',\n path: file,\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n }\n this.jsonCache.set(file, { mtimeMs: null, value: {} });\n return {};\n }\n const parsed = safeParse<PartialConfig>(raw);\n if (!parsed.ok || !parsed.value) {\n this.events?.emit('storage.read', {\n sessionId: '~config~',\n store: 'config',\n filePath: file,\n operation: 'read_json',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'parse error or empty file',\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'config.parse_failed',\n path: file,\n message: 'invalid JSON — falling back to defaults for this layer',\n timestamp: new Date().toISOString(),\n }));\n return {};\n }\n this.jsonCache.set(file, { mtimeMs, value: structuredClone(parsed.value) });\n return parsed.value;\n }\n\n private validateBehavior(cfg: PartialConfig): void {\n /* v8 ignore start -- defensive: config defaults always seed version:1 before validation */\n if (cfg.version === undefined) throw new ConfigError({\n message: 'Config: missing version field',\n code: ERROR_CODES.CONFIG_INVALID,\n context: { field: 'version' },\n });\n /* v8 ignore stop */\n if (cfg.version !== 1) throw new ConfigError({\n message: `Config: unsupported version ${cfg.version}`,\n code: ERROR_CODES.CONFIG_INVALID,\n context: { field: 'version', actual: cfg.version },\n });\n const c = cfg.context;\n if (!c) throw new ConfigError({\n message: 'Config: missing context section',\n code: ERROR_CODES.CONFIG_INVALID,\n context: { field: 'context' },\n });\n // A user-edited config.json can land strings here (\"0.6\") and slip past\n // truthiness checks; the `>=` comparison then coerces silently and the\n // threshold ordering check passes for nonsense values. Validate types\n // explicitly so misconfigs surface here, not as confusing failures deep\n // in the auto-compaction logic.\n const fields: Array<keyof typeof c> = ['warnThreshold', 'softThreshold', 'hardThreshold'];\n for (const f of fields) {\n const v = c[f];\n if (typeof v !== 'number' || !Number.isFinite(v)) {\n throw new ConfigError({\n message: `Config: context.${String(f)} must be a finite number (got ${typeof v})`,\n code: ERROR_CODES.CONFIG_INVALID,\n context: { field: `context.${String(f)}`, actualType: typeof v },\n });\n }\n }\n if (c.warnThreshold >= c.softThreshold || c.softThreshold >= c.hardThreshold) {\n throw new ConfigError({\n message: 'Config: context thresholds must satisfy warn < soft < hard',\n code: ERROR_CODES.CONFIG_INVALID,\n context: { warn: c.warnThreshold, soft: c.softThreshold, hard: c.hardThreshold },\n });\n }\n if (c.mode !== undefined && !isContextWindowModeId(c.mode)) {\n // An unknown mode (typo or value from an older/renamed scheme) should not\n // brick the CLI — unlike the numeric thresholds above there is a safe\n // default. Warn and fall back rather than throwing.\n const known = listContextWindowModes()\n .map((m) => m.id)\n .join(', ');\n console.warn(\n `[config] Ignoring unknown context.mode \"${c.mode}\" (expected one of: ${known}); ` +\n `falling back to \"${DEFAULT_CONTEXT_WINDOW_MODE_ID}\".`,\n );\n c.mode = DEFAULT_CONTEXT_WINDOW_MODE_ID;\n }\n }\n\n private validateIdentity(cfg: PartialConfig): void {\n if (!cfg.provider) {\n throw new ConfigError({\n message: 'Config: no provider configured. Run `wstack init` or set WRONGSTACK_PROVIDER.',\n code: ERROR_CODES.CONFIG_INVALID,\n context: { field: 'provider' },\n });\n }\n if (!cfg.model) {\n throw new ConfigError({\n message: 'Config: no model configured. Run `wstack init` or set WRONGSTACK_MODEL.',\n code: ERROR_CODES.CONFIG_INVALID,\n context: { field: 'model' },\n });\n }\n }\n}\n","/**\n * L2-D: Config version migration framework. Pure functions, decoupled\n * from disk/CLI — caller passes a parsed JSON object and gets back the\n * up-to-date `Config` shape (or a structured error explaining why\n * migration failed).\n *\n * Migrations are registered as `{ from, to, migrate }` triples and run\n * sequentially. Each migration is independently testable. Adding a new\n * version means appending one migration; existing user configs are\n * upgraded in place at load time.\n */\n\nexport interface MigrationContext {\n /**\n * Original on-disk version of the input. Migrations may use this to\n * decide between in-place patches and rewrites.\n */\n fromVersion: number;\n /**\n * Set when the migration writes back to disk. Callers persist the\n * migrated config when this is true so the user doesn't see the same\n * migration banner on every boot.\n */\n shouldPersist: boolean;\n}\n\nexport interface ConfigMigration {\n /** Version of the input this migration accepts. */\n from: number;\n /** Version of the output it produces. */\n to: number;\n /** Pure transform — no I/O. */\n migrate(input: Record<string, unknown>, ctx: MigrationContext): Record<string, unknown>;\n /** Optional human-readable description for migration logs / banners. */\n describe?: string | undefined;\n}\n\nexport interface MigrationResult {\n /** Final config (still typed as `unknown`-keyed — caller validates). */\n config: Record<string, unknown>;\n /** Ordered list of `from→to` versions that ran. */\n applied: string[];\n /** True when at least one migration produced changes worth persisting. */\n shouldPersist: boolean;\n}\n\nexport class ConfigMigrationError extends Error {\n readonly fromVersion: number;\n readonly targetVersion: number;\n readonly missingStep: number | null;\n\n constructor(opts: {\n message: string;\n fromVersion: number;\n targetVersion: number;\n missingStep: number | null;\n }) {\n super(opts.message);\n this.name = 'ConfigMigrationError';\n this.fromVersion = opts.fromVersion;\n this.targetVersion = opts.targetVersion;\n this.missingStep = opts.missingStep;\n }\n}\n\n/**\n * Run registered migrations until the input reaches `targetVersion`.\n *\n * Resolution rules:\n * 1. If `input.version === targetVersion`, no migrations run; `shouldPersist`\n * is false.\n * 2. Otherwise walk the migration chain from `input.version` upward,\n * picking the migration whose `from` matches the current version.\n * 3. Stop when `current.version === targetVersion`.\n * 4. If no migration matches at some point, throw `ConfigMigrationError`\n * with the missing step recorded for diagnostics.\n *\n * Migrations may be downward (e.g. for staged rollouts), but `targetVersion`\n * must be reachable strictly via the registered chain — there's no implicit\n * \"skip\" or transitive resolution.\n */\nexport function runConfigMigrations(\n input: Record<string, unknown>,\n targetVersion: number,\n migrations: readonly ConfigMigration[],\n): MigrationResult {\n const initial = typeof input['version'] === 'number' ? (input['version'] as number) : 1;\n let current: Record<string, unknown> = { ...input };\n let currentVersion = initial;\n const applied: string[] = [];\n let shouldPersist = false;\n\n let guard = 0;\n while (currentVersion !== targetVersion) {\n if (++guard > 100) {\n throw new ConfigMigrationError({\n message: `Config migration looped past 100 steps (from v${initial} toward v${targetVersion})`,\n fromVersion: initial,\n targetVersion,\n missingStep: currentVersion,\n });\n }\n const step = migrations.find((m) => m.from === currentVersion);\n if (!step) {\n throw new ConfigMigrationError({\n message: `No migration registered from config v${currentVersion} (target v${targetVersion}). Update the framework or revert the config file.`,\n fromVersion: initial,\n targetVersion,\n missingStep: currentVersion,\n });\n }\n const ctx: MigrationContext = { fromVersion: currentVersion, shouldPersist: false };\n const next = step.migrate(current, ctx);\n // Ensure the migration set the new version. Be tolerant: if it didn't,\n // patch it in so the chain doesn't infinite-loop on author oversight.\n if (typeof next['version'] !== 'number' || next['version'] !== step.to) {\n next['version'] = step.to;\n }\n current = next;\n currentVersion = step.to;\n applied.push(`v${step.from}→v${step.to}`);\n shouldPersist = shouldPersist || ctx.shouldPersist || step.from < step.to;\n }\n return { config: current, applied, shouldPersist };\n}\n\n/**\n * Default empty migration registry. Real migrations are appended as new\n * Config versions are introduced. Example (when v2 lands):\n *\n * export const CONFIG_MIGRATIONS: readonly ConfigMigration[] = [\n * {\n * from: 1, to: 2, describe: 'rename `apiKey` → `auth.apiKey`',\n * migrate(cfg) {\n * const apiKey = cfg.apiKey;\n * delete cfg.apiKey;\n * return { ...cfg, auth: { ...(cfg.auth ?? {}), apiKey } };\n * },\n * },\n * ];\n */\nexport const DEFAULT_CONFIG_MIGRATIONS: readonly ConfigMigration[] = [];\n","import * as fsp from 'node:fs/promises';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { SessionStore } from '../types/session.js';\nimport { ensureDir } from '../utils/atomic-write.js';\n\n/**\n * Per-project lockfile used for crash detection. The CLI writes one of\n * these alongside the session JSONLs (`<projectSessions>/active.json`)\n * when an interactive run starts, and deletes it on clean exit. If we\n * find one on the next launch whose owning PID is dead (or whose host\n * doesn't match), we know the previous run was killed mid-flight and\n * the session it was writing to is a recovery candidate.\n *\n * The lockfile is intentionally per-project (already isolated by\n * `wpaths.projectSessions`), so two TUIs in two different repos do not\n * fight each other.\n */\nexport interface RecoveryLockOptions {\n /** Directory the lockfile lives in. Usually `wpaths.projectSessions`. */\n dir: string;\n /** This process's PID. Default: `process.pid`. */\n pid?: number | undefined;\n /** Hostname recorded for the lock. Default: `os.hostname()`. */\n hostname?: string | undefined;\n /** Locks older than this are considered orphaned (disk wiped, etc.). Default 24h. */\n maxAgeMs?: number | undefined;\n /** Used to check whether the abandoned session was actually closed cleanly. */\n sessionStore?: SessionStore | undefined;\n /**\n * Override the PID-liveness probe. Default: `process.kill(pid, 0)` —\n * succeeds (or throws EPERM) when the PID is alive, throws ESRCH when\n * it is gone. Tests inject a deterministic stub.\n */\n isPidAlive?: (((pid: number) => boolean)) | undefined;\n}\n\nexport interface AbandonedSession {\n sessionId: string;\n pid: number;\n startedAt: string;\n /** Lockfile age in ms at the time of the check. */\n ageMs: number;\n /** Number of messages already on disk for this session. */\n messageCount: number;\n}\n\ninterface LockFile {\n v: 1;\n sessionId: string;\n pid: number;\n hostname: string;\n startedAt: string;\n}\n\nconst LOCK_FILE = 'active.json';\nconst DEFAULT_MAX_AGE_MS = 24 * 60 * 60 * 1000;\n\nexport class RecoveryLock {\n private readonly file: string;\n private readonly pid: number;\n private readonly hostname: string;\n private readonly maxAgeMs: number;\n private readonly sessionStore?: SessionStore | undefined;\n private readonly probe: (pid: number) => boolean;\n\n constructor(opts: RecoveryLockOptions) {\n this.file = path.join(opts.dir, LOCK_FILE);\n this.pid = opts.pid ?? process.pid;\n this.hostname = opts.hostname ?? os.hostname();\n this.maxAgeMs = opts.maxAgeMs ?? DEFAULT_MAX_AGE_MS;\n this.sessionStore = opts.sessionStore;\n this.probe = opts.isPidAlive ?? defaultIsPidAlive;\n }\n\n /**\n * Examine the lockfile and decide whether it represents an abandoned\n * session. Returns `null` if the file is missing, points to a live\n * instance, references a clean-closed session, is too old, or is\n * malformed. Otherwise returns enough detail to prompt the user.\n *\n * Important: this is a read-only check. We never delete an active\n * lock from here — if another wstack instance is alive, the caller\n * should bail or run with a fresh session instead.\n */\n async checkAbandoned(): Promise<AbandonedSession | null> {\n const lock = await this.readLock();\n if (!lock) return null;\n\n const ageMs = Date.now() - new Date(lock.startedAt).getTime();\n if (Number.isNaN(ageMs) || ageMs < 0) {\n // Clock skew or corrupted timestamp — treat as orphan.\n return null;\n }\n if (ageMs > this.maxAgeMs) return null;\n\n // PID liveness only meaningful on the same host. Different host\n // means we can't probe — assume abandoned (the other machine's\n // wstack can't be holding *our* sessions dir unless it was\n // shared via network mount, in which case the user is on their\n // own).\n if (lock.hostname === this.hostname && this.probe(lock.pid)) {\n // Another wstack on this box is actively writing here.\n return null;\n }\n\n let messageCount = 0;\n if (this.sessionStore) {\n try {\n const data = await this.sessionStore.load(lock.sessionId);\n // Closed means the LAST session_end is not followed by further\n // conversation activity. Legacy /save wrote mid-stream session_end\n // markers — `some()` would treat a session that crashed AFTER such a\n // marker as cleanly closed and silently skip recovery.\n const lastEnd = data.events.findLastIndex((e) => e.type === 'session_end');\n const closed =\n lastEnd >= 0 &&\n !data.events\n .slice(lastEnd + 1)\n .some(\n (e) =>\n e.type === 'user_input' ||\n e.type === 'llm_response' ||\n e.type === 'in_flight_start',\n );\n if (closed) return null;\n messageCount = data.messages.length;\n } catch {\n // Lock points to a session that doesn't exist on disk (deleted\n // out from under us). Nothing to recover.\n return null;\n }\n }\n\n return {\n sessionId: lock.sessionId,\n pid: lock.pid,\n startedAt: lock.startedAt,\n ageMs,\n messageCount,\n };\n }\n\n /**\n * Claim the lock for the given session. Uses exclusive-create (`O_EXCL`)\n * to detect whether another process acquired the lock between our\n * `checkAbandoned()` call and now. If the file already exists, it means\n * another process won the race and we throw instead of silently\n * overwriting their recovery record.\n *\n * The caller MUST have already called `checkAbandoned()` and handled its\n * null return before calling this.\n */\n async write(sessionId: string): Promise<void> {\n await ensureDir(path.dirname(this.file));\n const lock: LockFile = {\n v: 1,\n sessionId,\n pid: this.pid,\n hostname: this.hostname,\n startedAt: new Date().toISOString(),\n };\n // O_EXCL: atomic create — fails with EEXIST if another process wrote\n // the file between our checkAbandoned() and this write. This prevents\n // two processes that scanned the same stale lock from both believing\n // they hold it. The atomicWrite approach (temp+rename) would silently\n // replace on POSIX, hiding the race.\n try {\n await fsp.writeFile(this.file, JSON.stringify(lock), { flag: 'wx', mode: 0o600 });\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'EEXIST') {\n throw new Error(`Recovery lock already held by another process`);\n }\n /* v8 ignore next -- defensive: an unexpected (non-EEXIST) write failure is rethrown */\n throw err;\n }\n }\n\n /**\n * Release the lock. Idempotent — silently succeeds if the file is\n * already gone (e.g. someone else cleared it, or the directory was\n * wiped).\n */\n async clear(): Promise<void> {\n try {\n await fsp.unlink(this.file);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') return;\n /* v8 ignore next -- defensive: an unexpected (non-ENOENT) unlink failure is rethrown */\n throw err;\n }\n }\n\n private async readLock(): Promise<LockFile | null> {\n let raw: string;\n try {\n raw = await fsp.readFile(this.file, 'utf8');\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') return null;\n return null;\n }\n try {\n const parsed = JSON.parse(raw) as unknown;\n if (!isLockFile(parsed)) return null;\n return parsed;\n } catch {\n return null;\n }\n }\n}\n\nfunction isLockFile(v: unknown): v is LockFile {\n if (typeof v !== 'object' || v === null) return false;\n const o = v as Record<string, unknown>;\n return (\n o['v'] === 1 &&\n typeof o['sessionId'] === 'string' &&\n typeof o['pid'] === 'number' &&\n typeof o['hostname'] === 'string' &&\n typeof o['startedAt'] === 'string'\n );\n}\n\n/**\n * Probe whether a process is alive without sending it a real signal.\n *\n * Unix: `process.kill(pid, 0)` succeeds for our own processes, throws\n * EPERM for others (still alive, just not ours), and throws ESRCH\n * when the PID is gone.\n * Windows (Node 22+): same call returns true if the process exists,\n * throws otherwise.\n */\nfunction defaultIsPidAlive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid <= 0) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n /* v8 ignore next -- platform/permission-specific: EPERM means alive but owned by another user */\n if (code === 'EPERM') return true; // alive, but owned by someone else\n return false;\n }\n}\n","import * as fs from 'node:fs/promises';\r\nimport * as path from 'node:path';\r\nimport { expectDefined } from '../utils/expect-defined.js';\r\nimport type { ContentBlock } from '../types/blocks.js';\r\nimport type {\r\n DefaultSessionReaderOptions,\r\n SessionExportOptions,\r\n SessionQuery,\r\n SessionReader,\r\n SessionSearchHit,\r\n SessionSearchQuery,\r\n SessionSummaryLite,\r\n} from '../types/session-reader.js';\r\nimport { compileUserRegex } from '../utils/regex-guard.js';\r\nimport type { SessionData, SessionEvent, SessionMetadata, SessionStore } from '../types/session.js';\r\n\r\n/**\r\n * L2-A: read-only view over a `SessionStore` with query, replay, search,\r\n * and export helpers. Implemented on top of the public `SessionStore`\r\n * surface so any concrete store can be inspected without re-implementation.\r\n */\r\nexport class DefaultSessionReader implements SessionReader {\r\n private readonly store: SessionStore;\r\n private readonly eventCache = new Map<string, SessionData>();\r\n private readonly eventCacheMtimes = new Map<string, number>();\r\n private static readonly EVENT_CACHE_MAX_ENTRIES = 32;\r\n\r\n constructor(opts: DefaultSessionReaderOptions) {\r\n this.store = opts.store;\r\n }\r\n\r\n private async loadCachedSessionData(sessionId: string): Promise<SessionData> {\r\n const storeWithPath = this.store as SessionStore & {\r\n dir?: string | undefined;\r\n clearLoadCache?: ((sessionId?: string | undefined) => void) | undefined;\r\n };\r\n const rootDir = storeWithPath.dir;\r\n if (!rootDir) {\r\n return await this.store.load(sessionId);\r\n }\r\n const sessionPath = path.join(rootDir, `${sessionId}.jsonl`);\r\n let mtimeMs: number | null = null;\r\n try {\r\n const stat = await fs.stat(sessionPath);\r\n mtimeMs = stat.mtimeMs;\r\n } catch {\r\n this.eventCache.delete(sessionId);\r\n this.eventCacheMtimes.delete(sessionId);\r\n return await this.store.load(sessionId);\r\n }\r\n\r\n const cachedMtime = this.eventCacheMtimes.get(sessionId);\r\n const cachedData = this.eventCache.get(sessionId);\r\n if (cachedData && cachedMtime === mtimeMs) {\r\n this.eventCache.delete(sessionId);\r\n this.eventCacheMtimes.delete(sessionId);\r\n this.eventCache.set(sessionId, cachedData);\r\n this.eventCacheMtimes.set(sessionId, mtimeMs);\r\n return cachedData;\r\n }\r\n\r\n const data = await this.store.load(sessionId);\r\n this.eventCache.delete(sessionId);\r\n this.eventCacheMtimes.delete(sessionId);\r\n this.eventCache.set(sessionId, data);\r\n this.eventCacheMtimes.set(sessionId, mtimeMs);\r\n while (this.eventCache.size > DefaultSessionReader.EVENT_CACHE_MAX_ENTRIES) {\r\n const oldest = this.eventCache.keys().next().value;\r\n if (oldest === undefined) break;\r\n this.eventCache.delete(oldest);\r\n this.eventCacheMtimes.delete(oldest);\r\n }\r\n\r\n if (data.metadata.endedAt) {\r\n storeWithPath.clearLoadCache?.(sessionId);\r\n }\r\n\r\n return data;\r\n }\r\n\r\n async query(q: SessionQuery = {}): Promise<SessionSummaryLite[]> {\r\n // Prefer the store's filtered list when available — it pushes the\r\n // filter into the cached index instead of fetching 1000 + linear scan.\r\n const storeWithFilter = this.store as SessionStore & {\r\n listFiltered?: ((criteria: {\r\n since?: string | undefined;\r\n until?: string | undefined;\r\n provider?: string | undefined;\r\n model?: string | undefined;\r\n minTokens?: number | undefined;\r\n titleContains?: string | undefined;\r\n limit?: number | undefined;\r\n }) => Promise<import('../types/session.js').SessionSummary[]>) | undefined;\r\n };\r\n let raw: import('../types/session.js').SessionSummary[];\r\n if (typeof storeWithFilter.listFiltered === 'function') {\r\n raw = await storeWithFilter.listFiltered({\r\n since: q.since,\r\n until: q.until,\r\n provider: q.provider,\r\n model: q.model,\r\n minTokens: q.minTokens,\r\n titleContains: q.titleContains,\r\n limit: q.limit,\r\n });\r\n } else {\r\n const fetched = await this.store.list(q.limit ? Math.max(q.limit, 100) : 1000);\r\n const titleNeedle = q.titleContains?.toLowerCase();\r\n raw = fetched.filter((s) => {\r\n if (q.since && s.startedAt < q.since) return false;\r\n if (q.until && s.startedAt > q.until) return false;\r\n if (q.provider && s.provider !== q.provider) return false;\r\n if (q.model && s.model !== q.model) return false;\r\n if (q.minTokens !== undefined && s.tokenTotal < q.minTokens) return false;\r\n if (titleNeedle && !s.title.toLowerCase().includes(titleNeedle)) return false;\r\n return true;\r\n });\r\n }\r\n const out: SessionSummaryLite[] = raw.map((s) => ({\r\n id: s.id,\r\n title: s.title,\r\n startedAt: s.startedAt,\r\n provider: s.provider,\r\n model: s.model,\r\n tokenTotal: s.tokenTotal,\r\n }));\r\n return q.limit ? out.slice(0, q.limit) : out;\r\n }\r\n\r\n async *replay(sessionId: string): AsyncIterable<SessionEvent> {\r\n const data = await this.loadCachedSessionData(sessionId);\r\n for (const e of data.events) yield e;\r\n }\r\n\r\n async search(q: SessionSearchQuery, sessionId?: string | undefined, sessionQuery?: SessionQuery): Promise<SessionSearchHit[]> {\r\n const limit = q.limit ?? 100;\r\n const matcher = buildMatcher(q);\r\n const allowedTypes = q.types ? new Set(q.types) : null;\r\n\r\n // Filter sessions BEFORE scanning events — avoids touching the JSONL\r\n // for sessions that don't match the time/provider/model criteria.\r\n let ids: string[];\r\n if (sessionId) {\r\n ids = [sessionId];\r\n } else {\r\n // Prefer the store's filtered list when available — avoids fetching\r\n // 1000 sessions and linear-filtering in-process.\r\n const storeWithFilter = this.store as SessionStore & {\r\n listFiltered?: ((criteria: {\r\n since?: string | undefined;\r\n until?: string | undefined;\r\n provider?: string | undefined;\r\n model?: string | undefined;\r\n minTokens?: number | undefined;\r\n titleContains?: string | undefined;\r\n limit?: number | undefined;\r\n }) => Promise<import('../types/session.js').SessionSummary[]>) | undefined;\r\n };\r\n let sessions: import('../types/session.js').SessionSummary[];\r\n if (typeof storeWithFilter.listFiltered === 'function') {\r\n sessions = await storeWithFilter.listFiltered({\r\n since: sessionQuery?.since,\r\n until: sessionQuery?.until,\r\n provider: sessionQuery?.provider,\r\n model: sessionQuery?.model,\r\n minTokens: sessionQuery?.minTokens,\r\n titleContains: sessionQuery?.titleContains,\r\n limit: 1000,\r\n });\r\n } else {\r\n sessions = await this.store.list(1000);\r\n const titleNeedle = sessionQuery?.titleContains?.toLowerCase();\r\n sessions = sessions.filter((s) => {\r\n if (sessionQuery?.since && s.startedAt < sessionQuery.since) return false;\r\n if (sessionQuery?.until && s.startedAt > sessionQuery.until) return false;\r\n if (sessionQuery?.provider && s.provider !== sessionQuery.provider) return false;\r\n if (sessionQuery?.model && s.model !== sessionQuery.model) return false;\r\n if (sessionQuery?.minTokens !== undefined && s.tokenTotal < sessionQuery.minTokens) return false;\r\n if (titleNeedle && !s.title.toLowerCase().includes(titleNeedle)) return false;\r\n return true;\r\n });\r\n }\r\n ids = sessions.map((s) => s.id);\r\n }\r\n\r\n const hits: SessionSearchHit[] = [];\r\n\r\n // Fast path: when the underlying store supports streaming search,\r\n // walk each session's JSONL line-by-line and bail out the moment we\r\n // hit `limit`. This avoids reading + parsing the entire file (which\r\n // `load()` does) and never reuses `_loadCache`, so concurrent\r\n // analytics queries don't churn the writer-side cache.\r\n const streaming = this.store.searchEvents?.bind(this.store);\r\n if (streaming) {\r\n for (const id of ids) {\r\n const matched = await streaming(\r\n id,\r\n (ev) => {\r\n if (allowedTypes && !allowedTypes.has(ev.type)) return false;\r\n const text = eventText(ev);\r\n if (text === null) return false;\r\n return matcher(text) !== null;\r\n },\r\n { limit: limit - hits.length },\r\n );\r\n for (const m of matched) {\r\n const text = expectDefined(eventText(m.event));\r\n const hit = expectDefined(matcher(text));\r\n hits.push({\r\n sessionId: id,\r\n eventIndex: m.eventIndex,\r\n ts: m.ts,\r\n type: m.event.type,\r\n snippet: snippetOf(text, hit.start, hit.end),\r\n });\r\n if (hits.length >= limit) return hits;\r\n }\r\n }\r\n return hits;\r\n }\r\n\r\n // Fallback: stores that don't implement streaming. Loads the full\r\n // event stream per session — necessary for in-memory or non-file\r\n // stores that don't expose a streaming surface.\r\n for (const id of ids) {\r\n let data;\r\n try {\r\n data = await this.loadCachedSessionData(id);\r\n } catch {\r\n continue;\r\n }\r\n for (let i = 0; i < data.events.length; i++) {\r\n const ev = expectDefined(data.events[i]);\r\n if (allowedTypes && !allowedTypes.has(ev.type)) continue;\r\n const text = eventText(ev);\r\n if (text === null) continue;\r\n const hit = matcher(text);\r\n if (!hit) continue;\r\n hits.push({\r\n sessionId: id,\r\n eventIndex: i,\r\n ts: ev.ts,\r\n type: ev.type,\r\n snippet: snippetOf(text, hit.start, hit.end),\r\n });\r\n if (hits.length >= limit) return hits;\r\n }\r\n }\r\n return hits;\r\n }\r\n\r\n async export(sessionId: string, opts: SessionExportOptions): Promise<string> {\r\n const data = await this.loadCachedSessionData(sessionId);\r\n const includeTools = opts.includeTools ?? true;\r\n const includeDiagnostics = opts.includeDiagnostics ?? true;\r\n\r\n const filtered = data.events.filter((e) => {\r\n if (\r\n !includeTools &&\r\n (e.type === 'tool_use' ||\r\n e.type === 'tool_result' ||\r\n e.type === 'tool_call_start' ||\r\n e.type === 'tool_call_end')\r\n ) {\r\n return false;\r\n }\r\n if (\r\n !includeDiagnostics &&\r\n (e.type === 'error' || e.type === 'compaction' || e.type === 'message_truncated')\r\n ) {\r\n return false;\r\n }\r\n return true;\r\n });\r\n\r\n if (opts.format === 'json') {\r\n return JSON.stringify({ metadata: data.metadata, events: filtered }, null, 2);\r\n }\r\n if (opts.format === 'text') {\r\n return renderPlainText(data.metadata, filtered);\r\n }\r\n return renderMarkdown(data.metadata, filtered);\r\n }\r\n\r\n async metadata(sessionId: string): Promise<SessionMetadata> {\r\n const data = await this.loadCachedSessionData(sessionId);\r\n return data.metadata;\r\n }\r\n}\r\n\r\nfunction buildMatcher(\r\n q: SessionSearchQuery,\r\n): (text: string) => { start: number; end: number } | null {\r\n const ci = q.caseInsensitive ?? true;\r\n if (q.regex) {\r\n const flags = ci ? 'i' : '';\r\n const compiled = compileUserRegex(q.query, flags);\r\n if (!compiled.ok) {\r\n throw new Error(`Invalid search regex \"${q.query}\": ${compiled.reason}`);\r\n }\r\n const re = compiled.regex;\r\n return (text) => {\r\n const m = re.exec(text);\r\n return m ? { start: m.index, end: m.index + m[0].length } : null;\r\n };\r\n }\r\n const needle = ci ? q.query.toLowerCase() : q.query;\r\n return (text) => {\r\n const hay = ci ? text.toLowerCase() : text;\r\n const idx = hay.indexOf(needle);\r\n return idx === -1 ? null : { start: idx, end: idx + needle.length };\r\n };\r\n}\r\n\r\nfunction eventText(e: SessionEvent): string | null {\r\n switch (e.type) {\r\n case 'user_input':\r\n return contentToString(e.content);\r\n case 'llm_response':\r\n return contentToString(e.content);\r\n case 'tool_use':\r\n return `${e.name} ${JSON.stringify(e.input)}`;\r\n case 'tool_result':\r\n return typeof e.content === 'string' ? e.content : JSON.stringify(e.content);\r\n case 'error':\r\n return `${e.phase}: ${e.message}`;\r\n case 'session_start':\r\n case 'session_resumed':\r\n return `${e.model}/${e.provider}`;\r\n case 'task_created':\r\n case 'task_completed':\r\n return e.title;\r\n case 'task_failed':\r\n return `${e.title}: ${e.error}`;\r\n case 'skill_activated':\r\n case 'skill_deactivated':\r\n return e.skillName;\r\n default:\r\n return null;\r\n }\r\n}\r\n\r\nfunction contentToString(content: string | ContentBlock[]): string {\r\n if (typeof content === 'string') return content;\r\n return content\r\n .map((b) => {\r\n switch (b.type) {\r\n case 'text':\r\n return b.text;\r\n case 'tool_use':\r\n return `[tool_use:${b.name} ${JSON.stringify(b.input)}]`;\r\n case 'tool_result':\r\n return typeof b.content === 'string' ? b.content : JSON.stringify(b.content);\r\n default:\r\n return '';\r\n }\r\n })\r\n .join('\\n');\r\n}\r\n\r\nconst SNIPPET_RADIUS = 60;\r\n\r\nfunction snippetOf(text: string, start: number, end: number): string {\r\n const from = Math.max(0, start - SNIPPET_RADIUS);\r\n const to = Math.min(text.length, end + SNIPPET_RADIUS);\r\n const prefix = from > 0 ? '…' : '';\r\n const suffix = to < text.length ? '…' : '';\r\n return prefix + text.slice(from, to).replace(/\\s+/g, ' ').trim() + suffix;\r\n}\r\n\r\nfunction renderMarkdown(meta: SessionMetadata, events: SessionEvent[]): string {\r\n const lines: string[] = [];\r\n lines.push(`# Session ${meta.id}`);\r\n lines.push('');\r\n if (meta.model || meta.provider) {\r\n lines.push(`- **Model:** ${meta.provider ?? '?'}/${meta.model ?? '?'}`);\r\n }\r\n lines.push(`- **Started:** ${meta.startedAt}`);\r\n if (meta.endedAt) lines.push(`- **Ended:** ${meta.endedAt}`);\r\n lines.push('');\r\n lines.push('---');\r\n lines.push('');\r\n for (const e of events) {\r\n switch (e.type) {\r\n case 'user_input': {\r\n lines.push(`## User — ${e.ts}`);\r\n lines.push('');\r\n lines.push(contentToString(e.content));\r\n lines.push('');\r\n break;\r\n }\r\n case 'llm_response': {\r\n lines.push(`## Assistant — ${e.ts}`);\r\n lines.push('');\r\n lines.push(contentToString(e.content));\r\n if (e.stopReason && e.stopReason !== 'end_turn') {\r\n lines.push('');\r\n lines.push(`*stop: ${e.stopReason}*`);\r\n }\r\n lines.push('');\r\n break;\r\n }\r\n case 'tool_use': {\r\n lines.push(`### Tool call: \\`${e.name}\\``);\r\n lines.push('');\r\n lines.push('```json');\r\n lines.push(JSON.stringify(e.input, null, 2));\r\n lines.push('```');\r\n lines.push('');\r\n break;\r\n }\r\n case 'tool_result': {\r\n const body = typeof e.content === 'string' ? e.content : JSON.stringify(e.content, null, 2);\r\n lines.push(`### Tool result${e.isError ? ' (error)' : ''}`);\r\n lines.push('');\r\n lines.push('```');\r\n lines.push(body);\r\n lines.push('```');\r\n lines.push('');\r\n break;\r\n }\r\n case 'error': {\r\n lines.push(`> **Error** (${e.phase}): ${e.message}`);\r\n lines.push('');\r\n break;\r\n }\r\n case 'compaction': {\r\n lines.push(`> **Compaction**: ${e.before} → ${e.after} tokens`);\r\n lines.push('');\r\n break;\r\n }\r\n default:\r\n break;\r\n }\r\n }\r\n return lines.join('\\n');\r\n}\r\n\r\nfunction renderPlainText(meta: SessionMetadata, events: SessionEvent[]): string {\r\n const lines: string[] = [];\r\n lines.push(\r\n `Session ${meta.id} — ${meta.provider ?? '?'}/${meta.model ?? '?'} — started ${meta.startedAt}`,\r\n );\r\n lines.push(''.padEnd(72, '-'));\r\n for (const e of events) {\r\n switch (e.type) {\r\n case 'user_input':\r\n lines.push(`[${e.ts}] USER`);\r\n lines.push(contentToString(e.content));\r\n lines.push('');\r\n break;\r\n case 'llm_response':\r\n lines.push(`[${e.ts}] ASSISTANT`);\r\n lines.push(contentToString(e.content));\r\n lines.push('');\r\n break;\r\n case 'tool_use':\r\n lines.push(`[${e.ts}] TOOL_USE ${e.name} ${JSON.stringify(e.input)}`);\r\n break;\r\n case 'tool_result':\r\n lines.push(\r\n `[${e.ts}] TOOL_RESULT${e.isError ? ' (error)' : ''} ${\r\n typeof e.content === 'string' ? e.content : JSON.stringify(e.content)\r\n }`,\r\n );\r\n break;\r\n case 'error':\r\n lines.push(`[${e.ts}] ERROR (${e.phase}): ${e.message}`);\r\n break;\r\n default:\r\n break;\r\n }\r\n }\r\n return lines.join('\\n');\r\n}\r\n","import * as path from 'node:path';\nimport { ERROR_CODES, FsError } from '../types/errors.js';\n\n/**\n * Resolve `<dir>/<sessionId><suffix>` for per-session sidecar files\n * (annotations, audit chain, replay log, the session JSONL itself).\n *\n * Modern session ids are date-sharded (\"2026-06-11/12-30-45Z_model_ab12\"),\n * so a forward slash is a legitimate shard separator — NOT traversal.\n * Escape attempts are blocked two ways: an explicit ban on `..` and\n * backslashes, plus a resolved-path containment check that rejects any\n * id whose resolved target leaves `dir`. Character bans alone are how\n * several stores ended up throwing on every modern session id.\n */\nexport function sessionScopedPath(dir: string, sessionId: string, suffix: string): string {\n if (!sessionId || sessionId.includes('\\\\') || sessionId.includes('..')) {\n throw invalid(sessionId);\n }\n const resolved = path.resolve(dir, `${sessionId}${suffix}`);\n const rel = path.relative(path.resolve(dir), resolved);\n if (rel.startsWith('..') || path.isAbsolute(rel)) {\n throw invalid(sessionId);\n }\n return resolved;\n}\n\nfunction invalid(sessionId: string): FsError {\n return new FsError({\n message: `Invalid sessionId: ${sessionId}`,\n code: ERROR_CODES.FS_DELETE_FAILED,\n path: sessionId,\n context: { reason: 'path_traversal' },\n });\n}\n","import { expectDefined } from '../utils/expect-defined.js';\nimport { toErrorMessage } from '../utils/error.js';\nimport { randomUUID } from 'node:crypto';\nimport * as fs from 'node:fs/promises';\nimport { sessionScopedPath } from '../utils/session-scoped-path.js';\nimport { atomicWrite, withFileLock } from '../utils/atomic-write.js';\nimport { WrongStackError, ERROR_CODES } from '../types/errors.js';\nimport type { EventBus } from '../kernel/events.js';\n/**\n * L2-B: AnnotationsStore — sidecar storage for collaboration annotations\n * (Phase 2 of idea #13 from IDEAS.md).\n *\n * Why a sidecar file, not the session JSONL?\n *\n * The session log is an event-sourced append-only journal\n * (`packages/core/src/types/session.ts` invariant: events are\n * append-only, with `truncateToCheckpoint` only as an explicit\n * rewind). Mixing in human-typed annotations would break that\n * invariant — the user's note about \"this rm looks dangerous\"\n * is not part of the agent's event history; it is meta-commentary\n * on the history.\n *\n * So we keep annotations in a sibling file: one JSON document per\n * session, at `<sessionDir>/<sessionId>.annotations.json`. The\n * shape is a simple versioned array, written atomically.\n *\n * Concurrency model:\n *\n * The store uses a per-session Promise chain to serialize writes.\n * Multiple annotators adding notes at the same time will queue,\n * not race. The atomic write itself is the second line of\n * defense (in case the chain is bypassed — e.g. two processes\n * pointing at the same dir).\n */\n\n/** Wire/storage shape for one annotation. */\nexport interface Annotation {\n /** Stable id (UUIDv4-ish). Referenced by resolve/delete. */\n id: string;\n /** Session this annotation belongs to. */\n sessionId: string;\n /** Index into the session event log the annotation refers to. */\n atEventIndex: number;\n /** Participant id of the annotator (matches WSCollabParticipantJoined.participantId). */\n authorId: string;\n /** Human-readable role label snapshot for display (e.g. \"annotator\"). */\n authorRole: 'annotator';\n /** The note itself. Trimmed, capped at `MAX_TEXT_LENGTH` on add. */\n text: string;\n /** ISO timestamp of creation. */\n createdAt: string;\n /** Resolved state. Annotations start unresolved. */\n resolved: boolean;\n /** ISO timestamp when resolved (if resolved). */\n resolvedAt?: string | undefined;\n /** Participant id of the resolver (if resolved). */\n resolvedBy?: string | undefined;\n}\n\ninterface AnnotationsFile {\n /** Bumped when the on-disk shape changes. v1 = initial release. */\n version: 1;\n annotations: Annotation[];\n}\n\n/** Bumped when the on-disk shape changes. Bump + migration on change. */\nconst FILE_VERSION = 1;\n/** Hard cap to keep a runaway annotator from writing megabytes. */\nconst MAX_TEXT_LENGTH = 2000;\n/** Hard cap on total annotations per session (oldest are evicted beyond this). */\nconst MAX_ANNOTATIONS = 1000;\n\nexport interface AnnotationsStoreOptions {\n /** Directory where `<sessionId>.annotations.json` files live. */\n dir: string;\n events?: EventBus;\n traceId?: string;\n}\n\nexport class AnnotationsStore {\n private readonly dir: string;\n private readonly events: EventBus | undefined;\n private readonly traceId: string | undefined;\n /** Per-session write queue. Created lazily on first add. */\n private readonly writeChains = new Map<string, Promise<void>>();\n\n constructor(opts: AnnotationsStoreOptions) {\n this.dir = opts.dir;\n this.events = opts.events;\n this.traceId = opts.traceId;\n }\n\n // ── Reads ──────────────────────────────────────────────────────────────\n\n /**\n * Return all annotations for `sessionId` in insertion order\n * (oldest first). Returns an empty array when no file exists\n * yet (the normal case for a fresh session) and also degrades\n * gracefully to `[]` on a read error (permissions, corruption) —\n * the failure is still surfaced via a `storage.read` event so it\n * never silently hides I/O problems from observers.\n */\n async list(sessionId: string): Promise<Annotation[]> {\n const t0 = Date.now();\n const fp = this.filePath(sessionId);\n try {\n const file = await this.readFile(sessionId);\n const durationMs = Date.now() - t0;\n this.events?.emit('storage.read', {\n sessionId,\n store: 'annotations',\n filePath: fp,\n operation: 'list',\n outcome: 'success',\n durationMs,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return file ? file.annotations : [];\n } catch (err) {\n this.events?.emit('storage.read', {\n sessionId,\n store: 'annotations',\n filePath: fp,\n operation: 'list',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: toErrorMessage(err),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return [];\n }\n }\n\n /**\n * Convenience: only unresolved annotations, newest first — the\n * common UI rendering for \"what still needs attention?\".\n */\n async listOpen(sessionId: string): Promise<Annotation[]> {\n const all = await this.list(sessionId);\n return all.filter((a) => !a.resolved).reverse();\n }\n\n // ── Writes ─────────────────────────────────────────────────────────────\n\n /**\n * Add a new annotation. Returns the persisted record (with id\n * and timestamps filled in). Throws when `text` is empty or\n * exceeds `MAX_TEXT_LENGTH`.\n */\n async add(input: {\n sessionId: string;\n atEventIndex: number;\n authorId: string;\n text: string;\n }): Promise<Annotation> {\n const text = input.text.trim();\n if (text.length === 0) {\n throw new WrongStackError({\n message: 'Annotation text must be non-empty',\n code: ERROR_CODES.VALIDATION_ERROR,\n subsystem: 'general',\n context: { field: 'text', sessionId: input.sessionId },\n });\n }\n if (text.length > MAX_TEXT_LENGTH) {\n throw new WrongStackError({\n message: `Annotation text exceeds ${MAX_TEXT_LENGTH} chars (got ${text.length})`,\n code: ERROR_CODES.VALIDATION_ERROR,\n subsystem: 'general',\n context: { field: 'text', maxLength: MAX_TEXT_LENGTH, actualLength: text.length },\n });\n }\n if (!Number.isInteger(input.atEventIndex) || input.atEventIndex < 0) {\n throw new WrongStackError({\n message: 'atEventIndex must be a non-negative integer',\n code: ERROR_CODES.VALIDATION_ERROR,\n subsystem: 'general',\n context: { field: 'atEventIndex', value: input.atEventIndex },\n });\n }\n const annotation: Annotation = {\n id: randomUUID(),\n sessionId: input.sessionId,\n atEventIndex: input.atEventIndex,\n authorId: input.authorId,\n authorRole: 'annotator',\n text,\n createdAt: new Date().toISOString(),\n resolved: false,\n };\n const fp = this.filePath(input.sessionId);\n const t0 = Date.now();\n try {\n await this.enqueue(input.sessionId, async () => {\n await withFileLock(fp, async () => {\n const all = await this.list(input.sessionId);\n all.push(annotation);\n // Evict oldest if we crossed the cap. Resolved first, then oldest.\n if (all.length > MAX_ANNOTATIONS) {\n const sorted = all\n .map((a, i) => ({ a, i }))\n .sort((x, y) => {\n // resolved=false wins (keep unresolved); among same resolved state, oldest first.\n /* v8 ignore next -- scale+tiebreak: needs >1000 annotations with mixed resolved states */\n if (x.a.resolved !== y.a.resolved) return x.a.resolved ? 1 : -1;\n return x.a.createdAt.localeCompare(y.a.createdAt);\n });\n const evictCount = all.length - MAX_ANNOTATIONS;\n const toEvict = new Set(sorted.slice(0, evictCount).map((s) => s.a.id));\n const kept = all.filter((a) => !toEvict.has(a.id));\n await this.writeFile(input.sessionId, { version: FILE_VERSION, annotations: kept });\n const durationMs = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: input.sessionId,\n store: 'annotations',\n filePath: fp,\n operation: 'evict',\n outcome: 'success',\n durationMs,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n } else {\n await this.writeFile(input.sessionId, { version: FILE_VERSION, annotations: all });\n const durationMs = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: input.sessionId,\n store: 'annotations',\n filePath: fp,\n operation: 'add',\n outcome: 'success',\n durationMs,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n }\n });\n });\n return annotation;\n } catch (err) {\n this.events?.emit('storage.error', {\n sessionId: input.sessionId,\n store: 'annotations',\n filePath: fp,\n operation: 'add',\n outcome: 'failure',\n error: toErrorMessage(err),\n recoverable: false,\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n throw err;\n }\n }\n\n /**\n * Mark an annotation as resolved. Returns the updated record, or\n * `null` if no annotation with that id exists in this session.\n * Idempotent: resolving an already-resolved annotation refreshes\n * `resolvedAt` / `resolvedBy` to the latest call.\n */\n async resolve(input: {\n sessionId: string;\n annotationId: string;\n resolvedBy: string;\n }): Promise<Annotation | null> {\n let updated: Annotation | null = null;\n const fp = this.filePath(input.sessionId);\n const t0 = Date.now();\n try {\n await this.enqueue(input.sessionId, async () => {\n await withFileLock(fp, async () => {\n const all = await this.list(input.sessionId);\n const idx = all.findIndex((a) => a.id === input.annotationId);\n if (idx === -1) {\n updated = null;\n return;\n }\n const next: Annotation = {\n ...expectDefined(all[idx]),\n resolved: true,\n resolvedAt: new Date().toISOString(),\n resolvedBy: input.resolvedBy,\n };\n all[idx] = next;\n await this.writeFile(input.sessionId, { version: FILE_VERSION, annotations: all });\n updated = next;\n const durationMs = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: input.sessionId,\n store: 'annotations',\n filePath: fp,\n operation: 'resolve',\n outcome: 'success',\n durationMs,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n });\n });\n return updated;\n } catch (err) {\n this.events?.emit('storage.error', {\n sessionId: input.sessionId,\n store: 'annotations',\n filePath: fp,\n operation: 'resolve',\n outcome: 'failure',\n error: toErrorMessage(err),\n recoverable: false,\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n throw err;\n }\n }\n\n // ── Internals ──────────────────────────────────────────────────────────\n\n private filePath(sessionId: string): string {\n // Containment-checked: date-sharded ids (\"2026-06-11/<base>\") are\n // legitimate; traversal is rejected. A plain slash ban here used to\n // throw for every modern session id, breaking annotations entirely.\n return sessionScopedPath(this.dir, sessionId, '.annotations.json');\n }\n\n private async readFile(sessionId: string): Promise<AnnotationsFile | null> {\n const fp = this.filePath(sessionId);\n let raw: string;\n try {\n raw = await fs.readFile(fp, 'utf8');\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return null;\n // Non-ENOENT I/O errors (EACCES, ENOSPC): re-throw so callers emit\n // storage.error.\n throw err;\n }\n try {\n const parsed = JSON.parse(raw) as AnnotationsFile;\n if (parsed.version !== FILE_VERSION) {\n return { version: FILE_VERSION, annotations: [] };\n }\n return parsed;\n } catch {\n // JSON parse error (SyntaxError): treat as empty store — not an I/O failure.\n return null;\n }\n }\n\n private async writeFile(sessionId: string, file: AnnotationsFile): Promise<void> {\n const fp = this.filePath(sessionId);\n await atomicWrite(fp, JSON.stringify(file, null, 2));\n }\n\n /**\n * Serialize writes per-sessionId. We chain promises instead of\n * using a Mutex class so the contract is obvious from the\n * call-site: `enqueue(sid, fn)` runs `fn` after every prior\n * enqueue for `sid` has settled.\n */\n private enqueue(sessionId: string, fn: () => Promise<void>): Promise<void> {\n const prev = this.writeChains.get(sessionId) ?? Promise.resolve();\n const next = prev.then(fn, fn);\n // Keep the chain intact even when `fn` throws; failures\n // shouldn't break subsequent writes.\n this.writeChains.set(\n sessionId,\n next.catch(() => undefined),\n );\n return next;\n }\n}\n","import { createHash } from 'node:crypto';\nimport type { Request } from '../types/provider.js';\n\n/**\n * Idea #2 from IDEAS.md — Deterministic Replay.\n *\n * The hash function is the foundation of replay: given a `Request`,\n * produce a stable identifier so a recorded `Response` can be looked\n * up later when we want to \"re-run\" the same agent loop without\n * burning API credits.\n *\n * Stability rules:\n *\n * - All object keys are sorted recursively before stringification.\n * Without this, two semantically identical requests that differ\n * only in key insertion order would produce different hashes.\n * - We hash ONLY the fields that affect the response: `model`,\n * `system`, `messages`, `tools`, `maxTokens`, and the four\n * sampling knobs (`temperature`, `topP`, `stopSequences`,\n * `toolChoice`). Anything else on the `Request` (metadata,\n * future extensions) is ignored so replay stays forward-compat.\n * - We serialize to JSON. The `ContentBlock` and `Message` shapes\n * are pure data; this works as long as no `undefined` values\n * sneak in (those get dropped by `JSON.stringify`, which is\n * fine — the structural diff is what matters).\n *\n * The SHA-256 output is hex-encoded and prefixed with the algorithm\n * tag so a future migration to a different hash (e.g. blake3) is\n * trivial to detect.\n */\nexport function stableStringify(value: unknown): string {\n return JSON.stringify(sortKeys(value));\n}\n\nfunction sortKeys(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortKeys);\n if (value && typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(obj).sort()) {\n sorted[key] = sortKeys(obj[key]);\n }\n return sorted;\n }\n return value;\n}\n\nexport function hashRequest(request: Request): string {\n // Pick only the fields that affect the response. See stability rules.\n const payload = {\n model: request.model,\n system: request.system,\n messages: request.messages,\n tools: request.tools,\n maxTokens: request.maxTokens,\n temperature: request.temperature,\n topP: request.topP,\n stopSequences: request.stopSequences,\n toolChoice: request.toolChoice,\n };\n const json = stableStringify(payload);\n const digest = createHash('sha256').update(json, 'utf8').digest('hex');\n return `sha256:${digest}`;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { atomicWrite, withFileLock } from '../utils/atomic-write.js';\nimport { toErrorMessage } from '../utils/error.js';\nimport { sessionScopedPath } from '../utils/session-scoped-path.js';\nimport { hashRequest } from '../replay/hash.js';\nimport type { Request, Response } from '../types/provider.js';\nimport { safeParse } from '../utils/safe-json.js';\nimport type { EventBus } from '../kernel/events.js';\n\n/**\n * Surface the OS error code (EACCES, ENOSPC, …) alongside the message in\n * storage.* event payloads. Codes are stable and locale-independent, so\n * they are what dashboards and alerts key on; the message is supplementary.\n */\nfunction storageErrorString(err: unknown): string {\n if (err instanceof Error) {\n const code = (err as NodeJS.ErrnoException).code;\n return code ? `${code}: ${err.message}` : err.message;\n }\n /* v8 ignore next -- defensive: fs/lock failures are always Error instances */\n return String(err);\n}\n\n/**\n * ReplayLogStore — sidecar store for deterministic-replay support\n * (idea #2 from IDEAS.md). One JSONL file per session, recording\n * every provider request/response pair so the same agent loop can\n * be re-run later with frozen API responses.\n *\n * Why a sidecar (not the session JSONL)?\n *\n * Same reason as `AnnotationsStore` — the session log is\n * event-sourced and append-only; a provider request payload can be\n * tens of kilobytes (especially with long conversation history),\n * and we want replay to be opt-in (recorded only when the user\n * runs with `--replay` or a future equivalent). Mixing it into\n * the event log would inflate every read for replay-irrelevant\n * paths.\n *\n * File layout: `<dir>/<sessionId>.replay.jsonl`, one entry per line.\n * Each entry: `{ hash, ts, request, response }`. The `hash` is\n * computed via `hashRequest` so lookups are O(1) by hash.\n *\n * Concurrency: per-session write queue (same pattern as\n * `AnnotationsStore`). Reads are lock-free; the write chain makes\n * the append + rehash sequence atomic.\n */\nexport interface ReplayEntry {\n hash: string;\n ts: string;\n request: Request;\n response: Response;\n}\n\nconst FILE_VERSION = 1;\n\n/** Default cap on the number of entries per session. */\nconst DEFAULT_MAX_ENTRIES = 1000;\n\nexport interface ReplayLogStoreOptions {\n /** Directory where `<sessionId>.replay.jsonl` files live. */\n dir: string;\n /**\n * Cap on the number of entries per session. When a `record` would\n * push the file beyond this, the oldest entries are evicted (LRU\n * by insertion order). Set to `Infinity` to disable rotation.\n * Defaults to 1000 — a single LLM call averages ~5KB serialized\n * (messages + tools + response), so 1000 entries is ~5MB per\n * session which is a reasonable upper bound.\n */\n maxEntries?: number | undefined;\n events?: EventBus;\n traceId?: string;\n}\n\ninterface ReplayEntryLocation {\n entry?: ReplayEntry;\n offset: number;\n length: number;\n}\n\nexport class ReplayLogStore {\n private readonly dir: string;\n private readonly events: EventBus | undefined;\n private readonly traceId: string | undefined;\n private readonly writeChains = new Map<string, Promise<void>>();\n /** Per-session hash → on-disk location, with lazy entry hydration. */\n private readonly cache = new Map<string, Map<string, ReplayEntryLocation>>();\n /** Per-session entry count on disk, to detect when compaction is needed. */\n private readonly diskCount = new Map<string, number>();\n private readonly maxEntries: number;\n\n constructor(opts: ReplayLogStoreOptions) {\n this.dir = opts.dir;\n this.events = opts.events;\n this.traceId = opts.traceId;\n this.maxEntries = opts.maxEntries ?? DEFAULT_MAX_ENTRIES;\n }\n\n // ── Writes ──────────────────────────────────────────────────────────────\n\n /**\n * Record a request/response pair. Idempotent on hash: a second\n * `record` for the same hash is a no-op (the existing entry wins).\n * Returns the hash.\n */\n async record(input: {\n sessionId: string;\n request: Request;\n response: Response;\n }): Promise<string> {\n const hash = hashRequest(input.request);\n const fp = this.filePath(input.sessionId);\n const t0 = Date.now();\n try {\n await this.enqueue(input.sessionId, async () => {\n await withFileLock(fp, async () => {\n // Dedup via the in-memory hash map — O(1) instead of re-reading\n // and re-parsing the whole JSONL just to run `entries.some(...)`.\n // `ensureCache` populates both the cache and `diskCount` from a\n // single read on first contact; subsequent records reuse it.\n const cache = await this.ensureCache(input.sessionId);\n if (cache.has(hash)) return; // already recorded\n\n const entry: ReplayEntry = {\n hash,\n ts: new Date().toISOString(),\n request: input.request,\n response: input.response,\n };\n\n const currentCount = this.diskCount.get(input.sessionId) ?? 0;\n const willEvict = currentCount + 1 > this.maxEntries;\n\n if (!willEvict) {\n // Common path (the first `maxEntries` writes per session, plus\n // any session that never hits the cap): a single O(1) append.\n // The previous implementation did a full readAll + full rewrite\n // (atomicWrite of the entire file) on every single record, which\n // was quadratic in session length — a 1000-call session rewrote\n // a multi-MB file 1000 times.\n const line = JSON.stringify(entry) + '\\n';\n let offset = 0;\n try {\n const stat = await fs.stat(fp);\n offset = stat.size;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;\n }\n await fs.appendFile(fp, line, 'utf8');\n cache.set(hash, { entry, offset, length: Buffer.byteLength(line, 'utf8') });\n this.diskCount.set(input.sessionId, currentCount + 1);\n this.events?.emit('storage.write', {\n sessionId: input.sessionId,\n store: 'replay',\n filePath: fp,\n operation: 'record',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return;\n }\n\n // Eviction path: we're at capacity, drop the oldest entry to make\n // room. This does require a full read + rewrite, but it fires at\n // most once per `maxEntries` writes (default 1000), not per write.\n const all = await this.readAll(input.sessionId);\n all.push(entry);\n const keep = all.slice(-this.maxEntries);\n const refreshed = new Map<string, ReplayEntryLocation>();\n let offset = 0;\n for (const e of keep) {\n const line = JSON.stringify(e) + '\\n';\n refreshed.set(e.hash, { entry: e, offset, length: Buffer.byteLength(line, 'utf8') });\n offset += Buffer.byteLength(line, 'utf8');\n }\n this.cache.set(input.sessionId, refreshed);\n this.diskCount.set(input.sessionId, keep.length);\n await this.writeAll(input.sessionId, keep, 'compact');\n });\n });\n return hash;\n } catch (err) {\n this.events?.emit('storage.error', {\n sessionId: input.sessionId,\n store: 'replay',\n filePath: fp,\n operation: 'record',\n outcome: 'failure',\n error: storageErrorString(err),\n recoverable: false,\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n throw err;\n }\n }\n\n // ── Reads ───────────────────────────────────────────────────────────────\n\n /**\n * Look up an entry by hash. Returns `null` when the request has\n * not been recorded for this session. O(1) after the first call\n * per session (in-memory cache).\n */\n async lookup(sessionId: string, hash: string): Promise<ReplayEntry | null> {\n const fp = this.filePath(sessionId);\n const t0 = Date.now();\n try {\n const cache = await this.ensureCache(sessionId);\n const location = cache.get(hash);\n const entry = location ? await this.hydrateEntry(sessionId, hash, location) : null;\n this.events?.emit('storage.read', {\n sessionId,\n store: 'replay',\n filePath: fp,\n operation: 'lookup',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return entry;\n } catch (err) {\n this.events?.emit('storage.read', {\n sessionId,\n store: 'replay',\n filePath: fp,\n operation: 'lookup',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: storageErrorString(err),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n throw err;\n }\n }\n\n /** All recorded entries for a session, in insertion order. */\n async load(sessionId: string): Promise<ReplayEntry[]> {\n const fp = this.filePath(sessionId);\n const t0 = Date.now();\n try {\n const cache = await this.ensureCache(sessionId);\n const entries: ReplayEntry[] = [];\n for (const [hash, location] of cache) {\n entries.push(await this.hydrateEntry(sessionId, hash, location));\n }\n const durationMs = Date.now() - t0;\n this.events?.emit('storage.read', {\n sessionId,\n store: 'replay',\n filePath: fp,\n operation: 'load',\n outcome: 'success',\n durationMs,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return entries;\n } catch (err) {\n const durationMs = Date.now() - t0;\n this.events?.emit('storage.read', {\n sessionId,\n store: 'replay',\n filePath: fp,\n operation: 'load',\n outcome: 'failure',\n durationMs,\n error: storageErrorString(err),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n throw err;\n }\n }\n\n /**\n * List every session id that has a replay log in the store dir.\n * Returns an array of `{ sessionId, entryCount, path }` sorted\n * by sessionId for stable output. Used by `wstack replay --list`.\n */\n async list(): Promise<Array<{ sessionId: string; entryCount: number; path: string }>> {\n const out: Array<{ sessionId: string; entryCount: number; path: string }> = [];\n // Replay logs sit next to their session JSONL — flat at the root for\n // legacy/`record-<ts>` ids, inside a date-shard dir for modern ids.\n // Scan both levels; a root-only scan misses every sharded session.\n const scan = async (dir: string, prefix: string, depth: number): Promise<void> => {\n let entries: import('node:fs').Dirent[];\n try {\n entries = await fs.readdir(dir, { withFileTypes: true });\n } catch (err) {\n if (depth === 0 && (err as NodeJS.ErrnoException).code !== 'ENOENT') {\n // EACCES, ENOTDIR, etc. — log the real error so the operator can\n // diagnose a misconfiguration, but still return empty list so the\n // caller (slash command display) doesn't crash.\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'replay_log_store.list_readdir_failed',\n dir,\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n }\n return;\n }\n for (const entry of entries) {\n if (entry.name.startsWith('.')) continue;\n if (entry.isDirectory()) {\n if (depth === 0) await scan(path.join(dir, entry.name), entry.name, depth + 1);\n continue;\n }\n if (!entry.isFile() || !entry.name.endsWith('.replay.jsonl')) continue;\n const base = entry.name.slice(0, -'.replay.jsonl'.length);\n const sessionId = prefix ? `${prefix}/${base}` : base;\n const fp = path.join(dir, entry.name);\n out.push({\n sessionId,\n entryCount: await this.countEntries(fp),\n path: fp,\n });\n }\n };\n await scan(this.dir, '', 0);\n return out.sort((a, b) => a.sessionId.localeCompare(b.sessionId));\n }\n\n // ── Internals ───────────────────────────────────────────────────────────\n\n private filePath(sessionId: string): string {\n // Containment-checked: date-sharded ids (\"2026-06-11/<base>\") are\n // legitimate; traversal is rejected. A plain slash ban would throw\n // the moment a real (sharded) session id is used for --replay.\n return sessionScopedPath(this.dir, sessionId, '.replay.jsonl');\n }\n\n private async countEntries(filePath: string): Promise<number> {\n // list() only needs a count, not provider request/response payloads. Count\n // non-empty JSONL rows in fixed-size chunks so large replay logs are not\n // parsed or materialized just to render `wstack replay --list`.\n const handle = await fs.open(filePath, 'r');\n const buffer = Buffer.allocUnsafe(64 * 1024);\n let count = 0;\n let hasNonWhitespace = false;\n try {\n while (true) {\n const { bytesRead } = await handle.read(buffer, 0, buffer.length, null);\n if (bytesRead === 0) break;\n for (let i = 0; i < bytesRead; i++) {\n const ch = buffer[i]!;\n if (ch === 10) {\n if (hasNonWhitespace) count++;\n hasNonWhitespace = false;\n continue;\n }\n if (ch !== 13 && ch !== 32 && ch !== 9) {\n hasNonWhitespace = true;\n }\n }\n }\n } finally {\n await handle.close();\n }\n if (hasNonWhitespace) count++;\n return count;\n }\n\n private parseReplayLine(line: string): ReplayEntry | null {\n try {\n const parsed = safeParse<\n { version?: number | undefined; entry?: ReplayEntry | undefined } & ReplayEntry\n >(line);\n if (!parsed.ok || !parsed.value) return null;\n if ('entry' in parsed.value && parsed.value.entry) {\n return parsed.value.entry;\n }\n return parsed.value;\n } catch {\n return null;\n }\n }\n\n private async readAll(sessionId: string): Promise<ReplayEntry[]> {\n const fp = this.filePath(sessionId);\n try {\n const raw = await fs.readFile(fp, 'utf8');\n const out: ReplayEntry[] = [];\n for (const line of raw.split('\\n')) {\n if (!line.trim()) continue;\n const parsed = this.parseReplayLine(line);\n if (parsed) out.push(parsed);\n }\n return out;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return [];\n throw err;\n }\n }\n\n private async writeAll(\n sessionId: string,\n entries: ReplayEntry[],\n operation: 'record' | 'compact' = 'record',\n ): Promise<void> {\n const fp = this.filePath(sessionId);\n const t0 = Date.now();\n const body = entries.map((e) => JSON.stringify(e)).join('\\n') + (entries.length ? '\\n' : '');\n await atomicWrite(fp, body);\n const durationMs = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId,\n store: 'replay',\n filePath: fp,\n operation,\n outcome: 'success',\n durationMs,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n // Drop the version-stamp comment at the top — v1 has no envelope,\n // but we keep a one-line marker for human readers / future tooling.\n // (The atomicWrite just wrote pure JSONL; that's correct for v1.)\n void FILE_VERSION;\n }\n\n private async ensureCache(sessionId: string): Promise<Map<string, ReplayEntryLocation>> {\n let cache = this.cache.get(sessionId);\n if (cache) return cache;\n\n const fp = this.filePath(sessionId);\n cache = new Map();\n try {\n const handle = await fs.open(fp, 'r');\n const CHUNK = 64 * 1024;\n const buffer = Buffer.alloc(CHUNK);\n let leftover = '';\n let leftoverOffset = 0;\n let fileOffset = 0;\n try {\n while (true) {\n const { bytesRead } = await handle.read(buffer, 0, CHUNK, fileOffset);\n if (bytesRead === 0) break;\n const chunk = buffer.subarray(0, bytesRead).toString('utf8');\n const text = leftover + chunk;\n let lineStart = leftoverOffset;\n let searchFrom = 0;\n while (true) {\n const newlineIndex = text.indexOf('\\n', searchFrom);\n if (newlineIndex === -1) break;\n const line = text.slice(searchFrom, newlineIndex);\n const lineLength = Buffer.byteLength(text.slice(searchFrom, newlineIndex + 1), 'utf8');\n if (line.trim()) {\n const entry = this.parseReplayLine(line);\n if (entry) {\n cache.set(entry.hash, { offset: lineStart, length: lineLength });\n }\n }\n lineStart += lineLength;\n searchFrom = newlineIndex + 1;\n }\n leftover = text.slice(searchFrom);\n leftoverOffset = lineStart;\n fileOffset += bytesRead;\n }\n if (leftover.trim()) {\n const entry = this.parseReplayLine(leftover);\n if (entry) {\n cache.set(entry.hash, { offset: leftoverOffset, length: Buffer.byteLength(leftover, 'utf8') });\n }\n }\n } finally {\n await handle.close();\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;\n }\n\n this.cache.set(sessionId, cache);\n this.diskCount.set(sessionId, cache.size);\n return cache;\n }\n\n private async hydrateEntry(\n sessionId: string,\n hash: string,\n location: ReplayEntryLocation,\n ): Promise<ReplayEntry> {\n if (location.entry) return location.entry;\n\n const fp = this.filePath(sessionId);\n const handle = await fs.open(fp, 'r');\n try {\n const buffer = Buffer.alloc(location.length);\n const { bytesRead } = await handle.read(buffer, 0, location.length, location.offset);\n const line = buffer.subarray(0, bytesRead).toString('utf8').trimEnd();\n const entry = this.parseReplayLine(line);\n if (!entry) {\n throw new Error(`Replay entry ${hash} is unreadable`);\n }\n location.entry = entry;\n return entry;\n } finally {\n await handle.close();\n }\n }\n\n private enqueue(sessionId: string, fn: () => Promise<void>): Promise<void> {\n const prev = this.writeChains.get(sessionId) ?? Promise.resolve();\n const next = prev.then(fn, fn);\n this.writeChains.set(\n sessionId,\n next.catch(() => undefined),\n );\n return next;\n }\n}\n","import { expectDefined } from '../utils/expect-defined.js';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { SessionEvent } from '../types/session.js';\nimport { sessionScopedPath } from '../utils/session-scoped-path.js';\n/**\n * Idea #1 from IDEAS.md — Stateful Session Recovery.\n *\n * `SessionRecovery` is the read-side companion to the in-flight\n * marker mechanism. When the agent loop is running, it writes an\n * `in_flight_start` event at the current point in the log. On\n * clean shutdown, a matching `in_flight_end` follows. If the\n * process dies (crash, OOM, machine sleep, SIGKILL) the marker\n * is the last event in the file — and `detectStale` flags the\n * session as \"incomplete, can be resumed\".\n *\n * Phase 1 of this feature is **detection only**. The actual\n * re-execution of incomplete work is a follow-up: it requires\n * tracking pending tool calls, mid-stream LLM responses, and\n * uncommitted file changes — and re-running the agent loop from\n * the last `checkpoint` event. The detection layer is independent\n * and ships first because (a) it gives the user immediate\n * visibility into what died, and (b) it's the foundation for the\n * resume command and the CLI's \"Incomplete sessions\" surface.\n *\n * Concurrency: pure read; no writes. Safe to call from multiple\n * processes simultaneously.\n */\nexport interface StaleSession {\n sessionId: string;\n /** Path to the JSONL log. */\n path: string;\n /** Last event ts (the in_flight_start timestamp). */\n lastEventTs: string;\n /** Context the agent was working on when it died. */\n context: string;\n /** Total events in the log. */\n eventCount: number;\n}\n\nexport interface RecoveryPlan {\n sessionId: string;\n /** True if the session is stale (has a dangling in_flight_start). */\n stale: boolean;\n /** The last `checkpoint` event before the un-replayed work, or null. */\n lastCheckpoint: SessionEvent | null;\n /** All events after the last checkpoint (i.e. the work that needs re-execution). */\n pendingEvents: SessionEvent[];\n /** The dangling in_flight_start event, if any. */\n inFlightStart: SessionEvent | null;\n /** Free-form context the agent was working on, if any. */\n context: string | null;\n}\n\n/**\n * Result of `SessionRecovery.recover(sessionId)`. Distinct from\n * `StaleSession`: a session is \"stale\" if the last event is an\n * open marker, but a \"recovery plan\" can also be generated for\n * clean sessions whose last checkpoint is older than the\n * conversation history (e.g. a user-initiated \"rewind to last\n * good state\" flow). Phase 2 of idea #1: this returns the plan;\n * the actual kernel re-execution is a follow-up.\n */\nexport class SessionRecovery {\n /**\n * Scan a session log and return a `StaleSession` if and only\n * if the last event is an `in_flight_start` without a matching\n * `in_flight_end`. Returns `null` when:\n * - the log does not exist;\n * - the log is empty;\n * - the last event is `in_flight_end` (clean shutdown);\n * - the last event is something else (e.g. an unannotated\n * legacy log without in-flight markers).\n */\n async detectStale(sessionId: string): Promise<StaleSession | null> {\n const fp = this.filePath(sessionId);\n // Only read the last ~8KB — enough for several large events.\n // This is O(1) I/O vs O(n) of reading the entire file.\n const TAIL_SIZE = 8192;\n let stat;\n try {\n stat = await fs.stat(fp);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return null;\n /* v8 ignore next -- defensive: any other stat failure is also non-recoverable */\n return null;\n }\n if (stat.size === 0) return null;\n const position = Math.max(0, stat.size - TAIL_SIZE);\n const buf = Buffer.alloc(TAIL_SIZE);\n let fh;\n try {\n fh = await fs.open(fp, 'r');\n const { bytesRead } = await fh.read(buf, 0, TAIL_SIZE, position);\n // Count total events for StaleSession.eventCount — requires full scan.\n // For very large files this is a trade-off; count is informational.\n let eventCount = 0;\n const raw = buf.subarray(0, bytesRead).toString('utf8');\n for (const line of raw.split('\\n')) {\n if (line.trim()) eventCount++;\n }\n // Find the last complete JSON line in the tail.\n const lines = raw.split('\\n').filter((l) => l.trim());\n for (let i = lines.length - 1; i >= 0; i--) {\n try {\n const ev = JSON.parse(expectDefined(lines[i])) as SessionEvent;\n if (ev.type === 'in_flight_start') {\n return {\n sessionId,\n path: fp,\n lastEventTs: ev.ts,\n context: ev.context,\n eventCount,\n };\n }\n // Found a different last event — clean shutdown or legacy\n return null;\n } catch {\n // Incomplete line (spans the read boundary) — skip\n }\n }\n return null;\n /* v8 ignore start -- defensive: tail open/read failure after a successful stat is rare */\n } catch {\n return null;\n } finally {\n if (fh) await fh.close();\n }\n /* v8 ignore stop */\n }\n\n /**\n * Generate a recovery plan for a session. The plan describes\n * \"what would be re-executed\" if the user chose to resume —\n * everything after the last `checkpoint` event, plus the\n * dangling in-flight marker if present.\n *\n * Returns a non-null plan for ANY session that has at least\n * one event after a checkpoint (or, for legacy sessions, at\n * least one event). Pure read; no mutation.\n */\n async recover(sessionId: string): Promise<RecoveryPlan | null> {\n const fp = this.filePath(sessionId);\n let raw: string;\n try {\n raw = await fs.readFile(fp, 'utf8');\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return null;\n /* v8 ignore next -- defensive: any other read failure is also non-recoverable */\n return null;\n }\n const events: SessionEvent[] = [];\n for (const line of raw.split('\\n')) {\n if (!line.trim()) continue;\n try {\n events.push(JSON.parse(line) as SessionEvent);\n } catch {\n // skip corrupt lines\n }\n }\n if (events.length === 0) return null;\n // Find the last checkpoint.\n let lastCheckpoint: SessionEvent | null = null;\n let lastCheckpointIdx = -1;\n for (let i = 0; i < events.length; i++) {\n if (events[i]?.type === 'checkpoint') {\n lastCheckpoint = expectDefined(events[i]);\n lastCheckpointIdx = i;\n }\n }\n // Events after the last checkpoint = the work that needs re-execution.\n const pendingEvents =\n lastCheckpointIdx >= 0 ? events.slice(lastCheckpointIdx + 1) : events;\n // The dangling in_flight_start, if the last event is one.\n const lastEv = expectDefined(events[events.length - 1]);\n const inFlightStart =\n lastEv.type === 'in_flight_start' ? lastEv : null;\n const context = inFlightStart && inFlightStart.type === 'in_flight_start'\n ? inFlightStart.context\n : null;\n return {\n sessionId,\n stale: inFlightStart !== null,\n lastCheckpoint,\n pendingEvents,\n inFlightStart,\n context,\n };\n }\n\n /**\n * List every stale session in a directory. Returns an array\n * (possibly empty) sorted by `lastEventTs` descending — most\n * recent crash first.\n */\n async listResumable(): Promise<StaleSession[]> {\n const out: StaleSession[] = [];\n // Modern sessions live inside date-shard subdirectories\n // (\"2026-06-11/<base>.jsonl\"); legacy/flat sessions sit at the root.\n // Scan both — a root-only scan silently misses every modern crash.\n const collect = async (dir: string, prefix: string, depth: number): Promise<void> => {\n let entries: import('node:fs').Dirent[];\n try {\n entries = await fs.readdir(dir, { withFileTypes: true });\n /* v8 ignore start -- defensive: the sessions dir (and its shards) are readable during a scan */\n } catch {\n return;\n }\n /* v8 ignore stop */\n for (const entry of entries) {\n if (entry.name.startsWith('.')) continue;\n if (\n entry.name === 'shared' ||\n entry.name === 'subagents' ||\n entry.name === 'attachments'\n )\n continue;\n if (entry.isDirectory()) {\n if (depth === 0) {\n await collect(path.join(dir, entry.name), entry.name, depth + 1);\n }\n continue;\n }\n if (!entry.isFile() || !entry.name.endsWith('.jsonl')) continue;\n if (entry.name === '_index.jsonl' || entry.name === '_mailbox.jsonl') continue;\n const base = entry.name.slice(0, -'.jsonl'.length);\n if (base.includes('.replay') || base.includes('.annotations') || base.includes('.audit'))\n continue;\n const sessionId = prefix ? `${prefix}/${base}` : base;\n const stale = await this.detectStale(sessionId);\n if (stale) out.push(stale);\n }\n };\n await collect(this.dir, '', 0);\n return out.sort((a, b) => b.lastEventTs.localeCompare(a.lastEventTs));\n }\n\n // ── Internals ──────────────────────────────────────────────────────────\n\n private filePath(sessionId: string): string {\n // Containment-checked: date-sharded ids (\"2026-06-11/<base>\") are\n // legitimate; traversal is rejected. Shared with the other per-session\n // sidecar stores so the contract can't drift.\n return sessionScopedPath(this.dir, sessionId, '.jsonl');\n }\n\n constructor(private readonly dir: string) {}\n}\n","import { expectDefined } from '../utils/expect-defined.js';\nimport { toErrorMessage } from '../utils/error.js';\nimport { createHash, randomUUID } from 'node:crypto';\nimport * as fs from 'node:fs/promises';\nimport { withFileLock } from '../utils/atomic-write.js';\nimport { safeParse } from '../utils/safe-json.js';\nimport { sessionScopedPath } from '../utils/session-scoped-path.js';\nimport type { EventBus } from '../kernel/events.js';\n/**\n * ToolAuditLog — idea #9 from IDEAS.md.\n *\n * Tamper-evident audit trail for tool calls. Every tool_use /\n * tool_result pair is appended to a sidecar JSONL with a chained\n * SHA-256 — each entry's `prevHash` is the prior entry's `hash`,\n * so any post-hoc modification of a single line breaks the chain\n * from that point forward.\n *\n * Why a sidecar (not the session JSONL)?\n * Same reason as `AnnotationsStore` and `ReplayLogStore`: the\n * session log is an event-sourced journal. Mixing in a hash\n * chain would inflate every read and tightly couple the\n * integrity check to the event format. Sidecar keeps both\n * concerns orthogonal.\n *\n * What \"tamper-evident\" means here:\n * - The hash covers the full serialized entry: tool name, id,\n * input, output, timestamp, author. Changing any byte\n * changes the hash.\n * - The chain is sequential — a verifier walks the file in\n * order, recomputing each hash, and checks `prevHash`\n * matches the previous entry's `hash`.\n * - Any insertion, deletion, or modification of a single\n * entry surfaces as a \"chain broken at entry N\" verdict.\n *\n * What it does NOT defend against:\n * - An attacker who rewrites the whole file consistently.\n * For that you'd need an external anchor (signing key,\n * transparency log, etc.) — out of scope for Phase 1.\n * - The agent itself misbehaving; this is post-hoc audit, not\n * real-time enforcement. Use `PermissionPolicy` for that.\n *\n * File layout: `<dir>/<sessionId>.audit.jsonl`, one entry per\n * line. The chain starts with a `genesis` entry whose\n * `prevHash` is all zeros.\n */\nexport interface AuditEntry {\n /** Monotonic index (0-based). */\n index: number;\n /** UUID for cross-referencing with logs. */\n id: string;\n /** ISO timestamp. */\n ts: string;\n /** Hash of the previous entry (or all-zeros for the genesis entry). */\n prevHash: string;\n /** Hash of this entry's content (sha256 over the canonical JSON). */\n hash: string;\n toolName: string;\n toolUseId: string;\n input: unknown;\n output: unknown;\n isError: boolean;\n}\n\nconst GENESIS_PREV = '0'.repeat(64);\n\nexport type VerifyResult =\n | { ok: true; entries: number }\n | { ok: false; brokenAt: number; reason: string };\n\nexport interface ToolAuditLogOptions {\n /** Directory where `<sessionId>.audit.jsonl` files live. */\n dir: string;\n /**\n * Flush the file system cache to disk every N writes per session.\n * Default 100. Lower values = better crash durability, more I/O overhead.\n * Set to `Infinity` to disable periodic fsync (fastest, but highest data-loss risk).\n */\n fsyncEvery?: number | undefined;\n events?: EventBus;\n traceId?: string;\n}\n\n/** Default number of writes between fsync calls. */\nconst DEFAULT_FSYNC_EVERY = 100;\n\nexport class ToolAuditLog {\n private readonly dir: string;\n private readonly events: EventBus | undefined;\n private readonly traceId: string | undefined;\n /** In-memory cache of the last entry's hash (per session), to compute chains efficiently. */\n private readonly tailHash = new Map<string, string>();\n /** In-memory counter for entry indices — avoids re-reading the file on every write. */\n private readonly tailIndex = new Map<string, number>();\n /**\n * File mtime+size recorded after our last write, per session. Used to\n * detect cross-process writes (session handoff, recovery) that would\n * invalidate the in-memory tail cache: if the stat no longer matches\n * we re-read the file to re-establish the chain tip before appending.\n */\n private readonly tailStat = new Map<string, { mtimeMs: number; size: number }>();\n /** Tracks writes since last fsync, per session. */\n private readonly unSyncedWrites = new Map<string, number>();\n private readonly writeChains = new Map<string, Promise<void>>();\n private readonly fsyncEvery: number;\n\n constructor(opts: ToolAuditLogOptions) {\n this.dir = opts.dir;\n this.events = opts.events;\n this.traceId = opts.traceId;\n this.fsyncEvery = opts.fsyncEvery ?? DEFAULT_FSYNC_EVERY;\n }\n\n /**\n * Append a tool call/result pair to the chain. Returns the\n * resulting entry. Idempotency is not guaranteed — if you\n * record the same tool_use twice you get two entries. That's\n * intentional: the audit log is a record, not a cache.\n */\n async record(input: {\n sessionId: string;\n toolName: string;\n toolUseId: string;\n input: unknown;\n output: unknown;\n isError: boolean;\n }): Promise<AuditEntry> {\n let entry!: AuditEntry; // assigned inside the enqueue callback\n const fp = this.filePath(input.sessionId);\n const t0 = Date.now();\n try {\n await this.enqueue(input.sessionId, async () => {\n await withFileLock(fp, async () => {\n // Resolve the chain tip from the in-memory cache when possible,\n // re-reading the file only on first contact or when an external\n // writer (cross-process session handoff) changed it under us.\n // The previous implementation did `readAll` on every single\n // record just to find `entries.at(-1)` — a full parse of the\n // audit file per tool call.\n const tip = await this._resolveChainTip(input.sessionId, fp);\n const prevHash = tip.prevHash;\n const index = tip.nextIndex;\n\n const id = randomUUID();\n const ts = new Date().toISOString();\n const content = {\n id,\n ts,\n prevHash,\n toolName: input.toolName,\n toolUseId: input.toolUseId,\n input: input.input,\n output: input.output,\n isError: input.isError,\n index,\n };\n const hash = createHash('sha256').update(stableStringify(content), 'utf8').digest('hex');\n entry = {\n id,\n ts,\n prevHash,\n hash,\n toolName: input.toolName,\n toolUseId: input.toolUseId,\n input: input.input,\n output: input.output,\n isError: input.isError,\n index,\n };\n\n // True O(1) append — one line, no full-file rewrite. The previous\n // `writeAll(entries)` path re-serialized every entry on every\n // record; a 1000-call session rewrote a multi-MB audit file 1000\n // times (quadratic in session length). `withFileLock` above\n // guarantees no concurrent writer interleaves with our append.\n await fs.appendFile(fp, JSON.stringify(entry) + '\\n', 'utf8');\n\n // Refresh caches + fsync bookkeeping. We stat post-write so the\n // mtime+size tracker reflects the just-appended line — the next\n // record can trust the cache without re-reading.\n try {\n const st = await fs.stat(fp);\n this.tailStat.set(input.sessionId, { mtimeMs: st.mtimeMs, size: st.size });\n } catch {\n /* best-effort; next record will just re-read */\n }\n this.tailHash.set(input.sessionId, hash);\n this.tailIndex.set(input.sessionId, index + 1);\n await this._trackUnsynced(input.sessionId, fp);\n\n const durationMs = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: input.sessionId,\n store: 'audit',\n filePath: fp,\n operation: 'record',\n outcome: 'success',\n durationMs,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n });\n });\n return entry;\n } catch (err) {\n this.events?.emit('storage.error', {\n sessionId: input.sessionId,\n store: 'audit',\n filePath: fp,\n operation: 'record',\n outcome: 'failure',\n error: toErrorMessage(err),\n recoverable: false,\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n throw err;\n }\n }\n\n /**\n * Resolve the chain tip (previous hash + next index) for an append.\n * Uses the in-memory `tailHash`/`tailIndex` cache when the file's\n * stat matches our last known write; falls back to a full read on\n * cache miss or when an external writer has extended the file.\n */\n private async _resolveChainTip(\n sessionId: string,\n fp: string,\n ): Promise<{ prevHash: string; nextIndex: number }> {\n const cachedHash = this.tailHash.get(sessionId);\n const cachedIndex = this.tailIndex.get(sessionId);\n const cachedStat = this.tailStat.get(sessionId);\n\n if (cachedHash !== undefined && cachedIndex !== undefined && cachedStat) {\n // Verify no other process appended since our last write. Stat is a\n // single inode lookup; the common case (same-process sequential\n // writes) returns immediately and we skip the full read.\n try {\n const st = await fs.stat(fp);\n if (st.mtimeMs === cachedStat.mtimeMs && st.size === cachedStat.size) {\n return { prevHash: cachedHash, nextIndex: cachedIndex };\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n // File was removed out from under us — reset and start a new chain.\n this.tailHash.delete(sessionId);\n this.tailIndex.delete(sessionId);\n this.tailStat.delete(sessionId);\n return { prevHash: GENESIS_PREV, nextIndex: 0 };\n }\n /* v8 ignore next -- defensive: a non-ENOENT stat failure during cache-hit is rare */\n throw err;\n }\n }\n\n // Cache miss or external write detected — read the true tail.\n const entries = await this.readAll(sessionId);\n const prev = entries.at(-1);\n const prevHash = prev?.hash ?? GENESIS_PREV;\n const nextIndex = prev ? prev.index + 1 : 0;\n this.tailHash.set(sessionId, prevHash);\n this.tailIndex.set(sessionId, nextIndex);\n try {\n const st = await fs.stat(fp);\n this.tailStat.set(sessionId, { mtimeMs: st.mtimeMs, size: st.size });\n } catch {\n /* leave cache empty; next record re-reads */\n }\n return { prevHash, nextIndex };\n }\n\n /**\n * Walk the chain and verify every entry's hash and prevHash.\n * Returns a structured verdict — never throws.\n */\n async verify(sessionId: string): Promise<VerifyResult> {\n const fp = this.filePath(sessionId);\n const t0 = Date.now();\n let entries: AuditEntry[];\n try {\n entries = await this.readAll(sessionId);\n } catch (err) {\n // The file exists but can't be read (permissions, corruption). We\n // can't verify it, so emit a read failure for observability and\n // degrade gracefully — this method's contract is \"never throws\".\n this.events?.emit('storage.read', {\n sessionId,\n store: 'audit',\n filePath: fp,\n operation: 'verify',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: toErrorMessage(err),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return { ok: true, entries: 0 };\n }\n\n // Walk the chain into a verdict, then emit a single storage.read whose\n // outcome reflects the verification result (a broken chain is a failure).\n const verdict = ((): VerifyResult => {\n if (entries.length === 0) return { ok: true, entries: 0 };\n // The first entry's prevHash must be the all-zeros genesis marker.\n if (entries[0]?.prevHash !== GENESIS_PREV) {\n return {\n ok: false,\n brokenAt: 0,\n reason: 'first entry is not the genesis (prevHash != 0…0)',\n };\n }\n let prevHash = GENESIS_PREV;\n for (let i = 0; i < entries.length; i++) {\n const e = expectDefined(entries[i]);\n if (e.prevHash !== prevHash) {\n return {\n ok: false,\n brokenAt: i,\n reason: `prevHash mismatch at entry ${i} (expected ${prevHash.slice(0, 8)}…, got ${e.prevHash.slice(0, 8)}…)`,\n };\n }\n // Recompute the hash from the entry's content (without the\n // `hash` field itself, which is what we are verifying).\n const content = {\n id: e.id,\n ts: e.ts,\n prevHash: e.prevHash,\n toolName: e.toolName,\n toolUseId: e.toolUseId,\n input: e.input,\n output: e.output,\n isError: e.isError,\n index: e.index,\n };\n const expectedHash = createHash('sha256')\n .update(stableStringify(content), 'utf8')\n .digest('hex');\n if (expectedHash !== e.hash) {\n return {\n ok: false,\n brokenAt: i,\n reason: `hash mismatch at entry ${i} (entry content was modified)`,\n };\n }\n prevHash = e.hash;\n }\n return { ok: true, entries: entries.length };\n })();\n\n this.events?.emit('storage.read', {\n sessionId,\n store: 'audit',\n filePath: fp,\n operation: 'verify',\n outcome: verdict.ok ? 'success' : 'failure',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return verdict;\n }\n\n /** All entries for a session, in insertion order. */\n async load(sessionId: string): Promise<AuditEntry[]> {\n const fp = this.filePath(sessionId);\n const t0 = Date.now();\n try {\n const entries = await this.readAll(sessionId);\n const durationMs = Date.now() - t0;\n this.events?.emit('storage.read', {\n sessionId,\n store: 'audit',\n filePath: fp,\n operation: 'load',\n outcome: 'success',\n durationMs,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return entries;\n } catch (err) {\n const durationMs = Date.now() - t0;\n this.events?.emit('storage.read', {\n sessionId,\n store: 'audit',\n filePath: fp,\n operation: 'load',\n outcome: 'failure',\n durationMs,\n error: toErrorMessage(err),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n throw err;\n }\n }\n\n // ── Internals ────────────────────────────────────────────────────────────\n\n private filePath(sessionId: string): string {\n // Containment-checked: date-sharded ids (\"2026-06-11/<base>\") are\n // legitimate; traversal is rejected. A plain slash ban would throw\n // for every modern session id the moment record() gets wired in.\n return sessionScopedPath(this.dir, sessionId, '.audit.jsonl');\n }\n\n private async readAll(sessionId: string): Promise<AuditEntry[]> {\n const fp = this.filePath(sessionId);\n try {\n const raw = await fs.readFile(fp, 'utf8');\n const out: AuditEntry[] = [];\n for (const line of raw.split('\\n')) {\n if (!line.trim()) continue;\n try {\n const parsed = safeParse<AuditEntry>(line);\n if (parsed.ok && parsed.value) out.push(parsed.value);\n } catch {\n // Skip corrupt lines — audit data is meta, not fatal.\n }\n }\n return out;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return [];\n // Non-ENOENT errors (EACCES, ENOSPC, etc.) are real I/O failures —\n // re-throw so callers (verify, load) can emit storage.error.\n throw err;\n }\n }\n\n /**\n * Tracks writes since last fsync and triggers periodic fsync.\n * Called after each O(1) append to maintain the same durability\n * guarantees as the old writeAll approach.\n */\n private async _trackUnsynced(sessionId: string, fp: string): Promise<void> {\n const count = (this.unSyncedWrites.get(sessionId) ?? 0) + 1;\n this.unSyncedWrites.set(sessionId, count);\n if (this.fsyncEvery !== Number.POSITIVE_INFINITY && count % this.fsyncEvery === 0) {\n await this.sync(sessionId, fp);\n }\n }\n\n /**\n * Explicitly sync the file to disk. Called automatically every\n * `fsyncEvery` writes, and available for callers who want to\n * force a sync before closing or during graceful shutdown.\n */\n async flush(sessionId: string): Promise<void> {\n await this.sync(sessionId, this.filePath(sessionId));\n }\n\n private async sync(sessionId: string, fp: string): Promise<void> {\n try {\n const fh = await fs.open(fp, 'r+');\n try {\n await fh.sync();\n } finally {\n await fh.close();\n }\n } catch {\n // fsync is best-effort; a failure here does not corrupt the chain.\n } finally {\n this.unSyncedWrites.set(sessionId, 0);\n }\n }\n\n private enqueue(sessionId: string, fn: () => Promise<void>): Promise<void> {\n const prev = this.writeChains.get(sessionId) ?? Promise.resolve();\n const next = prev.then(fn, fn);\n this.writeChains.set(\n sessionId,\n next.catch(() => undefined),\n );\n return next;\n }\n}\n\nfunction stableStringify(value: unknown): string {\n return JSON.stringify(sortKeys(value));\n}\n\nfunction sortKeys(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortKeys);\n if (value && typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(obj).sort()) {\n sorted[key] = sortKeys(obj[key]);\n }\n return sorted;\n }\n return value;\n}\n","import type { SessionEvent } from '../types/session.js';\n\nexport interface QueryFilter {\n eventTypes?: string[] | undefined;\n toolNames?: string[] | undefined;\n timeRange?: { start: string; end: string } | undefined;\n}\n\nexport interface ToolInvocation {\n ts: string;\n name: string;\n input: unknown;\n output?: unknown | undefined;\n error?: string | undefined;\n durationMs: number;\n}\n\nexport interface SessionError {\n ts: string;\n phase: string;\n message: string;\n}\n\nexport interface ModeChange {\n ts: string;\n from: string;\n to: string;\n}\n\nexport interface TaskSummary {\n taskId: string;\n title: string;\n status: string;\n createdAt: string;\n completedAt?: string | undefined;\n}\n\nexport interface SessionAnalysis {\n sessionId: string;\n totalDuration: number;\n toolUsageCount: Record<string, number>;\n errorCount: number;\n modeChanges: ModeChange[];\n tasks: TaskSummary[];\n}\n\nexport class SessionAnalyzer {\n analyze(events: SessionEvent[]): SessionAnalysis {\n const toolUsageCount: Record<string, number> = {};\n const errors: SessionError[] = [];\n const modeChanges: ModeChange[] = [];\n const tasksById = new Map<string, TaskSummary>();\n let sessionId = '';\n\n for (const event of events) {\n // sessionId comes from session_start / session_resumed.\n if (event.type === 'session_start' || event.type === 'session_resumed') {\n if (!sessionId) sessionId = event.id;\n }\n if (event.type === 'tool_use') {\n toolUsageCount[event.name] = (toolUsageCount[event.name] ?? 0) + 1;\n }\n if (event.type === 'error') {\n errors.push({ ts: event.ts, phase: event.phase, message: event.message });\n }\n if (event.type === 'mode_changed') {\n modeChanges.push({ ts: event.ts, from: event.from, to: event.to });\n }\n if (event.type === 'task_created') {\n tasksById.set(event.taskId, {\n taskId: event.taskId,\n title: event.title,\n status: 'created',\n createdAt: event.ts,\n });\n }\n if (event.type === 'task_updated') {\n const t = tasksById.get(event.taskId);\n if (t) t.status = event.status;\n }\n if (event.type === 'task_completed') {\n const t = tasksById.get(event.taskId);\n if (t) {\n t.status = 'completed';\n t.completedAt = event.ts;\n } else {\n tasksById.set(event.taskId, {\n taskId: event.taskId,\n title: event.title,\n status: 'completed',\n createdAt: event.ts,\n completedAt: event.ts,\n });\n }\n }\n if (event.type === 'task_failed') {\n const t = tasksById.get(event.taskId);\n if (t) {\n t.status = 'failed';\n t.completedAt = event.ts;\n } else {\n tasksById.set(event.taskId, {\n taskId: event.taskId,\n title: event.title,\n status: 'failed',\n createdAt: event.ts,\n completedAt: event.ts,\n });\n }\n }\n }\n\n return {\n sessionId,\n totalDuration: this.calcDuration(events),\n toolUsageCount,\n errorCount: errors.length,\n modeChanges,\n tasks: Array.from(tasksById.values()),\n };\n }\n\n query(events: SessionEvent[], filter: QueryFilter): SessionEvent[] {\n return events.filter((e) => {\n if (filter.eventTypes?.length && !filter.eventTypes.includes(e.type)) return false;\n if (filter.toolNames?.length && e.type === 'tool_use') {\n const toolEvent = e as { type: 'tool_use'; name: string };\n if (!filter.toolNames.includes(toolEvent.name)) return false;\n }\n if (filter.timeRange) {\n const ts = new Date(e.ts).getTime();\n const start = new Date(filter.timeRange.start).getTime();\n const end = new Date(filter.timeRange.end).getTime();\n if (ts < start || ts > end) return false;\n }\n return true;\n });\n }\n\n private calcDuration(events: SessionEvent[]): number {\n if (events.length < 2) return 0;\n const firstEvent = events[0];\n const lastEvent = events[events.length - 1];\n /* v8 ignore next -- defensive: length>=2 guard above guarantees both ends exist */\n if (!firstEvent || !lastEvent) return 0;\n const first = new Date(firstEvent.ts).getTime();\n const last = new Date(lastEvent.ts).getTime();\n return last - first;\n }\n}\n","/**\n * SessionRegistry — cross-process session and agent tracker.\n *\n * Each WrongStack process registers its session on start and updates its\n * status periodically. The registry is a single JSON file at\n * `~/.wrongstack/session-registry.json`. Entries are keyed by session ID.\n *\n * Because multiple processes may write concurrently, every write is an\n * atomic read-modify-write protected by a per-file advisory lock (flock on\n * Unix, exclusive open on Windows). Stale entries (process no longer alive)\n * are pruned on every read.\n *\n * @module session-registry\n */\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { randomUUID } from 'node:crypto';\n\n// ── Types ─────────────────────────────────────────────────────────────────\n\n/** Live status of a single agent within a session. */\nexport type AgentLiveStatus =\n | 'idle'\n | 'running'\n | 'streaming'\n | 'waiting_user' // brain.ask_human, confirm prompt\n | 'error';\n\nexport interface AgentEntry {\n /** Unique agent id (ULID or UUID). */\n id: string;\n /** Human-readable label (e.g. \"leader\", \"bug-hunter #1\"). */\n name: string;\n /** UTC ISO timestamp when this agent/run started, when known. */\n startedAt?: string | undefined;\n status: AgentLiveStatus;\n /** Current tool name if running, undefined otherwise. */\n currentTool?: string | undefined;\n /** Iteration count so far. */\n iterations: number;\n /** Tool calls so far. */\n toolCalls: number;\n /** Cumulative cost in USD for this agent, when known. */\n costUsd?: number | undefined;\n /** Cumulative input tokens, when known. */\n tokensIn?: number | undefined;\n /** Cumulative output tokens, when known. */\n tokensOut?: number | undefined;\n /** Context window fill 0–100 (may exceed 100 when over limit), when known. */\n ctxPct?: number | undefined;\n /** Model id this agent is running on, when known. */\n model?: string | undefined;\n /**\n * Tail of the assistant text currently being streamed (capped, throttled).\n * Lets a cross-process watcher see the response form in near-real-time\n * instead of waiting for the completed turn to land in the session log.\n */\n partialText?: string | undefined;\n /** UTC ISO timestamp of last activity. */\n lastActivityAt: string;\n}\n\nexport type SessionLiveStatus =\n | 'active' // process running, agents may be idle or busy\n | 'idle' // process running, no agent activity\n | 'closing' // session_end written, process shutting down\n | 'stale'; // process no longer alive (pruned on next read)\n\nexport interface SessionRegistryEntry {\n sessionId: string;\n projectSlug: string;\n projectRoot: string;\n projectName: string;\n workingDir: string;\n /**\n * Which surface owns this session — `'tui'` / `'webui'` / `'cli'` (one-shot or\n * REPL). Lets cross-process consumers (e.g. the WebUI Fleet HQ office map) label\n * each live session by client kind. Optional for back-compat with older entries.\n */\n clientType?: 'tui' | 'webui' | 'cli' | 'repl' | string | undefined;\n /** Current git branch, if the project is a git repo. Detected at registration. */\n gitBranch?: string | undefined;\n status: SessionLiveStatus;\n pid: number;\n /** UTC ISO */\n startedAt: string;\n /** UTC ISO — updated on every heartbeat */\n lastHeartbeatAt: string;\n /** Count of tracked agents */\n agentCount: number;\n agents: AgentEntry[];\n}\n\n// ── Constants ─────────────────────────────────────────────────────────────\n\nconst REGISTRY_FILE = 'session-registry.json';\nconst HEARTBEAT_INTERVAL_MS = 5_000;\nconst STALE_TIMEOUT_MS = 30_000; // entry considered stale after 30s without heartbeat\n// A session that announced `closing` (heartbeat stopped) is dropped this long\n// after its last heartbeat, so the fleet view doesn't keep a dead client around.\nconst CLOSING_GRACE_MS = 15_000;\n// A held lock is released within milliseconds; anything older is a crashed\n// owner's leftover and is safe to break so writes never wedge permanently.\nconst STALE_LOCK_MS = 10_000;\nconst STALE_TMP_MS = 60_000;\nconst MAX_STALE_TMP_FILES = 20;\n\n// ── Helpers ───────────────────────────────────────────────────────────────\n\nfunction pidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n// ── Registry class ────────────────────────────────────────────────────────\n\nexport class SessionRegistry {\n private readonly filePath: string;\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private currentSessionId: string | null = null;\n /**\n * Last full entry this process registered. Kept so the heartbeat can\n * re-create our entry if it ever goes missing — e.g. our initial register()\n * write was dropped (a wedged lock), the file was reset, or we were pruned.\n */\n private lastEntry: SessionRegistryEntry | null = null;\n\n constructor(globalRoot: string) {\n this.filePath = path.join(globalRoot, REGISTRY_FILE);\n }\n\n // ── Public API ──────────────────────────────────────────────────────────\n\n /**\n * Register the current session. Call once on session start.\n * Starts the heartbeat timer.\n */\n async register(\n entry: Omit<SessionRegistryEntry, 'status' | 'lastHeartbeatAt' | 'agentCount' | 'agents'> & {\n agents?: AgentEntry[] | undefined;\n },\n ): Promise<void> {\n // Safe to call again on a project switch: the WebUI re-roots in place and\n // creates a fresh session id pointing at the new project. Clear the prior\n // heartbeat timer (otherwise each switch leaks a timer that keeps writing).\n // A process owns exactly one entry, so the same-pid dedup below drops our\n // own previous entry — the registry never carries a phantom session still\n // pointing at the old project's root/workingDir.\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n this.currentSessionId = entry.sessionId;\n const full: SessionRegistryEntry = {\n ...entry,\n status: 'active',\n lastHeartbeatAt: new Date().toISOString(),\n agentCount: entry.agents?.length ?? 0,\n agents: entry.agents ?? [],\n };\n this.lastEntry = full;\n await this.atomicUpdate((registry) => {\n // Prune dead entries that haven't heartbeated recently.\n // A just-created entry has no heartbeat yet — don't prune it.\n const now = Date.now();\n for (const [id, existing] of Object.entries(registry)) {\n if (existing.pid === entry.pid) {\n // Our own process owns exactly one entry. When re-registering under\n // a new session id (project switch re-roots in place), drop the\n // stale same-pid entry so it doesn't linger pointing at the old\n // project's root/workingDir.\n if (id !== entry.sessionId) delete registry[id];\n continue;\n }\n const heartbeatAge = now - new Date(existing.lastHeartbeatAt).getTime();\n if (heartbeatAge > STALE_TIMEOUT_MS && !pidAlive(existing.pid)) {\n delete registry[id];\n }\n }\n registry[entry.sessionId] = full;\n });\n\n // Start heartbeat\n this.heartbeatTimer = setInterval(() => {\n void this.heartbeat();\n }, HEARTBEAT_INTERVAL_MS);\n if (this.heartbeatTimer.unref) this.heartbeatTimer.unref();\n }\n\n /**\n * Update agent status for the current session. Call on every\n * significant status change (agent start, tool start, user wait, error).\n */\n async updateAgents(agents: AgentEntry[]): Promise<void> {\n if (!this.currentSessionId) return;\n // Derive session status from the agent collective.\n const hasRunning = agents.some((a) => a.status === 'running' || a.status === 'streaming');\n const hasWaiting = agents.some((a) => a.status === 'waiting_user');\n const hasError = agents.some((a) => a.status === 'error');\n const status: SessionLiveStatus = hasRunning || hasWaiting || hasError ? 'active' : 'idle';\n const nowIso = new Date().toISOString();\n\n // Keep the cached entry current so a heartbeat re-insert carries live agents.\n if (this.lastEntry) {\n this.lastEntry.agents = agents;\n this.lastEntry.agentCount = agents.length;\n this.lastEntry.status = status;\n this.lastEntry.lastHeartbeatAt = nowIso;\n }\n\n await this.atomicUpdate((registry) => {\n let entry = registry[this.currentSessionId!];\n if (!entry) {\n // Our entry vanished (dropped write / reset / pruned) — re-create it.\n if (!this.lastEntry) return;\n entry = { ...this.lastEntry };\n registry[this.currentSessionId!] = entry;\n }\n entry.agents = agents;\n entry.agentCount = agents.length;\n entry.status = status;\n entry.lastHeartbeatAt = nowIso;\n });\n }\n\n /**\n * Mark the session as closing. Called during shutdown.\n * Stops the heartbeat timer.\n */\n async markClosing(): Promise<void> {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n if (!this.currentSessionId) return;\n await this.atomicUpdate((registry) => {\n const entry = registry[this.currentSessionId!];\n if (!entry) return;\n entry.status = 'closing';\n entry.lastHeartbeatAt = new Date().toISOString();\n });\n }\n\n /**\n * Remove the current session from the registry. Call on clean exit.\n */\n async unregister(): Promise<void> {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n if (!this.currentSessionId) return;\n const sid = this.currentSessionId;\n this.currentSessionId = null;\n await this.atomicUpdate((registry) => {\n delete registry[sid];\n });\n }\n\n /**\n * List all non-stale sessions. Prunes stale entries automatically.\n */\n async list(): Promise<SessionRegistryEntry[]> {\n const registry = await this.readAndPrune();\n return Object.values(registry);\n }\n\n /**\n * Get a single session entry by ID. Returns undefined if not found or stale.\n */\n async get(sessionId: string): Promise<SessionRegistryEntry | undefined> {\n const registry = await this.readAndPrune();\n return registry[sessionId];\n }\n\n /**\n * List all sessions for a specific project (by slug).\n */\n async listByProject(projectSlug: string): Promise<SessionRegistryEntry[]> {\n const all = await this.list();\n return all.filter((e) => e.projectSlug === projectSlug);\n }\n\n /**\n * Return the registry file path. Useful for WebUI to watch/read.\n */\n get registryPath(): string {\n return this.filePath;\n }\n\n // ── Internal ────────────────────────────────────────────────────────────\n\n private async heartbeat(): Promise<void> {\n if (!this.currentSessionId) return;\n try {\n const sessionId = this.currentSessionId;\n const nowIso = new Date().toISOString();\n await this.atomicUpdate((registry) => {\n const entry = registry[sessionId];\n if (entry) {\n entry.lastHeartbeatAt = nowIso;\n // Status bound: if closing, don't revert\n if (entry.status !== 'closing') {\n const hasRunning = (entry.agents ?? []).some(\n (a) => a.status === 'running' || a.status === 'streaming',\n );\n entry.status = hasRunning ? 'active' : 'idle';\n }\n return;\n }\n if (this.lastEntry) {\n // Our entry is gone (initial register() dropped on a wedged lock, file\n // reset, or pruned). Re-create it through the locked path so a process\n // that booted into a broken registry still shows up once it heals.\n registry[sessionId] = { ...this.lastEntry, lastHeartbeatAt: nowIso };\n }\n });\n } catch {\n // Best-effort heartbeat — never throw\n }\n }\n\n private async readAndPrune(): Promise<Record<string, SessionRegistryEntry>> {\n try {\n const raw = await fs.readFile(this.filePath, 'utf8');\n const registry = JSON.parse(raw) as Record<string, SessionRegistryEntry>;\n const now = Date.now();\n let pruned = false;\n\n for (const [id, entry] of Object.entries(registry)) {\n const heartbeatAge = now - new Date(entry.lastHeartbeatAt).getTime();\n // Cleanly-closed session: drop after a short grace (handles both a fully\n // exited process and one still alive but done) so no dead client lingers.\n if (entry.status === 'closing' && heartbeatAge > CLOSING_GRACE_MS) {\n delete registry[id];\n pruned = true;\n continue;\n }\n if (heartbeatAge > STALE_TIMEOUT_MS && !pidAlive(entry.pid)) {\n entry.status = 'stale';\n // Keep stale entries for 5 minutes so UIs can show \"recently closed\"\n const startedAge = now - new Date(entry.startedAt).getTime();\n if (startedAge > 5 * 60_000) {\n delete registry[id];\n pruned = true;\n }\n }\n }\n\n if (pruned) {\n await this.writeAtomic(registry).catch(() => undefined);\n }\n\n return registry;\n } catch {\n return {};\n }\n }\n\n private async atomicUpdate(\n fn: (registry: Record<string, SessionRegistryEntry>) => void,\n ): Promise<void> {\n const lockPath = `${this.filePath}.lock`;\n const maxRetries = 8;\n const retryDelayMs = 20;\n\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n // Ensure directory exists\n await fs.mkdir(path.dirname(this.filePath), { recursive: true });\n\n // Acquire exclusive lock via O_CREAT | O_EXCL\n let lockHandle = await fs.open(lockPath, 'wx').catch(() => null);\n if (!lockHandle) {\n // Lock contended. A crashed process can leave its lock file behind\n // forever (the `finally` unlink never ran), which would wedge EVERY\n // future write — the registry silently stops updating. Break the lock\n // when its owner pid is dead or it has been held implausibly long\n // (legit holds are sub-millisecond), then retry the open once.\n if (await this.breakStaleLock(lockPath)) {\n lockHandle = await fs.open(lockPath, 'wx').catch(() => null);\n }\n if (!lockHandle) {\n await new Promise((r) => setTimeout(r, retryDelayMs * (attempt + 1)));\n continue;\n }\n }\n\n try {\n // Stamp the owner pid so other processes can detect a stale lock.\n await lockHandle.writeFile(String(process.pid)).catch(() => undefined);\n const raw = await fs.readFile(this.filePath, 'utf8').catch(() => '{}');\n const registry = JSON.parse(raw) as Record<string, SessionRegistryEntry>;\n fn(registry);\n await this.writeAtomicLocked(registry);\n return; // success\n } finally {\n await lockHandle.close();\n await fs.unlink(lockPath).catch(() => undefined);\n }\n } catch {\n // Best-effort — never throw from registry writes\n return;\n }\n }\n // All retries exhausted — registry update dropped (non-critical)\n }\n\n /**\n * Break a contended lock if it is stale: the recorded owner pid is no longer\n * alive, or the lock is older than {@link STALE_LOCK_MS}. Returns true when the\n * lock was removed (caller should retry acquisition). Best-effort and\n * race-tolerant — a fresh lock (age ~0, live owner) is never broken, so the\n * common concurrent case self-heals on the next heartbeat.\n */\n private async breakStaleLock(lockPath: string): Promise<boolean> {\n try {\n const [stat, content] = await Promise.all([\n fs.stat(lockPath),\n fs.readFile(lockPath, 'utf8').catch(() => ''),\n ]);\n const ageMs = Date.now() - stat.mtimeMs;\n const ownerPid = Number.parseInt(content.trim(), 10);\n const ownerDead =\n Number.isInteger(ownerPid) && ownerPid > 0 && ownerPid !== process.pid && !pidAlive(ownerPid);\n if (ownerDead || ageMs > STALE_LOCK_MS) {\n await fs.unlink(lockPath).catch(() => undefined);\n return true;\n }\n return false;\n } catch {\n // stat failed → the lock vanished underneath us; let the caller retry.\n return true;\n }\n }\n\n private async writeAtomicLocked(registry: Record<string, SessionRegistryEntry>): Promise<void> {\n await this.pruneStaleTempFiles();\n await this.writeAtomicFile(registry);\n }\n\n /** Legacy write without lock — used by heartbeat for performance. */\n private async writeAtomic(registry: Record<string, SessionRegistryEntry>): Promise<void> {\n await this.pruneStaleTempFiles();\n await this.writeAtomicFile(registry);\n }\n\n private async writeAtomicFile(registry: Record<string, SessionRegistryEntry>): Promise<void> {\n const tmp = path.join(\n path.dirname(this.filePath),\n `.${path.basename(this.filePath)}.${randomUUID().slice(0, 8)}.tmp`,\n );\n try {\n await fs.writeFile(tmp, JSON.stringify(registry, null, 2), 'utf8');\n await fs.rename(tmp, this.filePath);\n } catch (err) {\n await fs.unlink(tmp).catch(() => undefined);\n throw err;\n }\n }\n\n private async pruneStaleTempFiles(): Promise<void> {\n try {\n const dir = path.dirname(this.filePath);\n const base = path.basename(this.filePath);\n const now = Date.now();\n const stale: Array<{ name: string; mtimeMs: number }> = [];\n\n for (const name of await fs.readdir(dir)) {\n const isTemp =\n (name.startsWith(`${base}.`) || name.startsWith(`.${base}.`)) && name.endsWith('.tmp');\n if (!isTemp) continue;\n const stat = await fs.stat(path.join(dir, name)).catch(() => null);\n if (!stat) continue;\n if (now - stat.mtimeMs > STALE_TMP_MS) stale.push({ name, mtimeMs: stat.mtimeMs });\n }\n\n stale.sort((a, b) => b.mtimeMs - a.mtimeMs);\n await Promise.all(\n stale.slice(MAX_STALE_TMP_FILES).map(async ({ name }) => {\n await fs.unlink(path.join(dir, name)).catch(() => undefined);\n }),\n );\n } catch {\n // best-effort cleanup must not block registry heartbeats\n }\n }\n}\n\n/** Singleton — created once per process. */\nlet _instance: SessionRegistry | null = null;\n\nexport function getSessionRegistry(globalRoot?: string): SessionRegistry {\n if (!_instance && globalRoot) {\n _instance = new SessionRegistry(globalRoot);\n }\n if (!_instance) {\n throw new Error('SessionRegistry not initialized. Call getSessionRegistry(globalRoot) first.');\n }\n return _instance;\n}\n\nexport function hasSessionRegistry(): boolean {\n return _instance !== null;\n}\n","/**\n * AgentStatusTracker — subscribes to EventBus events and keeps the\n * SessionRegistry updated with live agent status.\n *\n * Created once per process during boot. Listens for:\n * - agent.run.started / agent.run.completed → agent status changes\n * - tool.started / tool.executed → current tool tracking\n * - brain.ask_human → waiting_user status\n * - fleet events (subagent spawn/start/done) → agent entries\n *\n * @module agent-status-tracker\n */\nimport type { EventBus } from './kernel/events.js';\nimport type {\n AgentEntry,\n AgentLiveStatus,\n SessionRegistry,\n} from './session-registry.js';\n\n/** A finished (idle/error) subagent older than this is reaped from the fleet view. */\nconst AGENT_REAP_MS = 30_000;\n/** How often the reaper sweeps for finished subagents. */\nconst AGENT_SWEEP_INTERVAL_MS = 10_000;\n/** Max chars of streamed assistant text kept in the registry (the live tail). */\nconst PARTIAL_TEXT_CAP = 1200;\n/** Min gap between registry flushes triggered purely by streamed text. */\nconst PARTIAL_FLUSH_THROTTLE_MS = 300;\n\nfunction clampPct(pct: number): number {\n if (!Number.isFinite(pct)) return 0;\n return Math.max(0, Math.min(100, pct));\n}\n\nexport interface AgentStatusTrackerOptions {\n events: EventBus;\n registry: SessionRegistry;\n /** Leader agent name shown in the registry. Default: \"leader\". */\n leaderName?: string | undefined;\n /**\n * Best-effort callback fired after each registry write settles. Used to nudge\n * local WebUI servers (FleetNotifier) so cross-process status reaches the map\n * without waiting on their file-watch/poll. Never block or throw.\n */\n onUpdate?: (() => void) | undefined;\n}\n\nexport class AgentStatusTracker {\n private readonly events: EventBus;\n private readonly registry: SessionRegistry;\n private readonly leaderName: string;\n\n // Live agent map: agentId → AgentEntry\n private agents = new Map<string, AgentEntry>();\n // Last full agent list flushed (leader + subagents). Lets external consumers\n // read the current state synchronously without re-deriving it.\n private lastAgents: AgentEntry[] = [];\n\n // Leader tracking\n private leaderStatus: AgentLiveStatus = 'idle';\n private leaderCurrentTool: string | undefined;\n private leaderIterations = 0;\n private leaderToolCalls = 0;\n private leaderCostUsd = 0;\n private leaderTokensIn = 0;\n private leaderTokensOut = 0;\n private leaderCtxPct: number | undefined;\n private leaderModel: string | undefined;\n private leaderPartialText = '';\n private leaderStartedAt: string | undefined;\n\n private unsubscribers: Array<() => void> = [];\n private readonly onUpdate: (() => void) | undefined;\n private sweepTimer: ReturnType<typeof setInterval> | null = null;\n private partialTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(opts: AgentStatusTrackerOptions) {\n this.events = opts.events;\n this.registry = opts.registry;\n this.leaderName = opts.leaderName ?? 'leader';\n this.onUpdate = opts.onUpdate;\n }\n\n /** Current full agent list (leader + subagents) as of the last flush. */\n getAgents(): AgentEntry[] {\n return this.lastAgents.length > 0 ? [...this.lastAgents] : [];\n }\n\n start(): void {\n // Leader events\n this.unsubscribers.push(\n this.events.onPattern('agent.run.started', (_event, payload) => {\n const p = payload as { at?: string; model?: string; ctx?: unknown } | undefined;\n this.markLeaderStarted(p?.at);\n this.captureLeaderContext(p?.ctx);\n if (p?.model) this.leaderModel = p.model;\n this.leaderStatus = 'running';\n this.leaderIterations++;\n this.flush();\n }),\n );\n\n // Capture the leader's model + context fill from each iteration's context.\n this.unsubscribers.push(\n this.events.onPattern('iteration.started', (_e, payload) => {\n const p = payload as { ctx?: unknown; index?: number } | undefined;\n const ctx = p?.ctx;\n this.markLeaderStarted();\n this.leaderStatus = 'running';\n if (typeof p?.index === 'number') {\n this.leaderIterations = Math.max(this.leaderIterations, p.index + 1);\n }\n if (!ctx) {\n this.flush();\n return;\n }\n this.captureLeaderContext(ctx);\n this.flush();\n }),\n );\n\n this.unsubscribers.push(\n this.events.onPattern('agent.run.completed', (_event, payload) => {\n const p = payload as { status?: string; ctx?: unknown } | undefined;\n this.captureLeaderContext(p?.ctx);\n this.leaderStatus = p?.status === 'failed' ? 'error' : 'idle';\n this.leaderCurrentTool = undefined;\n this.leaderPartialText = '';\n if (this.leaderStatus === 'idle') this.leaderStartedAt = undefined;\n this.flush();\n }),\n );\n\n this.unsubscribers.push(\n this.events.onPattern('agent.run.error', (_event, payload) => {\n const p = payload as { ctx?: unknown } | undefined;\n this.captureLeaderContext(p?.ctx);\n this.leaderStatus = 'error';\n this.leaderCurrentTool = undefined;\n this.leaderPartialText = '';\n this.flush();\n }),\n );\n\n // Tool events — track current tool\n this.unsubscribers.push(\n this.events.onPattern('tool.started', (_event, payload) => {\n const p = payload as { name?: string } | undefined;\n if (p?.name) {\n this.markLeaderStarted();\n this.leaderCurrentTool = p.name;\n this.leaderToolCalls++;\n }\n this.leaderStatus = 'running';\n this.flush();\n }),\n );\n\n this.unsubscribers.push(\n this.events.onPattern('tool.executed', () => {\n this.leaderCurrentTool = undefined;\n this.flush();\n }),\n );\n\n // Brain ask_human → waiting for user input\n this.unsubscribers.push(\n this.events.onPattern('brain.ask_human', () => {\n this.markLeaderStarted();\n this.leaderStatus = 'waiting_user';\n this.flush();\n }),\n );\n\n // Streaming events\n this.unsubscribers.push(\n this.events.onPattern('llm.stream_started', () => {\n this.markLeaderStarted();\n this.leaderStatus = 'streaming';\n // A new response is starting — drop the previous turn's live tail.\n this.leaderPartialText = '';\n this.flush();\n }),\n );\n\n // Live assistant text — accumulate the streamed tail so a cross-process\n // watcher sees the response form. Flushed on a throttle, NOT per token\n // (text_delta fires once per chunk → would thrash the shared registry).\n this.unsubscribers.push(\n this.events.onPattern('provider.text_delta', (_e, payload) => {\n const p = payload as { text?: string; ctx?: unknown } | undefined;\n const text = p?.text;\n if (!text) return;\n this.markLeaderStarted();\n this.captureLeaderContext(p?.ctx);\n this.leaderStatus = 'streaming';\n const next = this.leaderPartialText + text;\n this.leaderPartialText =\n next.length > PARTIAL_TEXT_CAP ? next.slice(next.length - PARTIAL_TEXT_CAP) : next;\n this.schedulePartialFlush();\n }),\n );\n\n this.unsubscribers.push(\n this.events.onPattern('provider.response', (_e, payload) => {\n const p = payload as { ctx?: unknown } | undefined;\n this.captureLeaderContext(p?.ctx);\n this.flush();\n }),\n );\n\n this.unsubscribers.push(\n this.events.onPattern('provider.fallback', (_e, payload) => {\n const p = payload as { to?: { providerId?: string; model?: string } } | undefined;\n if (p?.to?.model) {\n this.leaderModel = p.to.providerId\n ? `${p.to.providerId}/${p.to.model}`\n : p.to.model;\n this.flush();\n }\n }),\n );\n\n this.unsubscribers.push(\n this.events.onPattern('ctx.pct', (_e, payload) => {\n const p = payload as { load?: number } | undefined;\n if (typeof p?.load === 'number' && Number.isFinite(p.load)) {\n this.leaderCtxPct = clampPct(Math.round(p.load * 100));\n this.flush();\n }\n }),\n );\n\n // Leader token + cost accounting (per provider call — accumulate).\n this.unsubscribers.push(\n this.events.onPattern('token.accounted', (_e, payload) => {\n const p = payload as\n | { usage?: { input?: number; output?: number }; cost?: { total?: number } }\n | undefined;\n if (!p) return;\n this.leaderTokensIn += p.usage?.input ?? 0;\n this.leaderTokensOut += p.usage?.output ?? 0;\n this.leaderCostUsd += p.cost?.total ?? 0;\n this.flush();\n }),\n );\n\n // ── Subagent tracking ──────────────────────────────────────────────\n // These are the real fleet lifecycle events (emitted by MultiAgentHost /\n // the subagent runner / director). The previous code listened to a\n // `fleet.subagent.*` namespace that nothing emits, so subagents never\n // reached the registry — only the leader showed up.\n const touch = (id: string): AgentEntry => {\n let entry = this.agents.get(id);\n if (!entry) {\n const now = new Date().toISOString();\n entry = { id, name: id, status: 'idle', iterations: 0, toolCalls: 0, startedAt: now, lastActivityAt: now };\n this.agents.set(id, entry);\n }\n entry.lastActivityAt = new Date().toISOString();\n return entry;\n };\n\n this.unsubscribers.push(\n this.events.onPattern('subagent.spawned', (_e, payload) => {\n const p = payload as { subagentId?: string; name?: string; model?: string } | undefined;\n if (!p?.subagentId) return;\n const entry = touch(p.subagentId);\n entry.name = p.name?.trim() || entry.name;\n if (p.model) entry.model = p.model;\n if (!entry.startedAt) entry.startedAt = new Date().toISOString();\n entry.status = 'running';\n this.flush();\n }),\n );\n\n this.unsubscribers.push(\n this.events.onPattern('subagent.ctx_pct', (_e, payload) => {\n const p = payload as { subagentId?: string; load?: number } | undefined;\n if (!p?.subagentId) return;\n const entry = touch(p.subagentId);\n if (typeof p.load === 'number') entry.ctxPct = clampPct(Math.round(p.load * 100));\n this.flush();\n }),\n );\n\n this.unsubscribers.push(\n this.events.onPattern('subagent.task_started', (_e, payload) => {\n const p = payload as { subagentId?: string } | undefined;\n if (!p?.subagentId) return;\n const entry = touch(p.subagentId);\n entry.status = 'running';\n if (!entry.startedAt) entry.startedAt = new Date().toISOString();\n entry.iterations++;\n this.flush();\n }),\n );\n\n this.unsubscribers.push(\n this.events.onPattern('subagent.tool_executed', (_e, payload) => {\n const p = payload as { subagentId?: string; name?: string } | undefined;\n if (!p?.subagentId) return;\n const entry = touch(p.subagentId);\n entry.status = 'running';\n if (!entry.startedAt) entry.startedAt = new Date().toISOString();\n entry.currentTool = p.name;\n entry.toolCalls++;\n this.flush();\n }),\n );\n\n this.unsubscribers.push(\n this.events.onPattern('subagent.iteration_summary', (_e, payload) => {\n const p = payload as\n | {\n subagentId?: string;\n iteration?: number;\n toolCalls?: number;\n currentTool?: string;\n costUsd?: number;\n partialText?: string;\n }\n | undefined;\n if (!p?.subagentId) return;\n const entry = touch(p.subagentId);\n entry.status = 'running';\n if (!entry.startedAt) entry.startedAt = new Date().toISOString();\n if (typeof p.iteration === 'number') entry.iterations = p.iteration;\n if (typeof p.toolCalls === 'number') entry.toolCalls = p.toolCalls;\n if (typeof p.costUsd === 'number') entry.costUsd = p.costUsd;\n if (p.currentTool) entry.currentTool = p.currentTool;\n // Live streamed tail of THIS subagent's current response (the runner\n // already accumulates it) — capped to the same budget as the leader.\n if (typeof p.partialText === 'string') {\n entry.partialText =\n p.partialText.length > PARTIAL_TEXT_CAP\n ? p.partialText.slice(p.partialText.length - PARTIAL_TEXT_CAP)\n : p.partialText;\n }\n this.flush();\n }),\n );\n\n this.unsubscribers.push(\n this.events.onPattern('subagent.task_completed', (_e, payload) => {\n const p = payload as\n | { subagentId?: string; status?: string; iterations?: number; toolCalls?: number }\n | undefined;\n if (!p?.subagentId) return;\n // Only update an agent we already know — a completion for an unseen\n // agent isn't worth materialising.\n const entry = this.agents.get(p.subagentId);\n if (!entry) return;\n entry.status = p.status === 'failed' || p.status === 'timeout' ? 'error' : 'idle';\n entry.currentTool = undefined;\n entry.partialText = undefined;\n if (typeof p.iterations === 'number') entry.iterations = p.iterations;\n if (typeof p.toolCalls === 'number') entry.toolCalls = p.toolCalls;\n entry.lastActivityAt = new Date().toISOString();\n this.flush();\n }),\n );\n\n this.unsubscribers.push(\n this.events.onPattern('subagent.stopped', (_e, payload) => {\n const p = payload as { subagentId?: string } | undefined;\n if (!p?.subagentId) return;\n if (this.agents.delete(p.subagentId)) this.flush();\n }),\n );\n\n // Reap finished subagents so the fleet view doesn't fill with dead/idle\n // desks. The leader is synthesised in flush() (never in `this.agents`), so\n // it is never reaped — it represents the live session.\n this.sweepTimer = setInterval(() => this.sweep(), AGENT_SWEEP_INTERVAL_MS);\n if (typeof this.sweepTimer.unref === 'function') this.sweepTimer.unref();\n }\n\n stop(): void {\n for (const unsub of this.unsubscribers) {\n try { unsub(); } catch { /* ignore */ }\n }\n this.unsubscribers = [];\n if (this.sweepTimer) {\n clearInterval(this.sweepTimer);\n this.sweepTimer = null;\n }\n if (this.partialTimer) {\n clearTimeout(this.partialTimer);\n this.partialTimer = null;\n }\n }\n\n /**\n * Coalesce streamed-text flushes: at most one registry write per\n * {@link PARTIAL_FLUSH_THROTTLE_MS} while text streams in, so per-token\n * deltas never thrash the cross-process registry file.\n */\n private schedulePartialFlush(): void {\n if (this.partialTimer) return;\n this.partialTimer = setTimeout(() => {\n this.partialTimer = null;\n this.flush();\n }, PARTIAL_FLUSH_THROTTLE_MS);\n if (typeof this.partialTimer.unref === 'function') this.partialTimer.unref();\n }\n\n /**\n * Remove subagents that have been finished (idle/error) for longer than\n * {@link AGENT_REAP_MS}. Running / streaming / waiting_user agents are kept\n * regardless of age — only *not-working* agents are reaped.\n */\n private sweep(): void {\n const now = Date.now();\n let removed = false;\n for (const [id, a] of this.agents) {\n const finished = a.status !== 'running' && a.status !== 'streaming' && a.status !== 'waiting_user';\n const age = now - Date.parse(a.lastActivityAt);\n if (finished && Number.isFinite(age) && age > AGENT_REAP_MS) {\n this.agents.delete(id);\n removed = true;\n }\n }\n if (removed) this.flush();\n }\n\n private flush(): void {\n const leaderEntry: AgentEntry = {\n id: 'leader',\n name: this.leaderName,\n startedAt: this.leaderStartedAt,\n status: this.leaderStatus,\n currentTool: this.leaderCurrentTool,\n iterations: this.leaderIterations,\n toolCalls: this.leaderToolCalls,\n costUsd: this.leaderCostUsd,\n tokensIn: this.leaderTokensIn,\n tokensOut: this.leaderTokensOut,\n ctxPct: this.leaderCtxPct,\n model: this.leaderModel,\n partialText: this.leaderPartialText || undefined,\n lastActivityAt: new Date().toISOString(),\n };\n\n const allAgents = [leaderEntry, ...this.agents.values()];\n this.lastAgents = allAgents;\n // Broadcast the fresh agent list on the local bus so in-process consumers\n // (e.g. the HQ session-telemetry bridge) can build snapshots without\n // re-reading the shared registry file. Best-effort, never throws here.\n try {\n this.events.emit('session.agents_updated', { agents: allAgents });\n } catch {\n /* best-effort */\n }\n // Nudge local WebUIs only AFTER the write settles, so they re-read fresh\n // data. Best-effort — never let a notifier failure surface here.\n this.registry\n .updateAgents(allAgents)\n .then(() => {\n try {\n this.onUpdate?.();\n } catch {\n /* best-effort */\n }\n })\n .catch(() => undefined);\n }\n\n private markLeaderStarted(startedAt?: string): void {\n if (\n this.leaderStartedAt &&\n (this.leaderStatus === 'running' ||\n this.leaderStatus === 'streaming' ||\n this.leaderStatus === 'waiting_user')\n ) {\n return;\n }\n this.leaderStartedAt = startedAt ?? new Date().toISOString();\n }\n\n private captureLeaderContext(ctx: unknown): void {\n if (typeof ctx !== 'object' || ctx === null) return;\n const c = ctx as {\n model?: unknown;\n lastRequestTokens?: unknown;\n meta?: Record<string, unknown> | undefined;\n provider?: { capabilities?: { maxContext?: unknown } | undefined } | undefined;\n };\n if (typeof c.model === 'string' && c.model.length > 0) this.leaderModel = c.model;\n\n const metaLimit = c.meta?.['effectiveMaxContext'];\n const providerMax = c.provider?.capabilities?.maxContext;\n const maxContext =\n typeof metaLimit === 'number' && metaLimit > 0\n ? metaLimit\n : typeof providerMax === 'number' && providerMax > 0\n ? providerMax\n : undefined;\n if (\n typeof c.lastRequestTokens === 'number' &&\n c.lastRequestTokens > 0 &&\n maxContext !== undefined\n ) {\n this.leaderCtxPct = clampPct(Math.round((c.lastRequestTokens / maxContext) * 100));\n }\n }\n}\n","/**\n * FleetNotifier — push-on-write nudge to local WebUI servers.\n *\n * The cross-process source of truth is the file-based SessionRegistry, which\n * every WebUI server already watches (`fs.watch`, ~150ms) and polls (5s). This\n * notifier is a best-effort *latency* optimisation on top: after a process\n * writes its session/agent status to the registry, it sends a tiny\n * fire-and-forget `POST /api/fleet/ping` to every WebUI running against the\n * same project (discovered from `~/.wrongstack/webui-instances.json`). The\n * WebUI responds by re-broadcasting the (already-fresh) registry immediately —\n * so a TUI/REPL agent's activity reaches the Fleet HQ map in ~milliseconds\n * instead of waiting on the watch/poll.\n *\n * Design notes:\n * - **Never the source of truth.** If no WebUI is running, the file system +\n * watch/poll still carry everything. Every failure here is swallowed.\n * - **Coalesced.** Bursts of events (tool calls, deltas) collapse into one POST\n * per ~50ms so we never hammer the WebUI per token.\n * - **Discovery cached** for a couple seconds to avoid a disk read per event.\n * - **Loopback only / self-excluded.** Targets the local instances file; a\n * `0.0.0.0`/`::` bind is dialled on `127.0.0.1`, and the caller's own pid is\n * skipped so a WebUI never pings itself.\n *\n * @module fleet-notifier\n */\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\nconst INSTANCES_FILE = 'webui-instances.json';\nconst DISCOVERY_TTL_MS = 2_500;\nconst COALESCE_MS = 50;\nconst POST_TIMEOUT_MS = 500;\n\ninterface InstanceRecordLike {\n pid: number;\n httpPort: number;\n host: string;\n projectRoot: string;\n}\n\nfunction pidAlive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid <= 0) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch (err) {\n return (err as NodeJS.ErrnoException).code !== 'ESRCH';\n }\n}\n\n/** Normalise a project root for cross-process comparison (case-insensitive on Windows). */\nfunction normRoot(root: string): string {\n const resolved = path.resolve(root);\n return process.platform === 'win32' ? resolved.toLowerCase() : resolved;\n}\n\nexport interface FleetNotifierOptions {\n /** WrongStack global dir (`~/.wrongstack`) holding `webui-instances.json`. */\n baseDir: string;\n /** This process's project root — only WebUIs on the same project are pinged. */\n projectRoot: string;\n /** This process's pid, so a WebUI never pings itself. */\n selfPid?: number | undefined;\n /** Injectable POST for tests. Defaults to a timed `fetch`. */\n post?: ((url: string) => Promise<void>) | undefined;\n}\n\nexport class FleetNotifier {\n private readonly baseDir: string;\n private readonly projectRoot: string;\n private readonly selfPid: number;\n private readonly doPost: (url: string) => Promise<void>;\n\n private cache: { at: number; urls: string[] } | null = null;\n private timer: ReturnType<typeof setTimeout> | null = null;\n private disposed = false;\n\n constructor(opts: FleetNotifierOptions) {\n this.baseDir = opts.baseDir;\n this.projectRoot = normRoot(opts.projectRoot);\n this.selfPid = opts.selfPid ?? process.pid;\n this.doPost = opts.post ?? defaultPost;\n }\n\n /** Coalesced, best-effort nudge. Safe to call on every status change. */\n notify(): void {\n if (this.disposed || this.timer) return;\n this.timer = setTimeout(() => {\n this.timer = null;\n void this.flush();\n }, COALESCE_MS);\n if (typeof this.timer.unref === 'function') this.timer.unref();\n }\n\n /** Resolve same-project WebUI ping URLs (cached briefly). Exposed for tests. */\n async endpoints(): Promise<string[]> {\n const now = Date.now();\n if (this.cache && now - this.cache.at < DISCOVERY_TTL_MS) return this.cache.urls;\n const urls = await this.discover();\n this.cache = { at: now, urls };\n return urls;\n }\n\n dispose(): void {\n this.disposed = true;\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n }\n\n private async flush(): Promise<void> {\n const urls = await this.endpoints();\n await Promise.all(urls.map((u) => this.doPost(u).catch(() => undefined)));\n }\n\n private async discover(): Promise<string[]> {\n try {\n const raw = await fs.readFile(path.join(this.baseDir, INSTANCES_FILE), 'utf8');\n const data = JSON.parse(raw) as { instances?: InstanceRecordLike[] };\n const list = Array.isArray(data?.instances) ? data.instances : [];\n return list\n .filter((i) => i && typeof i.httpPort === 'number')\n .filter((i) => i.pid !== this.selfPid)\n .filter((i) => normRoot(i.projectRoot) === this.projectRoot)\n .filter((i) => pidAlive(i.pid))\n .map((i) => {\n const host = i.host === '0.0.0.0' || i.host === '::' || !i.host ? '127.0.0.1' : i.host;\n return `http://${host}:${i.httpPort}/api/fleet/ping`;\n });\n } catch {\n // Missing/corrupt instances file → no WebUIs to notify.\n return [];\n }\n }\n}\n\nasync function defaultPost(url: string): Promise<void> {\n await fetch(url, {\n method: 'POST',\n signal: AbortSignal.timeout(POST_TIMEOUT_MS),\n });\n}\n","import { expectDefined } from '../utils/expect-defined.js';\r\nimport { toErrorMessage } from '../utils/error.js';\nimport * as fsp from 'node:fs/promises';\r\nimport * as path from 'node:path';\r\nimport type { CheckpointInfo, RewindResult, RewindResultExtended, SessionRewinder } from '../types/session-rewinder.js';\r\nimport type { SessionEvent, FileSnapshot } from '../types/session.js';\r\nimport { atomicWrite } from '../utils/atomic-write.js';\r\nimport { SessionError, ERROR_CODES } from '../types/errors.js';\r\n\r\nexport interface SessionRewinderOptions {\r\n sessionsDir: string;\r\n /** The project root directory; used to validate rewind targets stay inside it. */\r\n projectRoot: string;\r\n}\r\n\r\n/**\r\n * Rewind engine that reads session JSONL files and reverts file system\r\n * changes to any previous checkpoint.\r\n */\r\nexport class DefaultSessionRewinder implements SessionRewinder {\r\n constructor(private readonly sessionsDir: string, private readonly projectRoot: string) {}\r\n\r\n async listCheckpoints(sessionId: string): Promise<CheckpointInfo[]> {\r\n const file = path.join(this.sessionsDir, `${sessionId}.jsonl`);\r\n const raw = await fsp.readFile(file, 'utf8');\r\n const events = parseEvents(raw);\r\n\r\n // Build a map of promptIndex -> file snapshot count\r\n const fileCountMap = new Map<number, number>();\r\n for (const event of events) {\r\n if (event.type === 'file_snapshot') {\r\n const e = event as { promptIndex: number; files: FileSnapshot[] };\r\n fileCountMap.set(e.promptIndex, (fileCountMap.get(e.promptIndex) ?? 0) + e.files.length);\r\n }\r\n }\r\n\r\n const checkpoints: CheckpointInfo[] = [];\r\n for (const event of events) {\r\n if (event.type === 'checkpoint') {\r\n const e = event as { promptIndex: number; promptPreview: string; ts: string };\r\n checkpoints.push({\r\n promptIndex: e.promptIndex,\r\n promptPreview: e.promptPreview,\r\n ts: e.ts,\r\n fileCount: fileCountMap.get(e.promptIndex) ?? 0,\r\n });\r\n }\r\n }\r\n\r\n return checkpoints;\r\n }\r\n\r\n async rewindToCheckpoint(\r\n sessionId: string,\r\n checkpointIndex: number,\r\n ): Promise<RewindResultExtended> {\r\n const file = path.join(this.sessionsDir, `${sessionId}.jsonl`);\r\n const raw = await fsp.readFile(file, 'utf8');\r\n const events = parseEvents(raw);\r\n\r\n let targetIdx = -1;\r\n for (let i = 0; i < events.length; i++) {\r\n const event = expectDefined(events[i]);\r\n if (event.type === 'checkpoint') {\r\n const checkpointEvent = event as { promptIndex: number };\r\n if (checkpointEvent.promptIndex === checkpointIndex) {\r\n targetIdx = i;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (targetIdx === -1) {\r\n throw new SessionError({\r\n message: `Checkpoint ${checkpointIndex} not found`,\r\n code: ERROR_CODES.SESSION_NOT_FOUND,\r\n context: { checkpointIndex },\r\n });\r\n }\r\n\r\n const snapshotsToRevert: Array<{ promptIndex: number; files: FileSnapshot[] }> = [];\r\n for (let i = targetIdx + 1; i < events.length; i++) {\r\n const event = expectDefined(events[i]);\r\n if (event.type === 'checkpoint') {\r\n break;\r\n }\r\n if (event.type === 'file_snapshot') {\r\n const snapshotEvent = event as { promptIndex: number; files: FileSnapshot[] };\r\n if (snapshotEvent.promptIndex >= checkpointIndex) {\r\n snapshotsToRevert.push({ promptIndex: snapshotEvent.promptIndex, files: snapshotEvent.files });\r\n }\r\n }\r\n }\r\n\r\n const result = await revertSnapshots(snapshotsToRevert, this.projectRoot);\r\n const removedEvents = events.length - targetIdx - 1;\r\n return { ...result, toPromptIndex: checkpointIndex, removedEvents };\r\n }\r\n\r\n async rewindLastN(sessionId: string, n: number): Promise<RewindResultExtended> {\r\n const file = path.join(this.sessionsDir, `${sessionId}.jsonl`);\r\n const raw = await fsp.readFile(file, 'utf8');\r\n const events = parseEvents(raw);\r\n\r\n const checkpoints: Array<{ promptIndex: number; ts: string }> = [];\r\n for (const event of events) {\r\n if (event.type === 'checkpoint') {\r\n checkpoints.push({ promptIndex: event.promptIndex, ts: event.ts });\r\n }\r\n }\r\n\r\n if (checkpoints.length === 0) {\r\n return { revertedFiles: [], errors: [], toPromptIndex: 0, removedEvents: 0 };\r\n }\r\n\r\n checkpoints.sort((a, b) => b.promptIndex - a.promptIndex);\r\n const targetIndex = checkpoints[n]?.promptIndex ?? 0;\r\n\r\n const snapshotsToRevert: Array<{ promptIndex: number; files: FileSnapshot[] }> = [];\r\n let shouldRevert = false;\r\n\r\n for (const event of events) {\r\n if (event.type === 'checkpoint' && event.promptIndex === targetIndex) {\r\n shouldRevert = true;\r\n continue;\r\n }\r\n if (shouldRevert && event.type === 'file_snapshot') {\r\n snapshotsToRevert.push({ promptIndex: event.promptIndex, files: event.files });\r\n }\r\n }\r\n\r\n const result = await revertSnapshots(snapshotsToRevert.reverse(), this.projectRoot);\r\n return { ...result, toPromptIndex: targetIndex, removedEvents: snapshotsToRevert.length };\r\n }\r\n\r\n async rewindToStart(sessionId: string): Promise<RewindResultExtended> {\r\n const file = path.join(this.sessionsDir, `${sessionId}.jsonl`);\r\n const raw = await fsp.readFile(file, 'utf8');\r\n const events = parseEvents(raw);\r\n\r\n const allSnapshots: Array<{ promptIndex: number; files: FileSnapshot[] }> = [];\r\n for (const event of events) {\r\n if (event.type === 'file_snapshot') {\r\n allSnapshots.push({ promptIndex: event.promptIndex, files: event.files });\r\n }\r\n }\r\n\r\n if (allSnapshots.length === 0) {\r\n return { revertedFiles: [], errors: [], toPromptIndex: 0, removedEvents: 0 };\r\n }\r\n\r\n const result = await revertSnapshots(allSnapshots.reverse(), this.projectRoot);\r\n return { ...result, toPromptIndex: 0, removedEvents: allSnapshots.length };\r\n }\r\n}\r\n\r\nfunction parseEvents(raw: string): SessionEvent[] {\r\n const lines = raw.split('\\n').filter((l) => l.trim());\r\n const events: SessionEvent[] = [];\r\n\r\n for (const line of lines) {\r\n try {\r\n const parsed = JSON.parse(line);\r\n if (\r\n parsed !== null &&\r\n typeof parsed === 'object' &&\r\n typeof (parsed as { type?: unknown | undefined }).type === 'string' &&\r\n typeof (parsed as { ts?: unknown | undefined }).ts === 'string'\r\n ) {\r\n events.push(parsed as SessionEvent);\r\n }\r\n } catch {\r\n // skip malformed\r\n }\r\n }\r\n\r\n return events;\r\n}\r\n\r\nasync function revertSnapshots(\r\n snapshots: Array<{ promptIndex: number; files: FileSnapshot[] }>,\r\n projectRoot: string,\r\n): Promise<RewindResult> {\r\n const revertedFiles: string[] = [];\r\n const errors: string[] = [];\r\n\r\n for (const snapshot of snapshots) {\r\n for (const file of snapshot.files) {\r\n try {\r\n // Guard: ensure the target path resolves inside the project root.\r\n // Without this, a maliciously recorded path (e.g., via path traversal\r\n // in a tool call that wasn't caught) could cause rewind to write\r\n // to arbitrary locations.\r\n const absPath = path.resolve(file.path);\r\n const root = path.resolve(projectRoot);\r\n const rel = path.relative(root, absPath);\r\n if (rel.startsWith('..') || path.isAbsolute(rel)) {\r\n errors.push(`${file.path}: path resolves outside project root — skipping`);\r\n continue;\r\n }\r\n\r\n if (file.action === 'deleted') {\r\n // File was deleted — restore it from before\r\n if (file.before !== null) {\r\n // atomicWrite: torn restore would leave the user with a frankenstein file.\r\n await atomicWrite(file.path, file.before, { mode: 0o644 });\r\n revertedFiles.push(file.path);\r\n }\r\n } else if (file.action === 'created') {\r\n // File was created — delete it\r\n await fsp.unlink(file.path);\r\n revertedFiles.push(file.path);\r\n } else if (file.action === 'modified') {\r\n // File was modified — restore before content\r\n if (file.before !== null) {\r\n // atomicWrite: torn restore would leave the user with a frankenstein file.\r\n await atomicWrite(file.path, file.before, { mode: 0o644 });\r\n revertedFiles.push(file.path);\r\n }\r\n }\r\n } catch (err) {\r\n errors.push(`${file.path}: ${toErrorMessage(err)}`);\r\n }\r\n }\r\n }\r\n\r\n return { revertedFiles, errors };\r\n}","import * as fsp from 'node:fs/promises';\nimport type { EventBus } from '../kernel/events.js';\nimport type { TodoItem } from '../core/context.js';\nimport type { ConversationState } from '../core/conversation-state.js';\nimport { atomicWrite } from '../utils/atomic-write.js';\nimport { toErrorMessage } from '../utils/error.js';\n\n/**\n * On-disk checkpoint for `ctx.todos`. Written atomically every time the\n * todo list changes, read once on session resume. This is the missing\n * piece that lets `wstack resume <id>` rehydrate where the previous run\n * stopped instead of starting with an empty board.\n *\n * Schema is intentionally small — a single JSON object so a future\n * format bump is easy. The `version` field is the only contract; the\n * shape under `todos` mirrors `TodoItem` so reading is a straight assign.\n */\nexport interface TodosCheckpointFile {\n version: 1;\n sessionId: string;\n updatedAt: string;\n todos: TodoItem[];\n}\n\nexport type TodosCheckpointDetach = () => Promise<void>;\n\n/** Read a checkpoint from disk. Returns null when the file doesn't\n * exist or is corrupt — callers treat both cases as \"no prior state\".\n */\nexport async function loadTodosCheckpoint(\n filePath: string,\n events?: EventBus,\n traceId?: string,\n): Promise<TodoItem[] | null> {\n const t0 = Date.now();\n let raw: string;\n try {\n raw = await fsp.readFile(filePath, 'utf8');\n } catch (err) {\n events?.emit('storage.error', {\n sessionId: traceId ?? '~boot~',\n store: 'todos',\n filePath,\n operation: 'load',\n outcome: 'failure',\n error: toErrorMessage(err),\n recoverable: true,\n });\n return null;\n }\n try {\n const parsed = JSON.parse(raw) as TodosCheckpointFile;\n if (parsed?.version !== 1 || !Array.isArray(parsed.todos)) {\n events?.emit('storage.read', {\n sessionId: traceId ?? '~boot~',\n store: 'todos',\n filePath,\n operation: 'load',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'invalid_schema',\n ...(traceId !== undefined && { traceId }),\n });\n return null;\n }\n events?.emit('storage.read', {\n sessionId: traceId ?? '~boot~',\n store: 'todos',\n filePath,\n operation: 'load',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(traceId !== undefined && { traceId }),\n });\n return parsed.todos.filter(\n (t): t is TodoItem =>\n !!t &&\n typeof t.id === 'string' &&\n typeof t.content === 'string' &&\n typeof t.status === 'string' &&\n (t.activeForm === undefined || typeof t.activeForm === 'string'),\n );\n } catch {\n events?.emit('storage.read', {\n sessionId: traceId ?? '~boot~',\n store: 'todos',\n filePath,\n operation: 'load',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'parse_failed',\n ...(traceId !== undefined && { traceId }),\n });\n return null;\n }\n}\n\n/** Write the checkpoint atomically. Best-effort: a write failure is\n * logged but does not throw — losing one checkpoint shouldn't bring\n * down the agent run.\n */\nexport async function saveTodosCheckpoint(\n filePath: string,\n sessionId: string,\n todos: readonly TodoItem[],\n events?: EventBus,\n traceId?: string,\n): Promise<void> {\n const t0 = Date.now();\n const payload: TodosCheckpointFile = {\n version: 1,\n sessionId,\n updatedAt: new Date().toISOString(),\n todos: [...todos],\n };\n try {\n await atomicWrite(filePath, JSON.stringify(payload, null, 2), { mode: 0o600 });\n events?.emit('storage.write', {\n sessionId: traceId ?? sessionId,\n store: 'todos',\n filePath,\n operation: 'save',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(traceId !== undefined && { traceId }),\n });\n } catch (err) {\n events?.emit('storage.error', {\n sessionId: traceId ?? sessionId,\n store: 'todos',\n filePath,\n operation: 'save',\n outcome: 'failure',\n error: toErrorMessage(err),\n recoverable: false,\n });\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'todos_checkpoint.save_failed',\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n }\n}\n\n/**\n * Subscribe a `ConversationState` so every `todos_replaced` mutation\n * triggers an atomic write to disk. Returns the unsubscribe function.\n *\n * Writes are debounced by 150ms so a flurry of edits (e.g. the LLM\n * marking three items done in the same tool call) coalesces into one\n * disk hit.\n */\nexport function attachTodosCheckpoint(\n state: ConversationState,\n filePath: string,\n sessionId: string,\n events?: EventBus,\n traceId?: string,\n): TodosCheckpointDetach {\n let timer: NodeJS.Timeout | null = null;\n let pending: readonly TodoItem[] | null = null;\n let writeChain: Promise<void> = Promise.resolve();\n\n const enqueueWrite = (todos: readonly TodoItem[]) => {\n writeChain = writeChain\n .then(() => saveTodosCheckpoint(filePath, sessionId, todos, events, traceId))\n /* v8 ignore start -- defensive: saveTodosCheckpoint swallows its own errors and never rejects */\n .catch((err) => {\n // Log and keep the chain alive — a failed write must not\n // poison the chain and silently stop all subsequent writes.\n const msg = toErrorMessage(err);\n console.error(JSON.stringify({\n level: 'error',\n event: 'todos_checkpoint.write_chain_failed',\n sessionId,\n message: msg,\n timestamp: new Date().toISOString(),\n }));\n });\n /* v8 ignore stop */\n return writeChain;\n };\n\n const flush = () => {\n timer = null;\n if (pending) {\n const todos = pending;\n pending = null;\n return enqueueWrite(todos);\n }\n /* v8 ignore next -- defensive: flush is only invoked when a change is pending */\n return writeChain;\n };\n\n const unsubscribe = state.onChange((change) => {\n if (change.kind !== 'todos_replaced') return;\n pending = change.todos;\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n void flush();\n }, 150);\n });\n return async () => {\n unsubscribe();\n if (timer) {\n clearTimeout(timer);\n // Flush any pending write before detach so callers can safely\n // unsubscribe at shutdown without losing the last update.\n await flush();\n } else {\n await writeChain;\n }\n };\n}\n","import * as fsp from 'node:fs/promises';\nimport { randomUUID } from 'node:crypto';\nimport type { EventBus } from '../kernel/events.js';\nimport type { ConversationState } from '../core/conversation-state.js';\nimport { atomicWrite, withFileLock } from '../utils/atomic-write.js';\nimport { toErrorMessage } from '../utils/error.js';\n\n/**\n * Plan items are the strategic counterpart to todos. Where `ctx.todos`\n * is the moment-to-moment task board the LLM mutates per-turn, a plan\n * captures the higher-level approach — the steps the user (or LLM)\n * laid out before any work began.\n *\n * Plans persist by default (per session) so a resumed session can show\n * \"you were on step 3 of 5\". Todos are derived/transient. Both can\n * coexist: think roadmap (plan) vs. sprint board (todos).\n */\nexport interface PlanItem {\n id: string;\n title: string;\n /** Optional longer-form context or rationale. */\n details?: string | undefined;\n status: 'open' | 'in_progress' | 'done';\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface PlanFile {\n version: 1;\n sessionId: string;\n title?: string | undefined;\n updatedAt: string;\n items: PlanItem[];\n}\n\nexport async function loadPlan(filePath: string, events?: EventBus): Promise<PlanFile | null> {\n const t0 = Date.now();\n let raw: string;\n try {\n raw = await fsp.readFile(filePath, 'utf8');\n } catch (err) {\n events?.emit('storage.error', {\n sessionId: '~boot~',\n store: 'plan',\n filePath,\n operation: 'load',\n error: toErrorMessage(err),\n recoverable: true,\n });\n return null;\n }\n try {\n const parsed = JSON.parse(raw) as PlanFile;\n if (parsed?.version !== 1 || !Array.isArray(parsed.items)) {\n events?.emit('storage.read', {\n sessionId: '~boot~',\n store: 'plan',\n filePath,\n operation: 'load',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'invalid_schema',\n });\n return null;\n }\n events?.emit('storage.read', {\n sessionId: '~boot~',\n store: 'plan',\n filePath,\n operation: 'load',\n outcome: 'success',\n durationMs: Date.now() - t0,\n });\n return parsed;\n } catch {\n events?.emit('storage.read', {\n sessionId: '~boot~',\n store: 'plan',\n filePath,\n operation: 'load',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'parse_failed',\n });\n return null;\n }\n}\n\n/**\n * Persist a plan. Returns `true` on success, `false` if the write failed\n * (still emits `storage.error` + warns — it does NOT throw, so callers that\n * treat a lost plan-save as non-fatal keep working). `mutatePlan` inspects the\n * result and throws so the plan TOOL can report `ok:false` instead of falsely\n * claiming the plan was persisted.\n */\nexport async function savePlan(filePath: string, plan: PlanFile, events?: EventBus): Promise<boolean> {\n const t0 = Date.now();\n try {\n await atomicWrite(filePath, JSON.stringify(plan, null, 2), { mode: 0o600 });\n events?.emit('storage.write', {\n sessionId: '~boot~',\n store: 'plan',\n filePath,\n operation: 'save',\n outcome: 'success',\n durationMs: Date.now() - t0,\n });\n return true;\n } catch (err) {\n events?.emit('storage.error', {\n sessionId: '~boot~',\n store: 'plan',\n filePath,\n operation: 'save',\n error: toErrorMessage(err),\n recoverable: false,\n });\n console.warn(\n '[plan-store] save failed:',\n toErrorMessage(err),\n );\n return false;\n }\n}\n\n/** Create a new PlanFile when none exists on disk. */\nexport function emptyPlan(sessionId: string, title?: string): PlanFile {\n return {\n version: 1,\n sessionId,\n title,\n updatedAt: new Date().toISOString(),\n items: [],\n };\n}\n\nexport function addPlanItem(\n plan: PlanFile,\n title: string,\n details?: string | undefined,\n): { plan: PlanFile; item: PlanItem } {\n const now = new Date().toISOString();\n const item: PlanItem = {\n id: `plan_${Date.now()}_${randomUUID().slice(0, 6)}`,\n title,\n details,\n status: 'open',\n createdAt: now,\n updatedAt: now,\n };\n return {\n plan: { ...plan, items: [...plan.items, item], updatedAt: now },\n item,\n };\n}\n\nexport function removePlanItem(plan: PlanFile, idOrIndex: string): PlanFile {\n const idx = matchIndex(plan, idOrIndex);\n if (idx === -1) return plan;\n return {\n ...plan,\n items: plan.items.filter((_, i) => i !== idx),\n updatedAt: new Date().toISOString(),\n };\n}\n\nexport function setPlanItemStatus(\n plan: PlanFile,\n idOrIndex: string,\n status: PlanItem['status'],\n): PlanFile {\n const idx = matchIndex(plan, idOrIndex);\n if (idx === -1) return plan;\n const now = new Date().toISOString();\n const items = plan.items.map((it, i) =>\n i === idx ? { ...it, status, updatedAt: now } : it,\n );\n return { ...plan, items, updatedAt: now };\n}\n\nexport function clearPlan(plan: PlanFile): PlanFile {\n return { ...plan, items: [], updatedAt: new Date().toISOString() };\n}\n\n/** Render the plan as a short markdown-ish string suitable for slash output. */\nexport function formatPlan(plan: PlanFile): string {\n if (plan.items.length === 0) return 'Plan is empty.';\n const lines: string[] = [];\n if (plan.title) lines.push(`# ${plan.title}`);\n plan.items.forEach((it, i) => {\n const mark = it.status === 'done' ? '[x]' : it.status === 'in_progress' ? '[~]' : '[ ]';\n lines.push(`${i + 1}. ${mark} ${it.title}`);\n if (it.details) {\n for (const line of it.details.split('\\n')) lines.push(` ${line}`);\n }\n });\n return lines.join('\\n');\n}\n\nfunction matchIndex(plan: PlanFile, idOrIndex: string): number {\n const asNum = Number.parseInt(idOrIndex, 10);\n if (!Number.isNaN(asNum) && asNum >= 1 && asNum <= plan.items.length) return asNum - 1;\n const byId = plan.items.findIndex((it) => it.id === idOrIndex);\n if (byId !== -1) return byId;\n const lower = idOrIndex.toLowerCase();\n return plan.items.findIndex((it) => it.title.toLowerCase().includes(lower));\n}\n\n/**\n * Promote a plan item to a set of todo items.\n * The plan item is marked 'in_progress' (if not already done) and its\n * title + details become the first todo; additional subtasks are appended.\n * Returns the derived todo list so the caller can pass it to `todoTool`\n * or `ctx.state.replaceTodos()`.\n */\nexport function deriveTodosFromPlanItem(\n plan: PlanFile,\n idOrIndex: string,\n subtasks?: string[] | undefined,\n): { plan: PlanFile; todos: Array<{ id: string; content: string; status: 'pending' | 'in_progress' | 'completed'; activeForm?: string | undefined; promotedFromPlan?: string | undefined }> } | null {\n const idx = matchIndex(plan, idOrIndex);\n if (idx === -1) return null;\n\n const item = plan.items[idx];\n /* v8 ignore next -- defensive: matchIndex returns a valid in-range index or -1 (handled above) */\n if (!item) return null;\n\n // Mark the plan item in_progress if it wasn't already done\n let updatedPlan = plan;\n if (item.status !== 'done') {\n updatedPlan = setPlanItemStatus(plan, idOrIndex, 'in_progress');\n }\n\n const todos: Array<{ id: string; content: string; status: 'pending' | 'in_progress' | 'completed'; activeForm?: string | undefined; promotedFromPlan?: string | undefined }> = [];\n\n // First todo from the plan item itself\n todos.push({\n id: `todo_${Date.now()}_plan`,\n content: item.title,\n status: 'in_progress',\n activeForm: item.title,\n promotedFromPlan: item.id,\n });\n\n // Optional subtasks\n if (subtasks && subtasks.length > 0) {\n for (const st of subtasks) {\n todos.push({\n id: `todo_${Date.now()}_${randomUUID().slice(0, 6)}`,\n content: st,\n status: 'pending',\n promotedFromPlan: item.id,\n });\n }\n }\n\n return { plan: updatedPlan, todos };\n}\n\n/**\n * Load, modify, and save the plan file under a file-level lock.\n * Prevents races from parallel tool invocations (e.g. batch_tool_use).\n */\nexport async function mutatePlan(\n filePath: string,\n sessionId: string,\n fn: (plan: PlanFile) => PlanFile | Promise<PlanFile>,\n): Promise<PlanFile> {\n return withFileLock(filePath, async () => {\n const plan = (await loadPlan(filePath)) ?? emptyPlan(sessionId);\n const updated = await fn(plan);\n const persisted = await savePlan(filePath, updated);\n if (!persisted) {\n throw new Error(`Failed to persist plan to ${filePath} — the change was NOT saved.`);\n }\n return updated;\n });\n}\n\n/**\n * Optional: attach a state-listener so meta operations (storing a plan\n * id on ctx.meta) trigger a save. Currently a stub — plans don't live\n * on Context, but this keeps the API surface symmetric with the todos\n * checkpoint so future refactors can flip plans into Context if needed.\n */\nexport function attachPlanCheckpoint(\n _state: ConversationState,\n _filePath: string,\n _sessionId: string,\n): () => void {\n return () => undefined;\n}\n","/**\n * Plan templates — pre-defined plan skeletons for common workflows.\n *\n * Templates are stored in-memory (no disk I/O). Users instantiate them\n * via `/plan template use <name>` or `planTool(action: 'template_use')`.\n * Each template is a function that returns an array of item titles, so\n * dynamic content (dates, project names) can be injected later.\n */\n\nexport interface PlanTemplate {\n name: string;\n description: string;\n category: 'development' | 'release' | 'maintenance' | 'infrastructure';\n items: Array<{\n title: string;\n details?: string | undefined;\n }>;\n}\n\nconst templates: Record<string, PlanTemplate> = {\n 'new-feature': {\n name: 'new-feature',\n description: 'Standard workflow for adding a new feature',\n category: 'development',\n items: [\n { title: 'Write specification / design doc', details: 'Define scope, acceptance criteria, edge cases' },\n { title: 'Set up feature branch', details: 'git checkout -b feature/...' },\n { title: 'Implement core logic', details: 'TDD preferred — write tests first' },\n { title: 'Add unit tests', details: '>= 80% coverage for new code' },\n { title: 'Add integration tests', details: 'End-to-end happy path + error paths' },\n { title: 'Update documentation', details: 'README, API docs, changelog' },\n { title: 'Code review', details: 'Self-review before requesting review' },\n { title: 'Merge and deploy', details: 'CI green, tag release' },\n ],\n },\n 'bug-fix': {\n name: 'bug-fix',\n description: 'Systematic approach to fixing bugs',\n category: 'maintenance',\n items: [\n { title: 'Reproduce the bug', details: 'Minimal reproduction case' },\n { title: 'Root cause analysis', details: 'Trace through logs, debugger' },\n { title: 'Write failing test', details: 'Test must fail before fix' },\n { title: 'Implement fix', details: 'Smallest possible change' },\n { title: 'Verify fix', details: 'Test passes, reproduction no longer fails' },\n { title: 'Regression test', details: 'Ensure no related tests broken' },\n { title: 'Document in changelog', details: 'Brief description + issue link' },\n ],\n },\n 'refactor': {\n name: 'refactor',\n description: 'Safe refactoring workflow',\n category: 'maintenance',\n items: [\n { title: 'Identify refactoring target', details: 'Code smell, performance bottleneck, or tech debt' },\n { title: 'Ensure test coverage', details: 'Existing tests must pass before and after' },\n { title: 'Write characterization tests', details: 'Capture current behavior if tests weak' },\n { title: 'Apply refactoring', details: 'Small steps, frequent commits' },\n { title: 'Run full test suite', details: 'All tests must pass' },\n { title: 'Performance check', details: 'Ensure no regression' },\n { title: 'Code review', details: 'Explain the why, not just the what' },\n ],\n },\n 'release': {\n name: 'release',\n description: 'Preparing a new release',\n category: 'release',\n items: [\n { title: 'Version bump', details: 'package.json, lockfiles, tags' },\n { title: 'Update changelog', details: 'All changes since last release' },\n { title: 'Run full test suite', details: 'Unit + integration + e2e' },\n { title: 'Build artifacts', details: 'Docker images, bundles, binaries' },\n { title: 'Staging smoke tests', details: 'Deploy to staging, verify' },\n { title: 'Production deploy', details: 'Blue-green or canary' },\n { title: 'Post-deploy verification', details: 'Health checks, error rates' },\n { title: 'Announce release', details: 'Slack, email, GitHub release notes' },\n ],\n },\n 'security-audit': {\n name: 'security-audit',\n description: 'Security review and hardening',\n category: 'infrastructure',\n items: [\n { title: 'Dependency audit', details: 'npm audit, Snyk, Dependabot alerts' },\n { title: 'Secret scan', details: 'git-secrets, truffleHog, manual review' },\n { title: 'Access control review', details: 'IAM, roles, least privilege' },\n { title: 'Input validation audit', details: 'SQL injection, XSS, path traversal' },\n { title: 'Authentication review', details: 'Session management, MFA, password policy' },\n { title: 'Logging and monitoring', details: 'PII in logs, audit trails' },\n { title: 'Incident response plan', details: 'Runbooks, contacts, escalation' },\n ],\n },\n 'onboarding': {\n name: 'onboarding',\n description: 'New developer onboarding checklist',\n category: 'infrastructure',\n items: [\n { title: 'Repository access', details: 'GitHub/GitLab permissions' },\n { title: 'Local environment setup', details: 'Docker, dependencies, env files' },\n { title: 'Run tests locally', details: 'Verify green suite' },\n { title: 'Read architecture docs', details: 'ADR, README, onboarding guide' },\n { title: 'First commit', details: 'Docs fix or small improvement' },\n { title: 'Pair programming session', details: 'Walk through codebase with buddy' },\n { title: 'Deploy to staging', details: 'Verify CI/CD access' },\n ],\n },\n};\n\nexport function listPlanTemplates(): PlanTemplate[] {\n return Object.values(templates);\n}\n\nexport function getPlanTemplate(name: string): PlanTemplate | undefined {\n return templates[name];\n}\n\nexport function formatPlanTemplates(): string {\n const cats = new Map<PlanTemplate['category'], PlanTemplate[]>();\n for (const t of Object.values(templates)) {\n const arr = cats.get(t.category) ?? [];\n arr.push(t);\n cats.set(t.category, arr);\n }\n\n const lines: string[] = ['Available plan templates:'];\n for (const [cat, items] of cats) {\n lines.push(`\\n${cat}:`);\n for (const t of items) {\n lines.push(` ${t.name.padEnd(18)} — ${t.description}`);\n }\n }\n return lines.join('\\n');\n}\n","import * as fsp from 'node:fs/promises';\nimport type { EventBus } from '../kernel/events.js';\nimport { atomicWrite, withFileLock } from '../utils/atomic-write.js';\nimport { toErrorMessage } from '../utils/error.js';\nimport type { TaskItem } from '../utils/task-format.js';\n\n// ---------------------------------------------------------------------------\n// Task file persistence — one JSON file per session in\n// `<projectSessions>/<sessionId>.tasks.json`.\n//\n// Low-level load/save are exported for read-only consumers. Mutating callers\n// should use `mutateTasks` which wraps the entire read-modify-write cycle\n// under a file-level lock, preventing races from parallel tool invocations.\n// ---------------------------------------------------------------------------\n\nexport interface TaskFile {\n version: 1;\n sessionId: string;\n updatedAt: string;\n tasks: TaskItem[];\n}\n\nexport function emptyTaskFile(sessionId: string): TaskFile {\n return {\n version: 1,\n sessionId,\n updatedAt: new Date().toISOString(),\n tasks: [],\n };\n}\n\n/** Read the task file. Returns null when the file doesn't exist. */\nexport async function loadTasks(\n filePath: string,\n events?: EventBus,\n traceId?: string,\n): Promise<TaskFile | null> {\n const t0 = Date.now();\n let raw: string;\n try {\n raw = await fsp.readFile(filePath, 'utf8');\n } catch (err) {\n events?.emit('storage.error', {\n sessionId: traceId ?? '~boot~',\n store: 'tasks',\n filePath,\n operation: 'load',\n outcome: 'failure',\n error: toErrorMessage(err),\n recoverable: true,\n });\n return null;\n }\n try {\n const parsed = JSON.parse(raw) as TaskFile;\n if (parsed?.version !== 1 || !Array.isArray(parsed.tasks)) {\n events?.emit('storage.read', {\n sessionId: traceId ?? '~boot~',\n store: 'tasks',\n filePath,\n operation: 'load',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'invalid_schema',\n ...(traceId !== undefined && { traceId }),\n });\n return null;\n }\n events?.emit('storage.read', {\n sessionId: traceId ?? '~boot~',\n store: 'tasks',\n filePath,\n operation: 'load',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(traceId !== undefined && { traceId }),\n });\n return parsed;\n } catch {\n events?.emit('storage.read', {\n sessionId: traceId ?? '~boot~',\n store: 'tasks',\n filePath,\n operation: 'load',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'parse_failed',\n ...(traceId !== undefined && { traceId }),\n });\n return null;\n }\n}\n\n/**\n * Write the task file atomically. Prefer `mutateTasks` for read-modify-write\n * cycles — this low-level function does NOT acquire a lock.\n */\n/**\n * Persist the task file. Returns `true` on success, `false` if the write\n * failed (still emits `storage.error` + warns — does NOT throw). `mutateTasks`\n * inspects the result and throws so the task TOOL can report `ok:false`\n * instead of falsely claiming the tasks were saved.\n */\nexport async function saveTasks(\n filePath: string,\n tasks: TaskFile,\n events?: EventBus,\n traceId?: string,\n): Promise<boolean> {\n const t0 = Date.now();\n try {\n tasks.updatedAt = new Date().toISOString();\n await atomicWrite(filePath, JSON.stringify(tasks, null, 2), { mode: 0o600 });\n events?.emit('storage.write', {\n sessionId: traceId ?? '~boot~',\n store: 'tasks',\n filePath,\n operation: 'save',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(traceId !== undefined && { traceId }),\n });\n return true;\n } catch (err) {\n events?.emit('storage.error', {\n sessionId: traceId ?? '~boot~',\n store: 'tasks',\n filePath,\n operation: 'save',\n outcome: 'failure',\n error: toErrorMessage(err),\n recoverable: false,\n ...(traceId !== undefined && { traceId }),\n });\n console.warn(\n '[task-store] save failed:',\n toErrorMessage(err),\n );\n return false;\n }\n}\n\n/**\n * Load, modify, and save the task file under a file-level lock.\n * `fn` receives the current TaskFile (or a fresh empty one) and must\n * return the mutated TaskFile (mutating in-place is fine — the returned\n * reference is what gets saved).\n *\n * This is the primary API for any code path that reads *and then writes*\n * the task file — it prevents races from parallel `batch_tool_use` calls.\n */\nexport async function mutateTasks(\n filePath: string,\n sessionId: string,\n fn: (file: TaskFile) => TaskFile | Promise<TaskFile>,\n events?: EventBus,\n traceId?: string,\n): Promise<TaskFile> {\n return withFileLock(filePath, async () => {\n const file = (await loadTasks(filePath, events, traceId)) ?? emptyTaskFile(sessionId);\n const updated = await fn(file);\n const persisted = await saveTasks(filePath, updated, events, traceId);\n if (!persisted) {\n throw new Error(`Failed to persist tasks to ${filePath} — the change was NOT saved.`);\n }\n return updated;\n });\n}\n","import * as fsp from 'node:fs/promises';\nimport { hostname } from 'node:os';\nimport { atomicWrite } from '../utils/atomic-write.js';\nimport { toErrorMessage } from '../utils/error.js';\n\n/**\n * Director state checkpoint — written incrementally throughout a fleet\n * run so a crashed director can be inspected (and eventually resumed)\n * instead of leaving only a final `fleet.json` manifest after `shutdown()`.\n *\n * Schema is JSON-friendly and deliberately denormalized. Each mutation\n * triggers an atomic-write of the whole file — small payloads (typically\n * < 10 KB even with dozens of subagents) make this cheap.\n */\nexport interface DirectorSubagentState {\n id: string;\n name?: string | undefined;\n role?: string | undefined;\n provider?: string | undefined;\n model?: string | undefined;\n spawnedAt: string;\n}\n\nexport interface DirectorTaskState {\n taskId: string;\n subagentId?: string | undefined;\n description?: string | undefined;\n status: 'pending' | 'running' | 'completed' | 'failed' | 'stopped' | 'timeout';\n assignedAt?: string | undefined;\n completedAt?: string | undefined;\n iterations?: number | undefined;\n toolCalls?: number | undefined;\n durationMs?: number | undefined;\n error?: string | undefined;\n}\n\nexport interface DirectorStateSnapshot {\n version: 1;\n directorRunId: string;\n updatedAt: string;\n spawnCount: number;\n maxSpawns?: number | undefined;\n spawnDepth: number;\n maxSpawnDepth: number;\n directorBudget?: {\n maxCostUsd?: number | undefined;\n } | undefined;\n subagents: DirectorSubagentState[];\n tasks: DirectorTaskState[];\n /** Aggregated usage snapshot. Optional — populated by the Director on save when available. */\n usage?: unknown | undefined;\n}\n\nexport async function loadDirectorState(filePath: string): Promise<DirectorStateSnapshot | null> {\n let raw: string;\n try {\n raw = await fsp.readFile(filePath, 'utf8');\n } catch {\n return null;\n }\n try {\n const parsed = JSON.parse(raw) as DirectorStateSnapshot;\n if (parsed?.version !== 1) return null;\n return parsed;\n } catch {\n return null;\n }\n}\n\n/**\n * Lock file entry written when a director starts. Prevents two directors\n * from resuming the same run — the second one sees the lock and refuses\n * rather than corrupting the checkpoint by writing concurrently.\n */\nexport interface DirectorStateLock {\n pid: number;\n hostname: string;\n startedAt: string;\n}\n\n/**\n * Write a lock file to claim this checkpoint. Returns false if the lock\n * is already held by a live process; returns true if the lock was acquired\n * (either the file didn't exist, or the previous holder is dead).\n */\nexport async function acquireDirectorStateLock(\n lockPath: string,\n processId = process.pid,\n): Promise<boolean> {\n let existing: string | undefined;\n try {\n existing = await fsp.readFile(lockPath, 'utf8');\n } catch {\n // No lock file — we're safe to claim\n }\n\n if (existing) {\n try {\n const lock = JSON.parse(existing) as DirectorStateLock;\n // Check if the process is still alive\n try {\n process.kill(lock.pid, 0);\n // Signal success means the process is alive — another director\n // owns this checkpoint. Refuse.\n return false;\n } catch {\n // ESRCH means the process is dead — stale lock. We'll overwrite.\n }\n } catch {\n // Malformed lock — treat as stale.\n }\n }\n\n const lock: DirectorStateLock = {\n pid: processId,\n hostname: hostname(),\n startedAt: new Date().toISOString(),\n };\n await atomicWrite(lockPath, JSON.stringify(lock), { mode: 0o600 });\n return true;\n}\n\n/**\n * Remove the lock file. Call this on graceful Director.shutdown() so the\n * next director run can claim the checkpoint without stale-lock checks.\n */\nexport async function releaseDirectorStateLock(lockPath: string): Promise<void> {\n try {\n await fsp.unlink(lockPath);\n } catch {\n // ignore\n }\n}\n\n/**\n * In-memory accumulator with atomic-write checkpoint. The Director keeps\n * an instance, mutates it on every spawn/assign/complete/fail event, and\n * the instance debounces writes so a burst of activity collapses into a\n * single disk hit.\n *\n * Supports crash recovery: use `loadDirectorState()` to read an existing\n * checkpoint, then call `DirectorStateCheckpoint.resume(snapshot)` to\n * re-attach to a fleet mid-flight. The lock mechanism ensures no two\n * directors can claim the same checkpoint.\n */\nexport class DirectorStateCheckpoint {\n private snapshot: DirectorStateSnapshot;\n private readonly filePath: string;\n private readonly lockPath: string;\n private timer: NodeJS.Timeout | null = null;\n private readonly debounceMs: number;\n private writing = false;\n private rewriteRequested = false;\n\n constructor(\n filePath: string,\n init: {\n directorRunId: string;\n maxSpawns?: number | undefined;\n spawnDepth: number;\n maxSpawnDepth: number;\n directorBudget?: {\n maxCostUsd?: number | undefined;\n } | undefined;\n },\n debounceMs = 250,\n ) {\n this.filePath = filePath;\n // Lock file lives alongside the checkpoint — `<path>.lock`\n this.lockPath = `${filePath}.lock`;\n this.debounceMs = debounceMs;\n this.snapshot = {\n version: 1,\n directorRunId: init.directorRunId,\n updatedAt: new Date().toISOString(),\n spawnCount: 0,\n maxSpawns: init.maxSpawns,\n spawnDepth: init.spawnDepth,\n maxSpawnDepth: init.maxSpawnDepth,\n directorBudget: init.directorBudget,\n subagents: [],\n tasks: [],\n };\n }\n\n /**\n * Attempt to acquire the lock for this checkpoint. Call this before\n * resuming a crashed director run. If it returns false, another\n * director process is still running this fleet — do not resume.\n */\n async acquireLock(): Promise<boolean> {\n return acquireDirectorStateLock(this.lockPath);\n }\n\n /**\n * Release the lock on graceful shutdown. Call `flush()` first to ensure\n * the final checkpoint state is on disk before removing the lock.\n * Without this, the next resume will see a stale-lock and refuse.\n */\n async releaseLock(): Promise<void> {\n return releaseDirectorStateLock(this.lockPath);\n }\n\n /**\n * Resume from a snapshot previously loaded via `loadDirectorState()`.\n * Use this when `--resume <runId>` is triggered — the snapshot has\n * the full fleet state (subagents, tasks) from before the crash; the\n * checkpoint continues from there.\n */\n resume(snapshot: DirectorStateSnapshot): void {\n this.snapshot = snapshot;\n }\n\n current(): DirectorStateSnapshot {\n return this.snapshot;\n }\n\n recordSpawn(sub: DirectorSubagentState, spawnCount: number): void {\n this.snapshot = {\n ...this.snapshot,\n spawnCount,\n subagents: [...this.snapshot.subagents.filter((s) => s.id !== sub.id), sub],\n };\n this.bumpUpdatedAt();\n this.schedule();\n }\n\n recordTaskAssigned(task: DirectorTaskState): void {\n const exists = this.snapshot.tasks.some((t) => t.taskId === task.taskId);\n this.snapshot = {\n ...this.snapshot,\n tasks: exists\n ? this.snapshot.tasks.map((t) => (t.taskId === task.taskId ? { ...t, ...task } : t))\n : [...this.snapshot.tasks, task],\n };\n this.bumpUpdatedAt();\n this.schedule();\n }\n\n recordTaskStatus(\n taskId: string,\n patch: Partial<DirectorTaskState> & { status: DirectorTaskState['status'] },\n ): void {\n this.snapshot = {\n ...this.snapshot,\n tasks: this.snapshot.tasks.map((t) =>\n t.taskId === taskId ? { ...t, ...patch } : t,\n ),\n };\n this.bumpUpdatedAt();\n this.schedule();\n }\n\n setUsage(usage: unknown): void {\n this.snapshot = { ...this.snapshot, usage };\n this.bumpUpdatedAt();\n this.schedule();\n }\n\n /** Force a synchronous flush — used by Director.shutdown(). */\n async flush(): Promise<void> {\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n await this.persist();\n // If a rewrite was requested while we waited, persist() scheduled\n // a follow-up write. Loop until no more rewrites are requested so\n // shutdown doesn't return before the most recent state lands on disk.\n /* v8 ignore start -- concurrency-defensive: persist()'s finally clears the flag in single-threaded flow */\n while (this.rewriteRequested) {\n this.rewriteRequested = false;\n await this.persist();\n }\n /* v8 ignore stop */\n }\n\n private bumpUpdatedAt(): void {\n this.snapshot = { ...this.snapshot, updatedAt: new Date().toISOString() };\n }\n\n private schedule(): void {\n if (this.timer) return;\n this.timer = setTimeout(() => {\n this.timer = null;\n void this.persist();\n }, this.debounceMs);\n }\n\n private async persist(): Promise<void> {\n if (this.writing) {\n // A write is already in flight — defer to a follow-up flush so the\n // most recent state still lands. Without this guard, simultaneous\n // burst mutations can drop the latest snapshot if rename races.\n this.rewriteRequested = true;\n return;\n }\n this.writing = true;\n try {\n await atomicWrite(this.filePath, JSON.stringify(this.snapshot, null, 2), {\n mode: 0o600,\n });\n } catch (err) {\n console.warn(\n '[director-state] checkpoint write failed:',\n toErrorMessage(err),\n );\n } finally {\n this.writing = false;\n /* v8 ignore start -- concurrency-defensive: rewriteRequested is only set by an overlapping persist() */\n if (this.rewriteRequested) {\n this.rewriteRequested = false;\n this.schedule();\n }\n /* v8 ignore stop */\n }\n }\n}\n","import * as fsp from 'node:fs/promises';\nimport type { EventBus } from '../kernel/events.js';\nimport { atomicWrite, withFileLock } from '../utils/atomic-write.js';\nimport { toErrorMessage } from '../utils/error.js';\nimport { color } from '../utils/color.js';\nimport { resolveWstackPaths } from '../utils/wstack-paths.js';\nimport { FsError, ERROR_CODES } from '../types/errors.js';\n\n/**\n * Long-running autonomous mission. A goal survives across sessions and\n * drives the EternalAutonomyEngine — every iteration of the engine\n * consults the goal to choose what to do next.\n *\n * Storage: `~/.wrongstack/projects/<hash>/goal.json`. Persistent and\n * project-scoped on purpose: the goal belongs to the codebase, not the\n * REPL session.\n */\n\nexport interface JournalEntry {\n /** ISO timestamp of the iteration. */\n at: string;\n /** Sequential iteration counter (1-based, monotonically increasing). */\n iteration: number;\n /** Source that produced the action ('todo' | 'git' | 'brainstorm' | 'resume' | 'manual' | 'parallel'). */\n source: 'todo' | 'git' | 'brainstorm' | 'resume' | 'manual' | 'parallel';\n /** Short one-line description of what the iteration set out to do. */\n task: string;\n /** Outcome status. */\n status: 'success' | 'failure' | 'aborted' | 'skipped';\n /** Optional free-form note (error message, summary, etc.). */\n note?: string | undefined;\n /** Optional token usage delta for this iteration. */\n tokens?: { input: number; output: number } | undefined;\n /** Optional USD cost delta for this iteration (provider-estimated). */\n costUsd?: number | undefined;\n}\n\nexport interface GoalFile {\n version: 1;\n /** The raw mission statement as entered by the user. */\n goal: string;\n /**\n * LLM-refined version of the goal — unambiguous, with concrete\n * deliverables and acceptance criteria.\n */\n refinedGoal?: string | undefined;\n /**\n * Concrete, verifiable deliverables extracted from the refined goal.\n */\n deliverables?: string[] | undefined;\n /**\n * Estimated completion 0-100. Updated by the engine after each\n * iteration. Null means \"not yet assessed\".\n */\n progress?: number | undefined;\n /** Human-readable note explaining the current progress estimate. */\n progressNote?: string | undefined;\n /**\n * Time-series of progress measurements for trend analysis.\n * Last 200 entries retained. Use `recordProgress()` to append.\n */\n progressHistory?: ProgressSnapshot[] | undefined;\n /**\n * Computed trend from recent progress measurements.\n * 'accelerating' | 'steady' | 'stalling' | undefined.\n */\n progressTrend?: 'accelerating' | 'steady' | 'stalling' | undefined;\n /** When the goal was first set or last replaced. */\n setAt: string;\n /** Updated on every iteration completion. */\n lastActivityAt: string;\n /** Total iterations the engine has run against this goal (cumulative). */\n iterations: number;\n /** Engine lifecycle state — 'running' means another process owns this goal. */\n engineState: 'idle' | 'running' | 'stopped';\n /**\n * Mission-level lifecycle.\n */\n goalState?: 'active' | 'paused' | 'completed' | 'abandoned' | undefined;\n /**\n * Per-todo attempt counter.\n */\n todoAttempts?: Record<string, number>;\n /** Bounded ring buffer of recent iterations (newest last). */\n journal: JournalEntry[];\n}\n\n/** Cap on persisted journal entries — older entries are evicted FIFO. */\nexport const MAX_JOURNAL_ENTRIES = 500;\n\n/**\n * Resolve the goal file path for a given project root.\n *\n * SINGLE canonical location: the per-project directory that\n * `resolveWstackPaths()` uses for everything else (sessions, memory, specs) —\n * `~/.wrongstack/projects/<slug>/goal.json`. This is the same path the `/goal`\n * slash command writes via `opts.paths.projectGoal`, so every reader/writer\n * (the eternal/parallel autonomy engines, the CLI autonomy commands, the TUI\n * F9 panel, and `/goal` itself) now agree on one file.\n *\n * Previously this returned a SEPARATE hash-based dir (`projects/<hash>/`), which\n * disagreed with `/goal` and littered the home dir with thousands of stray\n * `<hash>/goal.json` directories that held nothing else.\n */\nexport function goalFilePath(projectRoot: string): string {\n return resolveWstackPaths({ projectRoot }).projectGoal;\n}\n\nexport async function loadGoal(filePath: string, events?: EventBus): Promise<GoalFile | null> {\n const t0 = Date.now();\n let raw: string;\n try {\n raw = await fsp.readFile(filePath, 'utf8');\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') {\n events?.emit('storage.read', {\n sessionId: '~boot~',\n store: 'goal',\n filePath,\n operation: 'load',\n outcome: 'success',\n durationMs: Date.now() - t0,\n });\n return null; // file doesn't exist — not an error\n }\n events?.emit('storage.error', {\n sessionId: '~boot~',\n store: 'goal',\n filePath,\n operation: 'load',\n error: toErrorMessage(err),\n recoverable: false,\n });\n throw err; // permission errors etc. should surface\n }\n try {\n const parsed = JSON.parse(raw) as GoalFile;\n if (parsed?.version !== 1 || typeof parsed.goal !== 'string' || !Array.isArray(parsed.journal)) {\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'goal_store.invalid_schema',\n path: filePath,\n message: 'invalid schema — consider deleting and re-creating',\n timestamp: new Date().toISOString(),\n }));\n events?.emit('storage.read', {\n sessionId: '~boot~',\n store: 'goal',\n filePath,\n operation: 'load',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'invalid_schema',\n });\n return null;\n }\n events?.emit('storage.read', {\n sessionId: '~boot~',\n store: 'goal',\n filePath,\n operation: 'load',\n outcome: 'success',\n durationMs: Date.now() - t0,\n });\n return parsed;\n } catch {\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'goal_store.parse_failed',\n path: filePath,\n message: 'JSON parse failed — consider deleting and re-creating',\n timestamp: new Date().toISOString(),\n }));\n events?.emit('storage.read', {\n sessionId: '~boot~',\n store: 'goal',\n filePath,\n operation: 'load',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'parse_failed',\n });\n return null;\n }\n}\n\nexport async function saveGoal(filePath: string, goal: GoalFile, events?: EventBus): Promise<void> {\n const t0 = Date.now();\n try {\n await atomicWrite(filePath, JSON.stringify(goal, null, 2), { mode: 0o600 });\n events?.emit('storage.write', {\n sessionId: '~boot~',\n store: 'goal',\n filePath,\n operation: 'save',\n outcome: 'success',\n durationMs: Date.now() - t0,\n });\n } catch (err) {\n events?.emit('storage.error', {\n sessionId: '~boot~',\n store: 'goal',\n filePath,\n operation: 'save',\n error: toErrorMessage(err),\n recoverable: false,\n });\n throw new FsError({\n message: toErrorMessage(err),\n code: ERROR_CODES.FS_ATOMIC_WRITE_FAILED,\n path: filePath,\n cause: err,\n });\n }\n}\n\n/**\n * Atomically load, modify, and save a goal file under a file lock.\n * Prevents lost-update races when the autonomy engine and CLI /goal commands\n * write concurrently (both eternal and parallel engines may run simultaneously).\n *\n * `fn` receives the current GoalFile (or `null` if no goal exists yet)\n * and must return the updated GoalFile (or `null` to delete).\n */\nexport async function updateGoal(\n filePath: string,\n fn: (current: GoalFile | null) => GoalFile | null,\n events?: EventBus,\n): Promise<void> {\n const t0 = Date.now();\n await withFileLock(filePath, async () => {\n const current = await loadGoal(filePath, events);\n const next = fn(current);\n if (next) {\n await saveGoal(filePath, next, events);\n } else {\n try {\n await fsp.unlink(filePath);\n events?.emit('storage.write', {\n sessionId: '~boot~',\n store: 'goal',\n filePath,\n operation: 'delete',\n outcome: 'success',\n durationMs: Date.now() - t0,\n });\n } catch (err) {\n events?.emit('storage.error', {\n sessionId: '~boot~',\n store: 'goal',\n filePath,\n operation: 'delete',\n error: toErrorMessage(err),\n recoverable: true,\n });\n // best-effort — file may not exist\n }\n }\n events?.emit('storage.write', {\n sessionId: '~boot~',\n store: 'goal',\n filePath,\n operation: 'update',\n outcome: 'success',\n durationMs: Date.now() - t0,\n });\n });\n}\n\nexport function emptyGoal(goal: string): GoalFile {\n const now = new Date().toISOString();\n return {\n version: 1,\n goal,\n setAt: now,\n lastActivityAt: now,\n iterations: 0,\n engineState: 'idle',\n goalState: 'active',\n todoAttempts: {},\n journal: [],\n };\n}\n\n/**\n * Set progress estimate on a goal. Returns a new GoalFile.\n * Clamps progress to 0-100.\n */\nexport function setProgress(\n goal: GoalFile,\n progress: number,\n note?: string,\n): GoalFile {\n const clamped = Math.min(100, Math.max(0, progress));\n return {\n ...goal,\n progress: clamped,\n progressNote: note ?? clamped + '% complete',\n };\n}\n\n/**\n * Append a journal entry, bumping iteration counters and trimming the\n * ring buffer. Returns a new GoalFile — does not mutate the argument.\n */\nexport function appendJournal(goal: GoalFile, entry: Omit<JournalEntry, 'iteration' | 'at'>): GoalFile {\n const iteration = goal.iterations + 1;\n const at = new Date().toISOString();\n const full: JournalEntry = { ...entry, iteration, at };\n const journal = [...goal.journal, full];\n const trimmed = journal.length > MAX_JOURNAL_ENTRIES\n ? journal.slice(journal.length - MAX_JOURNAL_ENTRIES)\n : journal;\n return {\n ...goal,\n iterations: iteration,\n lastActivityAt: at,\n journal: trimmed,\n };\n}\n\n/**\n * Aggregate cumulative cost + tokens across all journal entries.\n */\nexport function summarizeUsage(goal: GoalFile): {\n totalCostUsd: number;\n totalInputTokens: number;\n totalOutputTokens: number;\n iterationsWithUsage: number;\n} {\n let totalCostUsd = 0;\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n let iterationsWithUsage = 0;\n for (const e of goal.journal) {\n if (typeof e.costUsd === 'number') totalCostUsd += e.costUsd;\n if (e.tokens) {\n totalInputTokens += e.tokens.input;\n totalOutputTokens += e.tokens.output;\n }\n if (typeof e.costUsd === 'number' || e.tokens) iterationsWithUsage++;\n }\n return { totalCostUsd, totalInputTokens, totalOutputTokens, iterationsWithUsage };\n}\n\nconst DOLLAR = '\\u0024';\n\n/** Format the goal + recent journal as a human-readable status block. */\nexport function formatGoal(goal: GoalFile, journalLimit = 10): string {\n const lines: string[] = [];\n\n // Header — show refined goal, with original as annotation if different\n const displayGoal = goal.refinedGoal || goal.goal;\n lines.push(color.bold('Goal') + ': ' + displayGoal);\n if (goal.refinedGoal && goal.refinedGoal !== goal.goal) {\n const snippet = goal.goal.length > 60 ? goal.goal.slice(0, 60) + '…' : goal.goal;\n lines.push(color.dim(' (original: \"' + snippet + '\")'));\n }\n\n // Progress bar (20-segment)\n if (typeof goal.progress === 'number') {\n const pct = Math.min(100, Math.max(0, Math.round(goal.progress)));\n const filled = Math.round(pct / 5);\n const empty = 20 - filled;\n const bar = color.green('█'.repeat(filled)) + color.dim('░'.repeat(empty));\n lines.push('Progress: ' + bar + ' ' + color.bold(pct + '%'));\n if (goal.progressNote) {\n lines.push(' ' + color.dim(goal.progressNote));\n }\n // Trend indicator\n if (goal.progressTrend) {\n const trendIcon = goal.progressTrend === 'accelerating' ? '🚀'\n : goal.progressTrend === 'stalling' ? '⚠️'\n : '➡️';\n lines.push(' Trend: ' + trendIcon + ' ' + goal.progressTrend);\n }\n }\n\n // Deliverables checklist\n if (goal.deliverables && goal.deliverables.length > 0) {\n lines.push('');\n lines.push(color.bold('Deliverables:'));\n for (const d of goal.deliverables) {\n const done = /^\\[[x✓]\\]|✅|\\(done\\)/i.test(d);\n const marker = done ? color.green('✓') : color.dim('○');\n lines.push(' ' + marker + ' ' + d);\n }\n }\n\n lines.push('');\n lines.push('Set: ' + goal.setAt);\n lines.push('Last activity: ' + goal.lastActivityAt);\n lines.push('Iterations: ' + goal.iterations);\n const stateLabel = goal.goalState ?? 'active';\n lines.push('State: ' + stateLabel + (goal.iterations > 0 ? ' (iteration #' + goal.iterations + ')' : ''));\n lines.push('Engine: ' + goal.engineState);\n const usage = summarizeUsage(goal);\n if (usage.iterationsWithUsage > 0) {\n const spent = 'Spent: ' + DOLLAR + usage.totalCostUsd.toFixed(4)\n + ' (in ' + usage.totalInputTokens + ' / out ' + usage.totalOutputTokens\n + ' tokens across ' + usage.iterationsWithUsage + ' iterations)';\n lines.push(spent);\n }\n if (goal.journal.length > 0) {\n lines.push('');\n lines.push('Recent journal (last ' + Math.min(journalLimit, goal.journal.length) + '):');\n const tail = goal.journal.slice(-journalLimit);\n for (const e of tail) {\n const mark = e.status === 'success' ? '✓' : e.status === 'failure' ? '✗' : e.status === 'aborted' ? '⊘' : '·';\n const note = e.note ? ' — ' + e.note : '';\n const cost = typeof e.costUsd === 'number' ? ' (' + DOLLAR + e.costUsd.toFixed(4) + ')' : '';\n lines.push(' #' + e.iteration + ' ' + mark + ' [' + e.source + '] ' + e.task + cost + note);\n }\n }\n return lines.join('\\n');\n}\n\n/** A single progress measurement at a point in time. */\nexport interface ProgressSnapshot {\n at: string;\n progress: number;\n note?: string | undefined;\n}\n\n/**\n * Parse [PROGRESS: N%] from agent final text.\n * Supports formats:\n * [PROGRESS: 45%]\n * [PROGRESS: 45%] — 3/5 deliverables done\n * [progress: 100%]\n * Returns null if no match.\n */\nexport function parseProgressFromText(text: string): { progress: number; note?: string } | null {\n const re = /\\[progress:\\s*(\\d{1,3})%\\]\\s*(?:[—-]\\s*(.+))?/i;\n const m = text.match(re);\n if (!m) return null;\n // Regex match guarantees capture group 1 exists, but use ?? fallback to\n // satisfy noUncheckedIndexedAccess without a non-null assertion.\n const progress = Math.min(100, Math.max(0, Number.parseInt(m[1] ?? '0', 10)));\n const note = m[2]?.trim() || undefined;\n return note === undefined ? { progress } : { progress, note };\n}\n\n/**\n * Record a progress measurement. Returns a new GoalFile with:\n * - progress + progressNote updated\n * - progressHistory appended (last 200 entries kept)\n * - progress trend computed (accelerating/steady/stalling)\n */\nexport function recordProgress(\n goal: GoalFile,\n progress: number,\n note?: string,\n): GoalFile {\n const clamped = Math.min(100, Math.max(0, progress));\n const history = [...(goal.progressHistory ?? []), { at: new Date().toISOString(), progress: clamped, note }];\n // Keep last 200 snapshots\n const trimmed = history.length > 200 ? history.slice(-200) : history;\n\n return {\n ...goal,\n progress: clamped,\n progressNote: note ?? `${clamped}% complete`,\n progressHistory: trimmed,\n progressTrend: computeTrend(trimmed),\n };\n}\n\n/** Max progress history entries to retain. */\nexport const MAX_PROGRESS_HISTORY = 200;\n\nfunction computeTrend(history: ProgressSnapshot[]): 'accelerating' | 'steady' | 'stalling' | undefined {\n if (history.length < 3) return undefined;\n const recent = history.slice(-5);\n const deltas: number[] = [];\n for (let i = 1; i < recent.length; i++) {\n deltas.push((recent[i]?.progress ?? 0) - (recent[i - 1]?.progress ?? 0));\n }\n /* v8 ignore next -- unreachable: history.length>=3 guard above guarantees >=2 deltas */\n if (deltas.length < 2) return undefined;\n const avgDelta = deltas.reduce((a, b) => a + b, 0) / deltas.length;\n if (avgDelta > 2) return 'accelerating';\n if (avgDelta < -1) return 'stalling';\n return 'steady';\n}\n","import { createHash } from 'node:crypto';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { PromptEntry, PromptVariable } from '../types/prompt.js';\nimport { atomicWrite, ensureDir } from '../utils/atomic-write.js';\nimport { slugify } from '../utils/slug.js';\nimport { ulid } from '../utils/ulid.js';\nimport type { WstackPaths } from '../utils/wstack-paths.js';\n\nexport type { PromptEntry, PromptSource, PromptVariable } from '../types/prompt.js';\n\nexport interface PromptStore {\n list(): Promise<PromptEntry[]>;\n get(id: string): Promise<PromptEntry | null>;\n save(entry: PromptEntry): Promise<void>;\n delete(id: string): Promise<boolean>;\n find(query: string): Promise<PromptEntry[]>;\n}\n\n/** Current on-disk schema version. */\nconst SCHEMA_VERSION = 2;\n\ninterface RawPromptFile {\n version: number;\n entry: unknown;\n}\n\n/** sha256 of a prompt's content — used for builtin/synced integrity checks. */\nexport function promptChecksum(content: string): string {\n return createHash('sha256').update(content, 'utf8').digest('hex');\n}\n\n/**\n * Upgrade any persisted prompt record (v1 or v2) to a fully-populated v2\n * `PromptEntry`. Pure — does not touch disk. v1 records (only\n * `id/title/content/tags/createdAt/updatedAt`) get sensible defaults:\n * slug from title, empty description, `uncategorized` category, `user` source.\n */\nexport function migratePromptEntry(raw: unknown): PromptEntry | null {\n if (!raw || typeof raw !== 'object') return null;\n const r = raw as Record<string, unknown>;\n if (typeof r['id'] !== 'string' || typeof r['title'] !== 'string') return null;\n\n const title = r['title'];\n const content = typeof r['content'] === 'string' ? r['content'] : '';\n const now = typeof r['createdAt'] === 'string' ? r['createdAt'] : new Date(0).toISOString();\n const tags = Array.isArray(r['tags'])\n ? (r['tags'].filter((t) => typeof t === 'string') as string[])\n : [];\n\n return {\n id: r['id'],\n slug: typeof r['slug'] === 'string' && r['slug'].length > 0 ? r['slug'] : slugify(title),\n title,\n description: typeof r['description'] === 'string' ? r['description'] : '',\n content,\n category:\n typeof r['category'] === 'string' && r['category'].length > 0\n ? r['category']\n : 'uncategorized',\n tags,\n source: isPromptSource(r['source']) ? r['source'] : 'user',\n favorite: r['favorite'] === true,\n variables: normalizeVariables(r['variables']),\n author: typeof r['author'] === 'string' ? r['author'] : undefined,\n version: typeof r['version'] === 'string' ? r['version'] : undefined,\n license: typeof r['license'] === 'string' ? r['license'] : undefined,\n checksum: typeof r['checksum'] === 'string' ? r['checksum'] : undefined,\n forkedFrom: typeof r['forkedFrom'] === 'string' ? r['forkedFrom'] : undefined,\n createdAt: now,\n updatedAt: typeof r['updatedAt'] === 'string' ? r['updatedAt'] : now,\n };\n}\n\nfunction isPromptSource(v: unknown): v is PromptEntry['source'] {\n return v === 'builtin' || v === 'user' || v === 'project' || v === 'synced';\n}\n\nfunction normalizeVariables(v: unknown): PromptVariable[] | undefined {\n if (!Array.isArray(v)) return undefined;\n const out: PromptVariable[] = [];\n for (const item of v) {\n if (\n item &&\n typeof item === 'object' &&\n typeof (item as Record<string, unknown>)['name'] === 'string'\n ) {\n const o = item as Record<string, unknown>;\n const enumVals =\n Array.isArray(o['enum']) && o['enum'].every((x) => typeof x === 'string')\n ? (o['enum'] as string[])\n : undefined;\n out.push({\n name: o['name'] as string,\n description: typeof o['description'] === 'string' ? o['description'] : undefined,\n default: typeof o['default'] === 'string' ? o['default'] : undefined,\n required: o['required'] === true ? true : undefined,\n enum: enumVals && enumVals.length > 0 ? enumVals : undefined,\n multiline: o['multiline'] === true ? true : undefined,\n });\n }\n }\n return out.length > 0 ? out : undefined;\n}\n\n/**\n * DefaultPromptStore — file-per-prompt JSON in a single directory (the global\n * `~/.wrongstack/prompts` by default, or a layer dir the loader passes in).\n * Reads tolerate legacy v1 files via `migratePromptEntry`; writes always emit\n * the current v2 schema.\n */\nexport class DefaultPromptStore implements PromptStore {\n private readonly dir: string;\n\n constructor(pathsOrDir: WstackPaths | string) {\n this.dir = typeof pathsOrDir === 'string' ? pathsOrDir : pathsOrDir.globalPrompts;\n }\n\n async list(): Promise<PromptEntry[]> {\n await ensureDir(this.dir);\n const entries: PromptEntry[] = [];\n try {\n const files = await fs.readdir(this.dir);\n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n try {\n const raw: RawPromptFile = JSON.parse(\n await fs.readFile(path.join(this.dir, file), 'utf8'),\n );\n const migrated = migratePromptEntry(raw.entry);\n if (migrated) entries.push(migrated);\n } catch {\n // skip corrupt files\n }\n }\n } catch {\n // dir doesn't exist yet\n }\n return entries.sort(\n (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(),\n );\n }\n\n async get(id: string): Promise<PromptEntry | null> {\n const file = path.join(this.dir, `${id}.json`);\n try {\n const raw: RawPromptFile = JSON.parse(await fs.readFile(file, 'utf8'));\n return migratePromptEntry(raw.entry);\n } catch {\n return null;\n }\n }\n\n async save(entry: PromptEntry): Promise<void> {\n await ensureDir(this.dir);\n const file = path.join(this.dir, `${entry.id}.json`);\n const raw: RawPromptFile = { version: SCHEMA_VERSION, entry };\n await atomicWrite(file, JSON.stringify(raw, null, 2));\n }\n\n async delete(id: string): Promise<boolean> {\n const file = path.join(this.dir, `${id}.json`);\n try {\n await fs.unlink(file);\n return true;\n } catch {\n return false;\n }\n }\n\n async find(query: string): Promise<PromptEntry[]> {\n const all = await this.list();\n const lower = query.toLowerCase();\n return all.filter(\n (e) =>\n e.title.toLowerCase().includes(lower) ||\n e.description.toLowerCase().includes(lower) ||\n e.content.toLowerCase().includes(lower) ||\n e.category.toLowerCase().includes(lower) ||\n e.tags.some((t) => t.toLowerCase().includes(lower)),\n );\n }\n\n /** Create a new v2 entry and return it. Does NOT persist — call save() afterwards. */\n createNew(\n title: string,\n content: string,\n tags: string[] = [],\n extra: Partial<\n Omit<PromptEntry, 'id' | 'title' | 'content' | 'tags' | 'createdAt' | 'updatedAt'>\n > = {},\n ): PromptEntry {\n const now = new Date().toISOString();\n return {\n id: ulid(),\n slug: extra.slug && extra.slug.length > 0 ? extra.slug : slugify(title),\n title,\n description: extra.description ?? '',\n content,\n category: extra.category ?? 'uncategorized',\n tags,\n source: extra.source ?? 'user',\n favorite: extra.favorite ?? false,\n variables: extra.variables,\n author: extra.author,\n version: extra.version,\n license: extra.license,\n checksum: extra.checksum,\n forkedFrom: extra.forkedFrom,\n createdAt: now,\n updatedAt: now,\n };\n }\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { atomicWrite, ensureDir } from '../utils/atomic-write.js';\n\nexport interface PromptUsage {\n count: number;\n lastUsedAt: string;\n}\n\ninterface RawUsageFile {\n version: 1;\n usage: Record<string, PromptUsage>;\n}\n\n/**\n * Tracks how often each prompt is inserted, keyed by slug, in a single JSON\n * file (`~/.wrongstack/prompt-usage.json`). Kept SEPARATE from the prompt\n * entries so usage can be recorded for read-only builtin prompts without\n * copy-on-writing them into the user layer. Surfaces \"recent / most-used\"\n * views and a gentle search-ranking boost.\n */\nexport class PromptUsageStore {\n constructor(private readonly file: string) {}\n\n async load(): Promise<Record<string, PromptUsage>> {\n try {\n const raw: RawUsageFile = JSON.parse(await fs.readFile(this.file, 'utf8'));\n if (raw && typeof raw === 'object' && raw.usage && typeof raw.usage === 'object') {\n return raw.usage;\n }\n } catch {\n // missing or corrupt → empty\n }\n return {};\n }\n\n async record(slug: string, at: string = new Date().toISOString()): Promise<PromptUsage> {\n const usage = await this.load();\n const prev = usage[slug];\n const next: PromptUsage = { count: (prev?.count ?? 0) + 1, lastUsedAt: at };\n usage[slug] = next;\n await ensureDir(path.dirname(this.file));\n await atomicWrite(this.file, JSON.stringify({ version: 1, usage } satisfies RawUsageFile, null, 2));\n return next;\n }\n\n async get(slug: string): Promise<PromptUsage | undefined> {\n return (await this.load())[slug];\n }\n\n /** Slugs ordered by most-recently-used (then by count), capped at `limit`. */\n async recent(limit = 15): Promise<{ slug: string; usage: PromptUsage }[]> {\n const usage = await this.load();\n return Object.entries(usage)\n .map(([slug, u]) => ({ slug, usage: u }))\n .sort(\n (a, b) =>\n new Date(b.usage.lastUsedAt).getTime() - new Date(a.usage.lastUsedAt).getTime() ||\n b.usage.count - a.usage.count,\n )\n .slice(0, limit);\n }\n\n /** Slugs ordered by usage count (then recency), capped at `limit`. */\n async top(limit = 15): Promise<{ slug: string; usage: PromptUsage }[]> {\n const usage = await this.load();\n return Object.entries(usage)\n .map(([slug, u]) => ({ slug, usage: u }))\n .sort(\n (a, b) =>\n b.usage.count - a.usage.count ||\n new Date(b.usage.lastUsedAt).getTime() - new Date(a.usage.lastUsedAt).getTime(),\n )\n .slice(0, limit);\n }\n}\n","import { expectDefined } from '../utils/expect-defined.js';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { createHash } from 'node:crypto';\nimport type { WstackPaths } from '../utils/wstack-paths.js';\nimport type { SyncCategory, SyncConfig } from '../types/config.js';\nimport { FsError, WrongStackError, ERROR_CODES } from '../types/errors.js';\nexport const ALL_SYNC_CATEGORIES: SyncCategory[] = ['settings', 'skills', 'prompts', 'memory', 'history'];\n\nexport interface SyncResult {\n ok: boolean;\n action: 'push' | 'pull';\n categories: SyncCategory[];\n committedAt?: string | undefined;\n message: string;\n}\n\ninterface SyncStateFile {\n version: 1;\n sha: string;\n lastSyncedAt: string;\n localRev: string;\n}\n\n/**\n * CloudSync — push/pull user-selected ~/.wrongstack categories to a\n * private GitHub repo. No git CLI needed; uses GitHub REST API via fetch.\n * The token is stored encrypted via SecretVault (field named `githubToken`\n * so the vault walker picks it up automatically).\n */\nexport class CloudSync {\n private readonly statePath: string;\n private state: SyncStateFile | null = null;\n\n constructor(\n private readonly paths: WstackPaths,\n private readonly getConfig: () => SyncConfig | null,\n private readonly setConfig: (c: SyncConfig) => Promise<void>,\n ) {\n this.statePath = path.join(paths.globalRoot, 'sync-state.json');\n }\n\n // ── Public API ─────────────────────────────────────────────────────\n\n async status(): Promise<string> {\n const cfg = this.getConfig();\n if (!cfg?.enabled) {\n return 'CloudSync: disabled. Run `/sync enable` to activate.';\n }\n const last = this.state?.lastSyncedAt;\n const since = last ? timeAgo(last) : 'never';\n return [\n `CloudSync: enabled`,\n ` repo: ${cfg.repo}`,\n ` categories: ${cfg.categories.join(', ')}`,\n ` last sync: ${since}`,\n ].join('\\n');\n }\n\n async enable(_repo: string, _categories: SyncCategory[]): Promise<string> {\n // Persisted by the slash command via configStore.update.\n return 'Enable via /sync enable.';\n }\n\n async disable(): Promise<string> {\n const cfg = this.getConfig();\n if (!cfg) return 'CloudSync is not configured.';\n const next = { ...cfg, enabled: false };\n await this.setConfig(next);\n return 'CloudSync disabled. Local data kept.';\n }\n\n async push(token: string): Promise<SyncResult> {\n const cfg = this.getConfig();\n if (!cfg?.enabled) return { ok: false, action: 'push', categories: [], message: 'Not enabled.' };\n\n const parts = cfg.repo.split('/');\n const owner = expectDefined(parts[0]);\n const repoName = expectDefined(parts[1]);\n const branch = 'main';\n const baseTreeSha = this.state?.sha;\n\n const { treeEntries, rev } = await this.buildLocalTree(cfg.categories);\n const newTreeSha = await this.createGitTree(token, owner, repoName, treeEntries, baseTreeSha);\n\n const commitSha = await this.createCommit(\n token, owner, repoName, newTreeSha,\n baseTreeSha,\n `Sync ${cfg.categories.join(', ')} — ${new Date().toISOString()}`,\n );\n\n try {\n await this.updateRef(token, owner, repoName, branch, commitSha);\n } catch (err) {\n // 422 = not a fast forward — remote branch moved. Fetch latest SHA and retry.\n if (err instanceof Error && err.message.includes('422')) {\n const remote = await this.getRef(token, owner, repoName, branch);\n const currentSha = remote.object.sha;\n const rebasedCommitSha = await this.createCommit(\n token, owner, repoName, newTreeSha,\n currentSha,\n `Sync ${cfg.categories.join(', ')} — ${new Date().toISOString()}`,\n );\n await this.updateRef(token, owner, repoName, branch, rebasedCommitSha);\n } else {\n throw err;\n }\n }\n\n const syncState: SyncStateFile = {\n version: 1,\n sha: commitSha,\n lastSyncedAt: new Date().toISOString(),\n localRev: rev,\n };\n await fs.writeFile(this.statePath, JSON.stringify(syncState, null, 2), 'utf8');\n this.state = syncState;\n\n return {\n ok: true,\n action: 'push',\n categories: cfg.categories,\n committedAt: commitSha,\n message: `Pushed ${cfg.categories.join(', ')} to ${cfg.repo}. Commit: ${commitSha.slice(0, 7)}`,\n };\n }\n\n async pull(token: string): Promise<SyncResult> {\n const cfg = this.getConfig();\n if (!cfg?.enabled) return { ok: false, action: 'pull', categories: [], message: 'Not enabled.' };\n\n const pullParts = cfg.repo.split('/');\n const owner = expectDefined(pullParts[0]);\n const repoName = expectDefined(pullParts[1]);\n\n const branchData = await this.getRef(token, owner, repoName, 'main');\n const currentSha = branchData.object.sha;\n\n const commitData = await this.getCommit(token, owner, repoName, currentSha);\n const treeSha = commitData.tree.sha;\n\n const treeEntries = await this.getTreeEntries(token, owner, repoName, treeSha);\n\n for (const entry of treeEntries) {\n if (entry.type !== 'blob') continue;\n\n // Paths look like \"data/{category}/...\" — extract the category\n const segments = entry.path.split('/');\n if (segments[0] !== 'data' || !segments[1]) continue;\n const cat = segments[1] as SyncCategory;\n if (!['settings', 'skills', 'prompts', 'memory', 'history'].includes(cat)) continue;\n\n const localPath = this.categoryToPath(cat);\n if (!localPath) continue;\n\n // Reconstruct relative path under the category dir. Remote trees are\n // untrusted input: a compromised sync repo could contain paths like\n // data/skills/../../config.json. Keep every write inside the selected\n // category root, and only allow subpaths for directory-backed categories.\n const rel = segments.slice(2).join('/');\n const destPath = resolvePulledCategoryPath(cat, localPath, rel, entry.path);\n\n const blobData = await this.getBlob(token, owner, repoName, entry.sha);\n await fs.mkdir(path.dirname(destPath), { recursive: true });\n await fs.writeFile(destPath, Buffer.from(blobData, 'base64'));\n }\n\n const localRev = await this.hashLocalCategories(cfg.categories);\n const syncState: SyncStateFile = {\n version: 1,\n sha: currentSha,\n lastSyncedAt: new Date().toISOString(),\n localRev,\n };\n await fs.writeFile(this.statePath, JSON.stringify(syncState, null, 2), 'utf8');\n this.state = syncState;\n\n return {\n ok: true,\n action: 'pull',\n categories: cfg.categories,\n committedAt: currentSha,\n message: `Pulled ${cfg.categories.join(', ')} from ${cfg.repo}. Commit: ${currentSha.slice(0, 7)}`,\n };\n }\n\n async hasLocalChanges(): Promise<boolean> {\n if (!this.state) return true;\n const cfg = this.getConfig();\n if (!cfg) return true;\n const current = await this.hashLocalCategories(cfg.categories);\n return current !== this.state.localRev;\n }\n\n async loadState(): Promise<void> {\n try {\n const raw = await fs.readFile(this.statePath, 'utf8');\n this.state = JSON.parse(raw) as SyncStateFile;\n } catch {\n this.state = null;\n }\n }\n\n // ── GitHub API helpers ──────────────────────────────────────────────\n\n private async githubFetch(\n token: string,\n owner: string,\n repo: string,\n method: 'GET' | 'POST' | 'PUT' | 'PATCH',\n pathSegment: string,\n body?: unknown | undefined,\n ): Promise<unknown> {\n const url = `https://api.github.com/repos/${owner}/${repo}${pathSegment}`;\n const init: RequestInit = {\n signal: AbortSignal.timeout(15_000),\n method,\n headers: {\n Authorization: `Bearer ${token}`,\n Accept: 'application/vnd.github+json',\n 'X-GitHub-Api-Version': '2022-11-28',\n 'Content-Type': 'application/json',\n },\n };\n if (body !== undefined) init.body = JSON.stringify(body);\n const res = await fetch(url, init);\n\n if (!res.ok) {\n const errText = await res.text();\n throw new WrongStackError({\n message: `GitHub API ${method} ${pathSegment} failed (${res.status}): ${errText}`,\n code: ERROR_CODES.UNKNOWN,\n subsystem: 'general',\n context: { method, pathSegment, status: res.status, repo: `${owner}/${repo}` },\n });\n }\n\n const text = await res.text();\n return text ? JSON.parse(text) : {};\n }\n\n private async getRef(token: string, owner: string, repo: string, ref: string) {\n return (await this.githubFetch(token, owner, repo, 'GET', `/git/refs/heads/${ref}`)) as {\n object: { sha: string };\n };\n }\n\n private async updateRef(token: string, owner: string, repo: string, ref: string, sha: string) {\n await this.githubFetch(token, owner, repo, 'PATCH', `/git/refs/heads/${ref}`, {\n sha,\n force: false,\n });\n }\n\n private async getCommit(token: string, owner: string, repo: string, sha: string) {\n return (await this.githubFetch(token, owner, repo, 'GET', `/git/commits/${sha}`)) as {\n tree: { sha: string };\n message: string;\n };\n }\n\n private async getTreeEntries(token: string, owner: string, repo: string, treeSha: string) {\n return (await this.githubFetch(token, owner, repo, 'GET', `/git/trees/${treeSha}?recursive=1`)) as Array<{\n path: string;\n sha: string;\n type: 'blob' | 'tree';\n }>;\n }\n\n private async createCommit(\n token: string, owner: string, repo: string,\n treeSha: string, parentSha?: string | undefined, message = 'sync',\n ) {\n const body: Record<string, unknown> = { message, tree: treeSha };\n if (parentSha) body.parents = [parentSha];\n const result = (await this.githubFetch(token, owner, repo, 'POST', '/git/commits', body)) as { sha: string };\n return result.sha;\n }\n\n private async createGitTree(\n token: string, owner: string, repo: string,\n entries: Array<{ path: string; content: string; mode: string }>,\n baseTreeSha?: string | undefined,\n ): Promise<string> {\n const tree = entries.map((e) => ({\n path: e.path,\n mode: e.mode,\n type: 'blob',\n content: e.content,\n }));\n const body: Record<string, unknown> = { tree };\n if (baseTreeSha) body.base_tree = baseTreeSha;\n const result = (await this.githubFetch(token, owner, repo, 'POST', '/git/trees', body)) as { sha: string };\n return result.sha;\n }\n\n private async getBlob(token: string, owner: string, repo: string, sha: string): Promise<string> {\n const result = (await this.githubFetch(token, owner, repo, 'GET', `/git/blobs/${sha}`)) as { content: string };\n return result.content;\n }\n\n // ── Local file helpers ──────────────────────────────────────────────\n\n private async buildLocalTree(categories: SyncCategory[]): Promise<{\n treeEntries: Array<{ path: string; content: string; mode: string }>;\n rev: string;\n }> {\n const entries: Array<{ path: string; content: string; mode: string }> = [];\n const hashes: string[] = [];\n\n for (const cat of categories) {\n const localPath = this.categoryToPath(cat);\n if (!localPath) continue;\n try {\n const stat = await fs.stat(localPath);\n if (stat.isDirectory()) {\n const files = await this.walkDir(localPath, localPath);\n for (const file of files) {\n const content = await fs.readFile(file, 'utf8');\n const rel = path.relative(localPath, file).replace(/\\\\/g, '/');\n entries.push({ path: `data/${cat}/${rel}`, content, mode: '100644' });\n hashes.push(content);\n }\n } else {\n const content = await fs.readFile(localPath, 'utf8');\n entries.push({ path: `data/${cat}`, content, mode: '100644' });\n hashes.push(content);\n }\n } catch {\n // skip missing files/dirs\n }\n }\n\n const rev = createHash('sha256').update(hashes.join('')).digest('hex').slice(0, 12);\n return { treeEntries: entries, rev };\n }\n\n private async hashLocalCategories(categories: SyncCategory[]): Promise<string> {\n const hashes: string[] = [];\n for (const cat of categories) {\n const localPath = this.categoryToPath(cat);\n if (!localPath) continue;\n try {\n const stat = await fs.stat(localPath);\n if (stat.isDirectory()) {\n const files = await this.walkDir(localPath, localPath);\n for (const file of files) {\n const content = await fs.readFile(file);\n hashes.push(content.toString('base64') + file);\n }\n } else {\n const content = await fs.readFile(localPath);\n hashes.push(content.toString('base64') + localPath);\n }\n } catch {\n // skip\n }\n }\n return createHash('sha256').update(hashes.join('')).digest('hex').slice(0, 12);\n }\n\n private categoryToPath(cat: SyncCategory): string | null {\n switch (cat) {\n case 'settings': return this.paths.globalConfig;\n case 'skills': return this.paths.globalSkills;\n case 'prompts': return this.paths.globalPrompts;\n case 'memory': return this.paths.globalMemory;\n case 'history': return this.paths.historyFile;\n /* v8 ignore next -- unreachable: SyncCategory is exhaustively matched above */\n default: return null;\n }\n }\n\n private async walkDir(dir: string, base: string): Promise<string[]> {\n const results: string[] = [];\n const entries = await fs.readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n results.push(...(await this.walkDir(full, base)));\n } else {\n results.push(full);\n }\n }\n return results;\n }\n}\n\nfunction resolvePulledCategoryPath(\n cat: SyncCategory,\n localPath: string,\n rel: string,\n remotePath: string,\n): string {\n const directoryBacked = cat === 'skills' || cat === 'prompts';\n if (!directoryBacked) {\n if (rel) throw new FsError({\n message: `Refusing nested CloudSync path for file category: ${remotePath}`,\n code: ERROR_CODES.FS_DELETE_FAILED,\n path: remotePath,\n context: { reason: 'nested_file_category', category: cat },\n });\n return localPath;\n }\n\n if (!rel) return localPath;\n const normalizedRel = path.normalize(rel);\n const traversesUp = normalizedRel === '..' || normalizedRel.startsWith(`..${path.sep}`);\n if (path.isAbsolute(normalizedRel) || traversesUp) {\n throw new FsError({\n message: `Refusing CloudSync path traversal: ${remotePath}`,\n code: ERROR_CODES.FS_DELETE_FAILED,\n path: remotePath,\n context: { reason: 'path_traversal', normalizedRel },\n });\n }\n\n const dest = path.resolve(localPath, normalizedRel);\n const root = path.resolve(localPath);\n const relative = path.relative(root, dest);\n /* v8 ignore start -- unreachable: the normalizedRel '..' guard above already rejects traversal */\n if (relative.startsWith('..') || path.isAbsolute(relative)) {\n throw new FsError({\n message: `Refusing CloudSync path outside category root: ${remotePath}`,\n code: ERROR_CODES.FS_DELETE_FAILED,\n path: remotePath,\n context: { reason: 'outside_category_root', category: cat },\n });\n }\n /* v8 ignore stop */\n return dest;\n}\n\nfunction timeAgo(iso: string): string {\n const diff = Date.now() - new Date(iso).getTime();\n const mins = Math.floor(diff / 60_000);\n if (mins < 1) return 'just now';\n if (mins < 60) return `${mins}m ago`;\n const hrs = Math.floor(mins / 60);\n if (hrs < 24) return `${hrs}h ago`;\n const days = Math.floor(hrs / 24);\n return `${days}d ago`;\n}\n","import type { SessionEvent, SessionWriter } from '../types/session.js';\n\nexport type AuditLevel = 'minimal' | 'standard' | 'full';\n\n/**\n * Configuration for sampling high-volume events inside the bridge.\n * This allows callers (CLI, TUI, WebUI, plugins) to tune how aggressively\n * noisy events like tool progress are persisted.\n */\nexport interface ToolProgressSamplingOptions {\n /**\n * How often to persist 'log' and 'partial_output' progress events.\n * - 1 = every message (no sampling)\n * - 8 = keep the first message + every 8th after that (default)\n */\n sampleRate?: number | undefined;\n}\n\nexport interface SessionSamplingOptions {\n /** Controls sampling behavior for `tool_progress` events (only relevant at auditLevel 'full'). */\n toolProgress?: ToolProgressSamplingOptions | undefined;\n}\n\nexport interface SessionEventBridgeOptions {\n /** Sampling rules for high-volume audit events. */\n sampling?: SessionSamplingOptions | undefined;\n}\n\n/**\n * Small, safe helper that wraps a SessionWriter and enforces the\n * configured auditLevel.\n *\n * All appends are best-effort. Failures are swallowed (with optional\n * diagnostics) so they never crash the agent loop.\n */\nexport interface SessionEventBridge {\n /** Append an event if allowed by the current audit level. */\n append(event: SessionEvent): Promise<void>;\n /** Batch-append events allowed by the current audit level. */\n appendBatch(events: SessionEvent[]): Promise<void>;\n\n /** Current audit level. Reflects the latest {@link setAuditLevel} value. */\n readonly level: AuditLevel;\n\n /**\n * Change the audit level on a live bridge. Subsequent appends are filtered\n * by the new level — used by the TUI `/settings` picker to apply an\n * `auditLevel` change to the running session without a restart.\n */\n setAuditLevel(level: AuditLevel): void;\n\n /** Returns true if an event of this type should be written at the current level. */\n allows(type: SessionEvent['type']): boolean;\n}\n\n/** Core events that are always written regardless of auditLevel. */\nconst CORE_RECONSTRUCT_EVENTS = new Set<SessionEvent['type']>([\n 'session_start',\n 'session_resumed',\n 'user_input',\n 'llm_response',\n 'tool_result',\n 'checkpoint',\n 'file_snapshot',\n 'rewound',\n 'in_flight_start',\n 'in_flight_end',\n 'session_end',\n]);\n\n/**\n * Events that are considered \"standard\" audit detail.\n * These are lightweight and high-value for forensics.\n */\nconst STANDARD_AUDIT_EVENTS = new Set<SessionEvent['type']>([\n 'llm_request',\n 'tool_use',\n 'tool_call_start',\n 'tool_call_end',\n 'compaction',\n 'error',\n 'message_truncated',\n 'provider_retry',\n 'provider_error',\n]);\n\n/**\n * Events that are only allowed at 'full' audit level because they can be\n * very high volume (e.g. streaming tool output).\n */\nconst FULL_ONLY_EVENTS = new Set<SessionEvent['type']>([\n 'tool_progress',\n]);\n\n/**\n * \"full\" level allows everything (including potentially heavy events\n * that plugins or future code may emit).\n */\nfunction isAllowed(type: SessionEvent['type'], level: AuditLevel): boolean {\n if (CORE_RECONSTRUCT_EVENTS.has(type)) return true;\n if (level === 'minimal') return false;\n\n if (STANDARD_AUDIT_EVENTS.has(type)) return true;\n if (level === 'standard') return false;\n\n // 'full' level events (high volume)\n if (FULL_ONLY_EVENTS.has(type)) {\n return level === 'full';\n }\n\n // 'full' — allow everything else\n return true;\n}\n\n/**\n * Create a safe, audit-level-aware bridge around a SessionWriter.\n *\n * The bridge can also apply sampling for high-volume events (e.g. `tool_progress`)\n * when `auditLevel` is set to `'full'`.\n *\n * @example\n * const bridge = createSessionEventBridge(sessionWriter, 'full', {\n * sampling: {\n * toolProgress: { sampleRate: 5 } // more aggressive sampling\n * }\n * });\n */\nexport function createSessionEventBridge(\n writer:\n | SessionWriter\n | (() => SessionWriter | undefined | null)\n | undefined\n | null,\n level: AuditLevel = 'standard',\n options: SessionEventBridgeOptions = {},\n): SessionEventBridge {\n // Mutable so setAuditLevel() can re-tune a live bridge in place.\n let currentLevel: AuditLevel = level ?? 'standard';\n\n // Accept either a writer instance or a getter. A getter lets long-lived\n // hosts (CLI/TUI/WebUI) resolve the CURRENT writer on every append — when\n // the user resumes another session mid-run, audit events follow the swap\n // instead of being silently dropped into the old, closed writer.\n const resolveWriter: () => SessionWriter | undefined | null =\n typeof writer === 'function' ? writer : () => writer;\n\n // Internal sampling state for high-volume events (e.g. tool_progress).\n // Keyed by tool call id (or name as fallback) to keep sampling per-call.\n const progressCounters = new Map<string, number>();\n\n const toolProgressConfig = options.sampling?.toolProgress ?? {};\n const TOOL_PROGRESS_SAMPLE_RATE = toolProgressConfig.sampleRate ?? 8;\n\n /**\n * Decide whether a high-volume event should be sampled in.\n * Currently only implements sampling for 'tool_progress'.\n */\n function shouldSample(event: SessionEvent): boolean {\n if (event.type !== 'tool_progress') return true;\n\n const progEvent = event as Extract<SessionEvent, { type: 'tool_progress' }>;\n const innerType = progEvent.event?.type;\n\n // Always let through high-signal structured events\n if (innerType === 'warning' || innerType === 'metric' || innerType === 'file_changed') {\n return true;\n }\n\n // Sample noisy text streams (log / partial_output)\n if (innerType === 'log' || innerType === 'partial_output') {\n const key = progEvent.id || progEvent.name;\n const count = (progressCounters.get(key) || 0) + 1;\n progressCounters.set(key, count);\n\n // Always keep the first message + every Nth after that\n return count === 1 || (count % TOOL_PROGRESS_SAMPLE_RATE === 0);\n }\n\n return true;\n }\n\n return {\n get level() {\n return currentLevel;\n },\n\n setAuditLevel(next) {\n currentLevel = next ?? 'standard';\n },\n\n allows(type) {\n return isAllowed(type, currentLevel);\n },\n\n async append(event) {\n const target = resolveWriter();\n if (!target) return;\n if (!isAllowed(event.type, currentLevel)) return;\n\n // Apply sampling for high-volume events (only at 'full' level)\n if (!shouldSample(event)) return;\n\n try {\n await target.append(event);\n } catch (_err) {\n // Best-effort: never let session logging break the agent.\n // The existing FileSessionWriter already does throttled warnings,\n // but we keep this wrapper silent by default to avoid log spam.\n // Callers that care can listen to EventBus 'session.damaged' etc.\n }\n },\n\n async appendBatch(events) {\n const target = resolveWriter();\n if (!target || events.length === 0) return;\n const allowed = events.filter(\n (e) => isAllowed(e.type, currentLevel) && shouldSample(e),\n );\n if (allowed.length === 0) return;\n try {\n await target.appendBatch(allowed);\n } catch {\n // best-effort — same contract as append()\n }\n },\n };\n}\n\n/** Convenience re-export of the allowed core set for tests/docs. */\nexport { CORE_RECONSTRUCT_EVENTS, STANDARD_AUDIT_EVENTS };\n\n/**\n * Safely extract the auditLevel from a (possibly partial) Config object.\n * Falls back to 'standard' if not present or invalid.\n */\nexport function resolveAuditLevel(\n cfg?: { session?: { auditLevel?: AuditLevel | undefined } | undefined } | null,\n): AuditLevel {\n const raw = cfg?.session?.auditLevel;\n if (raw === 'minimal' || raw === 'standard' || raw === 'full') {\n return raw;\n }\n return 'standard';\n}\n\n/**\n * Fully resolves the session logging configuration with sensible defaults.\n * This is the recommended way for the CLI / TUI / WebUI to read session config.\n */\nexport function resolveSessionLoggingConfig(\n cfg?: {\n session?: {\n auditLevel?: AuditLevel | undefined;\n sampling?: {\n toolProgress?: { sampleRate?: number | undefined };\n };\n };\n } | null,\n): {\n auditLevel: AuditLevel;\n sampling: {\n toolProgress: { sampleRate: number };\n };\n} {\n const session = cfg?.session ?? {};\n\n const auditLevel = resolveAuditLevel(cfg);\n\n const toolProgressSampleRate =\n session.sampling?.toolProgress?.sampleRate ?? 8;\n\n return {\n auditLevel,\n sampling: {\n toolProgress: {\n sampleRate: Math.max(1, Math.floor(toolProgressSampleRate)),\n },\n },\n };\n}"]}
1
+ {"version":3,"sources":["../../src/utils/term.ts","../../src/utils/color.ts","../../src/utils/deep-merge.ts","../../src/utils/error.ts","../../src/utils/expect-defined.ts","../../src/utils/message-invariants.ts","../../src/utils/regex-guard.ts","../../src/utils/safe-json.ts","../../src/utils/session-scoped-path.ts","../../src/utils/slug.ts","../../src/utils/ulid.ts","../../src/utils/wstack-paths.ts","../../src/types/errors.ts","../../src/utils/atomic-write.ts","../../src/storage/session-helpers.ts","../../src/storage/file-session-writer.ts","../../src/storage/session-id.ts","../../src/storage/session-summary.ts","../../src/storage/session-tool-call-ends.ts","../../src/storage/storage-concurrency.ts","../../src/storage/session-store.ts","../../src/storage/queue-store.ts","../../src/storage/attachment-store.ts","../../src/types/memory.ts","../../src/storage/memory-backend.ts","../../src/storage/memory-store.ts","../../src/storage/memory-graph-backend.ts","../../src/utils/instruction-file.ts","../../src/storage/memory-consolidator.ts","../../src/storage/config-store.ts","../../src/security/secret-vault.ts","../../src/storage/provider-config-watcher.ts","../../src/types/context-window.ts","../../src/types/config.ts","../../src/types/default-config.ts","../../src/storage/config-loader.ts","../../src/storage/config-migration.ts","../../src/storage/recovery-lock.ts","../../src/storage/session-reader.ts","../../src/storage/annotations-store.ts","../../src/replay/hash.ts","../../src/storage/replay-log-store.ts","../../src/storage/session-recovery.ts","../../src/storage/tool-audit-log.ts","../../src/storage/session-analyzer.ts","../../src/session-registry.ts","../../src/agent-status-tracker.ts","../../src/fleet-notifier.ts","../../src/storage/session-rewinder.ts","../../src/storage/todos-checkpoint.ts","../../src/storage/plan-store.ts","../../src/storage/plan-templates.ts","../../src/storage/task-store.ts","../../src/storage/director-state.ts","../../src/storage/goal-store.ts","../../src/storage/prompt-store.ts","../../src/storage/prompt-usage-store.ts","../../src/storage/cloud-sync.ts","../../src/storage/session-event-bridge.ts"],"names":["open","path","slugify","projectHash","path3","fs","randomBytes","stat","resolve","path4","fsp","path5","entry","path6","fsp3","fsp4","path7","fs2","path8","writeFile","mkdir","fs3","path9","fs5","path11","path12","deepMerge","fs6","path13","os2","fsp6","fs7","randomUUID","fs8","createHash","storageErrorString","offset","fs9","path14","fs10","path15","stableStringify","fs11","sortKeys","path16","projectSlug","fs12","pidAlive","path17","fs13","fsp7","path18","fsp8","fsp9","fsp10","fsp11","lock","hostname","fsp12","fs14","path19","fs15","path20","path21","fs16","relative"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * TTY detection helpers — the single source of truth for \"is this process\n * running against a real terminal?\". Replaces ad-hoc `process.stdin.isTTY`\n * / `process.stdout.isTTY` checks scattered across the codebase so that:\n *\n * 1. test code can mock a single module instead of stubbing `isTTY` on\n * every ReadStream/WriteStream the test happens to touch;\n * 2. a future TTY-detection source (an env var override, a Windows\n * ConPTY workaround, …) lands in one place;\n * 3. `isInteractive()` encodes the rule the project already used inline\n * (\"both streams are TTYs AND we're not running under CI\") in one\n * testable helper instead of the same 3-condition check in two\n * different files.\n *\n * Scope: detection only. Raw-mode control (`setRawMode`), resize\n * subscriptions, and write-injection belong to a future, larger TTY\n * abstraction; this module is the smallest pull that gives us a\n * testable seam and dedups 20+ call sites.\n */\n\nconst hasStdout = (): boolean => typeof process !== 'undefined' && !!process.stdout;\nconst hasStdin = (): boolean => typeof process !== 'undefined' && !!process.stdin;\n\n/** True when `process.stdout` is attached to a terminal (not a pipe/file). */\nexport function isStdoutTTY(): boolean {\n return hasStdout() && Boolean(process.stdout.isTTY);\n}\n\n/** True when `process.stdin` is attached to a terminal (not a pipe/file). */\nexport function isStdinTTY(): boolean {\n return hasStdin() && Boolean(process.stdin.isTTY);\n}\n\n/**\n * True when the current process is an interactive session: both stdin and\n * stdout are TTYs. Callers that also need a \"not a single-shot invocation\"\n * or \"not under CI\" check should layer that on top — keeping this helper\n * minimal preserves the original inline checks it replaces.\n */\nexport function isInteractive(): boolean {\n return isStdinTTY() && isStdoutTTY();\n}\n\n/** Current terminal size in characters, with a 24×80 fallback for non-TTYs. */\nexport function getTermSize(): { rows: number; cols: number } {\n if (!hasStdout()) return { rows: 24, cols: 80 };\n return {\n rows: process.stdout.rows ?? 24,\n cols: process.stdout.columns ?? 80,\n };\n}\n\n/**\n * Subscribe to terminal resize events. `cb` is called with the new size each\n * time the underlying stream emits `resize`. Returns a cleanup function the\n * caller MUST call on dispose to remove the listener — leaving a stale\n * `resize` listener on a disposed component leaks the closure (and the\n * component itself, transitively) until the process exits.\n *\n * The stream argument defaults to `process.stdout`. Pass an explicit\n * `NodeJS.WriteStream` when the caller already owns one (e.g. a status line\n * that targets an injected `out` for testability). For non-TTY streams no\n * listener is registered and the returned cleanup is a no-op.\n */\nexport function onResize(\n cb: (size: { rows: number; cols: number }) => void,\n stream: NodeJS.WriteStream = process.stdout,\n): () => void {\n if (!stream || typeof stream.on !== 'function') return () => {};\n const handler = (): void => {\n cb({\n rows: stream.rows ?? 24,\n cols: stream.columns ?? 80,\n });\n };\n stream.on('resize', handler);\n return () => {\n stream.off('resize', handler);\n };\n}\n\n/**\n * Toggle raw mode on a TTY stdin stream. Returns `true` when the toggle was\n * applied, `false` when the stream is null, not a TTY, or doesn't expose\n * `setRawMode` (pipes, file descriptors, Windows ConPTY edge cases). Callers\n * that need to restore the previous mode should snapshot `input.isRaw`\n * BEFORE the call and pass the value to a second call to flip back.\n *\n * Use this helper to drop the now-redundant\n * `if (input.isTTY) input.setRawMode(...)` ceremony at every call site.\n */\nexport function setRawMode(input: NodeJS.ReadStream, mode: boolean): boolean {\n if (input?.isTTY !== true) return false;\n if (typeof input.setRawMode !== 'function') return false;\n input.setRawMode(mode);\n return true;\n}\n\n/**\n * Bracket installed by the interactive input reader while a `readline`\n * prompt is on screen. Out-of-band terminal writes — logger WARN/INFO\n * lines, async activity from the Telegram bridge, etc. — go to the same\n * physical terminal as the half-typed prompt but readline has no idea they\n * happened, so it never repaints. The result is the classic corruption the\n * user sees: every async line strands the in-progress draft as a fresh\n * scrollback row (sometimes with its cursor underline).\n *\n * The guard closes that gap. `suspend()` wipes the draft row so the message\n * prints clean; `resume()` repaints the prompt + draft (cursor preserved).\n * When no prompt is active the guard is `null` and writes pass straight\n * through — so agent-turn output (spinner, renderer) is untouched.\n */\nexport interface OutputLineGuard {\n /** Clear the current input row right before an out-of-band write. */\n suspend(): void;\n /** Repaint the prompt + in-progress draft right after the write. */\n resume(): void;\n}\n\nlet activeOutputGuard: OutputLineGuard | null = null;\n\n/**\n * Register (or clear, with `null`) the guard that brackets out-of-band\n * writes. Installed by {@link writeOut}/{@link writeErr} consumers — in\n * practice the CLI's readline input reader — only while a prompt is live.\n * Idempotent; the most recent caller wins.\n */\nexport function setOutputLineGuard(guard: OutputLineGuard | null): void {\n activeOutputGuard = guard;\n}\n\n/**\n * Stream-agnostic write primitive. Returns `false` when the stream is\n * missing or doesn't expose `write` so callers can degrade silently under\n * hostile host environments (closed pipe, mock injects `null`, test\n * replaces the stream with a stub).\n *\n * When an {@link OutputLineGuard} is installed (a readline prompt is on\n * screen) the write is bracketed by `suspend()`/`resume()` so the user's\n * half-typed input survives the interruption instead of being stranded in\n * scrollback. The guard's own redraw uses raw stream writes — never\n * `writeOut`/`writeErr` — so there is no re-entrancy here.\n *\n * **Not exported in the public API.** Exposed only inside `term.ts` for\n * `writeOut` / `writeErr` to share a single implementation. If a caller\n * needs to write to an arbitrary stream, they should call `writeOut` (or\n * `writeErr`) with an explicit `stream` argument — the named functions\n * are the public surface so the \"this is the standard error stream\"\n * intent stays visible at every call site.\n */\nfunction writeTo(\n s: string,\n stream: NodeJS.WriteStream | undefined,\n): boolean {\n if (!stream || typeof stream.write !== 'function') return false;\n const guard = activeOutputGuard;\n if (!guard) {\n stream.write(s);\n return true;\n }\n // A prompt is live — wipe the draft row, emit the message, repaint.\n guard.suspend();\n stream.write(s);\n guard.resume();\n return true;\n}\n\n/**\n * Write `s` to `stream` (defaults to `process.stdout`). Returns `false`\n * when the stream is missing or doesn't expose `write` so callers can\n * degrade silently under hostile host environments (closed pipe, mock\n * injects `null`, test replaces the stream with a stub).\n *\n * Why a helper:\n * 1. **Single seam for output capture in tests** — stub `writeOut` once\n * and assert on what the rest of the codebase intended to print,\n * without spying on `process.stdout.write` (which is brittle and\n * leaks across parallel test files).\n * 2. **Stream swap without grep** — routing the CLI's output to a\n * logger or `out.log` becomes a one-line change at process boot.\n * 3. **Defensive default** — closes the \"what if `process.stdout` is\n * `null`\" gap that currently exists at ~50 call sites that just\n * call `process.stdout.write(s)` and crash on certain Windows\n * redirect invocations.\n *\n * Call-site migration is staged: this commit introduces the helper, a\n * follow-up commit replaces the 50+ `process.stdout.write(...)` sites\n * with `writeOut(...)`. Until that migration lands, both forms coexist\n * and `writeOut` is the preferred form for new code.\n */\nexport function writeOut(\n s: string,\n stream: NodeJS.WriteStream = process.stdout,\n): boolean {\n return writeTo(s, stream);\n}\n\n/**\n * Symmetric partner of `writeOut` for the standard error stream. Same shape,\n * same defensive contract, same single-seam-for-tests story — just defaults to\n * `process.stderr` instead of `process.stdout`.\n *\n * Use this in code paths that emit error/diagnostic/warning text. Keeping\n * these two helpers split (rather than a single `writeTo(s, stream)`) means\n * the call site reads as a clear intent signal: \"I am writing an error\" vs.\n * \"I am writing a result\" — which matters for callers that decide between\n * stdout/stderr routing (e.g. `--quiet` flags, log-level filtering,\n * structured-log rewriters that fork on stream).\n *\n * Stderr writes from the core logger (see `infrastructure/logger.ts`) and from\n * the TUI guard (see `tui/run-tui.ts`) used to call `process.stderr.write`\n * directly. Routing them through this helper lets tests stub the stream at\n * one boundary and lets future logging middleware (e.g. a JSON-line rewriter)\n * swap the destination for the entire process in one place.\n */\nexport function writeErr(\n s: string,\n stream: NodeJS.WriteStream = process.stderr,\n): boolean {\n return writeTo(s, stream);\n}\n","import { isStdoutTTY } from './term.js';\n\nconst isColorTty = (): boolean => {\n if (envFlag(process.env.NO_COLOR)) return false;\n if (envFlag(process.env.FORCE_COLOR)) return true;\n return isStdoutTTY();\n};\n\nfunction envFlag(value: string | undefined): boolean {\n if (value === undefined) return false;\n if (value.trim() === '') return false;\n return !/^(0|false|no|off)$/i.test(value.trim());\n}\n\nconst COLOR = isColorTty();\n\nconst wrap =\n (open: string, close: string) =>\n (s: string): string =>\n COLOR ? `\\x1b[${open}m${s}\\x1b[${close}m` : s;\n\nexport const color = {\n reset: wrap('0', '0'),\n bold: wrap('1', '22'),\n dim: wrap('2', '22'),\n italic: wrap('3', '23'),\n underline: wrap('4', '24'),\n red: wrap('31', '39'),\n green: wrap('32', '39'),\n yellow: wrap('33', '39'),\n blue: wrap('34', '39'),\n magenta: wrap('35', '39'),\n cyan: wrap('36', '39'),\n gray: wrap('90', '39'),\n amber: wrap('38;5;214', '39'),\n pink: wrap('38;5;205', '39'),\n bgRed: wrap('41', '49'),\n bgGreen: wrap('42', '49'),\n};\n\nexport function stripAnsi(s: string): string {\n return s.replace(/\\x1b\\[[0-9;]*[A-Za-z]/g, '');\n}\n","/**\n * Deep merge utility — safely merges nested objects with configurable\n * conflict resolution, array merging, and prototype-pollution guarding.\n *\n * Used by:\n * - config-loader (config layer merging with primitive-array concatenation)\n * - secret-vault (config patching)\n * - json-path (json_merge tool with prefer-base / prefer-patch semantics)\n *\n * @module utils/deep-merge\n */\n\n// ---------------------------------------------------------------------------\n// Prototype-pollution guard — shared set of forbidden __proto__ keys\n// ---------------------------------------------------------------------------\n\nexport const FORBIDDEN_PROTO_KEYS = new Set([\n '__proto__',\n 'constructor',\n 'prototype',\n '__defineGetter__',\n '__defineSetter__',\n '__lookupGetter__',\n '__lookupSetter__',\n]);\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** True when every element is a primitive or null (no nested objects/arrays). */\nexport function isPrimitiveArray(a: unknown[]): boolean {\n return a.every((v) => v === null || (typeof v !== 'object' && typeof v !== 'function'));\n}\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface DeepMergeOptions {\n /**\n * Which side wins on collision for scalars and arrays.\n *\n * - `'prefer-patch'` (default): patch value replaces base value.\n * - `'prefer-base'`: base value is kept, patch value is ignored.\n */\n conflictResolution?: 'prefer-base' | 'prefer-patch';\n\n /**\n * How to handle array values.\n *\n * - `'replace'` (default): patch array replaces base array entirely.\n * - `'concat-primitives'`: when both values are primitive arrays,\n * they are concatenated and deduped (via Set). Non-primitive\n * arrays still replace the base wholesale.\n */\n arrayMode?: 'replace' | 'concat-primitives';\n\n /**\n * Skip prototype-pollution keys (`__proto__`, `constructor`, etc.).\n * Enabled by default. Only disable when you control both inputs\n * and the keyset (e.g. when merging trusted JSON schemas).\n */\n protectProto?: boolean;\n\n /**\n * Optional callback fired when a non-primitive (object) array is\n * replaced wholesale (only relevant with `arrayMode: 'concat-primitives'`).\n * Receives the key name, existing array length, and patch array length.\n * Used by config-loader for debug logging.\n */\n onNonPrimitiveArrayReplace?: (\n key: string,\n existingLen: number,\n patchLen: number,\n ) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\n/**\n * Recursively merge `patch` into `base`, returning a new object.\n *\n * - Nested plain objects are merged recursively.\n * - Arrays are handled per `options.arrayMode`.\n * - Scalar collisions are resolved per `options.conflictResolution`.\n * - `null` and non-object values in `patch` replace the base value\n * (unless `conflictResolution` is `'prefer-base'`).\n * - Keys in `base` that are absent from `patch` are preserved.\n * - `FORBIDDEN_PROTO_KEYS` are skipped in the patch (unless\n * `options.protectProto` is set to `false`).\n *\n * The function is generic over `T extends Record<string, unknown>` for\n * callers that pass typed config objects, but the runtime signature\n * also accepts `unknown` inputs (used by the json-path plugin).\n */\nexport function deepMerge<T extends Record<string, unknown>>(\n base: T,\n patch: Record<string, unknown>,\n options?: DeepMergeOptions,\n): T;\n\nexport function deepMerge(\n base: unknown,\n patch: unknown,\n options?: DeepMergeOptions,\n): unknown;\n\nexport function deepMerge(\n base: unknown,\n patch: unknown,\n options: DeepMergeOptions = {},\n): unknown {\n const {\n conflictResolution = 'prefer-patch',\n arrayMode = 'replace',\n protectProto = true,\n onNonPrimitiveArrayReplace,\n } = options;\n\n // Non-object / null handling — delegate to conflict resolution.\n if (typeof base !== 'object' || base === null) {\n return conflictResolution === 'prefer-patch' ? patch : base;\n }\n if (typeof patch !== 'object' || patch === null) {\n return conflictResolution === 'prefer-patch' ? patch : base;\n }\n\n // Arrays — handled *before* the object merge so array-of-objects\n // aren't accidentally treated as plain records.\n if (Array.isArray(base) && Array.isArray(patch)) {\n if (\n arrayMode === 'concat-primitives' &&\n isPrimitiveArray(base) &&\n isPrimitiveArray(patch)\n ) {\n return [...new Set([...base, ...patch])];\n }\n return conflictResolution === 'prefer-patch' ? patch : base;\n }\n\n // If only one side is an array, treat as scalar collision.\n if (Array.isArray(base) || Array.isArray(patch)) {\n return conflictResolution === 'prefer-patch' ? patch : base;\n }\n\n // Plain object merge.\n const baseObj = base as Record<string, unknown>;\n const patchObj = patch as Record<string, unknown>;\n const out: Record<string, unknown> = { ...baseObj };\n\n for (const [k, v] of Object.entries(patchObj)) {\n if (protectProto && FORBIDDEN_PROTO_KEYS.has(k)) continue;\n\n const existing = out[k];\n if (\n v !== null &&\n typeof v === 'object' &&\n !Array.isArray(v) &&\n existing !== null &&\n typeof existing === 'object' &&\n !Array.isArray(existing)\n ) {\n // Recursive merge for nested plain objects.\n out[k] = deepMerge(existing, v, options);\n } else if (Array.isArray(v) && Array.isArray(existing)) {\n // Delegate to top-level array handling so arrayMode\n // (e.g. 'concat-primitives') applies to nested arrays too.\n // Fire debug hook when a non-primitive array replaces an existing\n // array (for non-primitive arrays, concat-primitives is a no-op and\n // the result is always a wholesale replacement).\n if (onNonPrimitiveArrayReplace && !isPrimitiveArray(v)) {\n onNonPrimitiveArrayReplace(k, existing.length, v.length);\n }\n out[k] = deepMerge(existing, v, options);\n } else if (v !== undefined) {\n // Fire debug hook when a non-primitive (object) array replaces an\n // existing value in concat-primitives mode.\n if (\n onNonPrimitiveArrayReplace &&\n Array.isArray(v) &&\n !isPrimitiveArray(v)\n ) {\n const existingLen = Array.isArray(existing) ? existing.length : 0;\n onNonPrimitiveArrayReplace(k, existingLen, v.length);\n }\n out[k] = v;\n }\n // When v === undefined, leave the existing value untouched\n // (this matches config-loader's behaviour: undefined in patch\n // means \"don't change this key\").\n }\n\n return out;\n}\n","/**\n * Converts an unknown error value to a human-readable string.\n * Used in 40+ files across the codebase to normalize error messaging.\n */\nexport function toErrorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n","/** Assert a value is neither null nor undefined. Throws if it is.\n * Useful after optional chaining and indexed access when the\n * control flow guarantees the value exists but TypeScript can't\n * prove it (e.g. after a check on a related field). */\nexport function expectDefined<T>(value: T | null | undefined, label?: string): T {\n if (value === null || value === undefined) {\n const err = new Error(label ? `Expected ${label} to be defined` : 'Expected value to be defined');\n err.name = 'ExpectDefinedError';\n throw err;\n }\n return value;\n}\n","import { expectDefined } from './expect-defined.js';\nimport type { ContentBlock, ToolResultBlock, ToolUseBlock } from '../types/blocks.js';\nimport type { Message } from '../types/messages.js';\nexport interface MessageRepairReport {\n changed: boolean;\n removedToolUses: string[];\n removedToolResults: string[];\n removedMessages: number;\n}\n\nexport interface MessageRepairResult {\n messages: Message[];\n report: MessageRepairReport;\n}\n\n/**\n * Repair provider-level tool-call adjacency invariants.\n *\n * Anthropic requires every assistant `tool_use` block to have a matching\n * `tool_result` block in the immediately following user message. Manual\n * context surgery (summary/prune) can cut through the middle of such an\n * exchange. This function removes only the now-orphaned protocol blocks,\n * preserving surrounding text/images/thinking blocks where possible.\n */\nexport function repairToolUseAdjacency(messages: Message[]): MessageRepairResult {\n const removedToolUses: string[] = [];\n const removedToolResults: string[] = [];\n let removedMessages = 0;\n let changed = false;\n const out: Message[] = [];\n\n for (let i = 0; i < messages.length; i++) {\n const original = expectDefined(messages[i]);\n let msg = original;\n\n if (hasToolUse(msg)) {\n const nextIds = toolResultIds(messages[i + 1]);\n const filtered = mapContent(msg, (blocks) => {\n const next: ContentBlock[] = [];\n for (const block of blocks) {\n if (block.type === 'tool_use' && !nextIds.has(block.id)) {\n removedToolUses.push(block.id);\n changed = true;\n continue;\n }\n next.push(block);\n }\n return next;\n });\n msg = filtered ?? msg;\n }\n\n if (hasToolResult(msg)) {\n const allowed = toolUseIds(out[out.length - 1]);\n const filtered = mapContent(msg, (blocks) => {\n const next: ContentBlock[] = [];\n for (const block of blocks) {\n if (block.type === 'tool_result' && !allowed.has(block.tool_use_id)) {\n removedToolResults.push(block.tool_use_id);\n changed = true;\n continue;\n }\n next.push(block);\n }\n return next;\n });\n msg = filtered ?? msg;\n }\n\n if (isEmptyMessage(msg)) {\n removedMessages++;\n changed = true;\n continue;\n }\n out.push(msg);\n }\n\n return {\n messages: changed ? out : messages,\n report: { changed, removedToolUses, removedToolResults, removedMessages },\n };\n}\n\nfunction hasToolUse(msg: Message | undefined): boolean {\n return contentBlocks(msg).some((b): b is ToolUseBlock => b.type === 'tool_use');\n}\n\nfunction hasToolResult(msg: Message | undefined): boolean {\n return contentBlocks(msg).some((b): b is ToolResultBlock => b.type === 'tool_result');\n}\n\nfunction toolUseIds(msg: Message | undefined): Set<string> {\n const ids = new Set<string>();\n if (msg?.role !== 'assistant') return ids;\n for (const block of contentBlocks(msg)) {\n if (block.type === 'tool_use') ids.add(block.id);\n }\n return ids;\n}\n\nfunction toolResultIds(msg: Message | undefined): Set<string> {\n const ids = new Set<string>();\n if (msg?.role !== 'user') return ids;\n for (const block of contentBlocks(msg)) {\n if (block.type === 'tool_result') ids.add(block.tool_use_id);\n }\n return ids;\n}\n\nfunction contentBlocks(msg: Message | undefined): ContentBlock[] {\n return msg && Array.isArray(msg.content) ? msg.content : [];\n}\n\nfunction mapContent(\n msg: Message,\n fn: (blocks: ContentBlock[]) => ContentBlock[],\n): Message | null {\n if (!Array.isArray(msg.content)) return msg;\n const next = fn(msg.content);\n if (next.length === msg.content.length && next.every((b, idx) => b === msg.content[idx])) {\n return msg;\n }\n return { ...msg, content: next };\n}\n\nfunction isEmptyMessage(msg: Message): boolean {\n if (typeof msg.content === 'string') return msg.content.trim().length === 0;\n return msg.content.length === 0;\n}\n","/**\n * Compile a user-supplied regex with conservative bounds against ReDoS.\n *\n * Duplicated from @wrongstack/tools/_regex.ts to avoid a circular\n * dependency (tools depends on core, not vice versa). Keep both copies\n * in sync if the heuristics change.\n *\n * V8's regex engine is backtracking-based and cannot interrupt a\n * synchronous match — a pattern like `(a+)+$` against a sufficiently\n * long line will pin a worker for seconds.\n */\n\nconst MAX_PATTERN_LEN = 512;\n\n// Heuristics for catastrophic-backtracking constructs.\nconst DANGEROUS_PATTERNS: ReadonlyArray<RegExp> = [\n /(\\([^)]*[+*][^)]*\\))[+*]/, // (a+)+, (.*)+, etc\n /(\\(\\?:[^)]*[+*][^)]*\\))[+*]/, // same, with non-capturing group\n];\n\nexport interface CompileResult {\n ok: true;\n regex: RegExp;\n}\n\nexport interface CompileFail {\n ok: false;\n reason: string;\n}\n\nexport function compileUserRegex(pattern: string, flags: string): CompileResult | CompileFail {\n if (typeof pattern !== 'string') {\n return { ok: false, reason: 'pattern must be a string' };\n }\n if (pattern.length === 0) {\n return { ok: false, reason: 'pattern is empty' };\n }\n if (pattern.length > MAX_PATTERN_LEN) {\n return { ok: false, reason: `pattern exceeds ${MAX_PATTERN_LEN} characters` };\n }\n for (const rx of DANGEROUS_PATTERNS) {\n if (rx.test(pattern)) {\n return {\n ok: false,\n reason:\n 'pattern looks vulnerable to catastrophic backtracking — rewrite without nested quantifiers',\n };\n }\n }\n try {\n return { ok: true, regex: new RegExp(pattern, flags) };\n } catch (err) {\n return {\n ok: false,\n reason: err instanceof Error ? err.message : 'invalid regex',\n };\n }\n}\n","import { toErrorMessage } from './error.js';\n\nexport interface SafeParseResult<T> {\n ok: boolean;\n value?: T | undefined;\n error?: string | undefined;\n}\n\nexport function safeParse<T = unknown>(input: string, maxBytes = 5_000_000): SafeParseResult<T> {\n if (input.length > maxBytes) {\n return { ok: false, error: `Input exceeds limit (${maxBytes} bytes)` };\n }\n try {\n return { ok: true, value: JSON.parse(input) as T };\n } catch (err) {\n return {\n ok: false,\n error: toErrorMessage(err),\n };\n }\n}\n\nexport function safeStringify(value: unknown, pretty = false): string {\n const seen = new WeakSet();\n const replacer = (_k: string, v: unknown): unknown => {\n if (typeof v === 'bigint') return v.toString();\n if (v instanceof Error) {\n return { name: v.name, message: v.message, stack: v.stack };\n }\n if (typeof v === 'object' && v !== null) {\n if (seen.has(v as object)) return '[Circular]';\n seen.add(v as object);\n }\n return v;\n };\n try {\n return JSON.stringify(value, replacer, pretty ? 2 : undefined) ?? 'null';\n } catch (err) {\n return JSON.stringify({\n __serialization_error: toErrorMessage(err),\n });\n }\n}\n\n/**\n * Attempt to parse JSON5-style input and return a valid JSON string.\n * Handles trailing commas, single-line comments, and unquoted keys\n * that are common in provider output.\n *\n * Returns the sanitized string if it parses successfully as JSON,\n * or `null` if the input cannot be made valid. Callers use this to\n * decide whether to proceed with the parsed result or fall back to\n * raw handling.\n */\nexport function sanitizeJsonString(s: string): string | null {\n let out = s.trim();\n\n // Stage 1: strip single-line comments (// to end of line) that appear\n // outside of string values. This is a heuristic: comments inside strings\n // are preserved because we only strip // when preceded by a char that\n // strongly suggests we're not in a string (quote count modulo 2 is even).\n out = stripSingleLineComments(out);\n\n // Stage 2: strip trailing commas before } or ]\n out = out.replace(/,(\\s*[}\\]])/g, '$1');\n\n // Stage 3: escape literal control characters that appear *inside* string\n // values. Models frequently emit raw newlines/tabs inside a code payload\n // (e.g. edit's old_string/new_string) instead of the required \\n / \\t, which\n // makes JSON.parse throw. This is the single most common malformed-args case.\n out = escapeControlCharsInStrings(out);\n\n // Stage 4: attempt full parse; return null if it fails so callers can\n // distinguish \"already valid JSON\" from \"unrecoverable\".\n try {\n JSON.parse(out);\n return out;\n } catch {\n return null; // stripped but still not valid JSON; caller handles it\n }\n}\n\n/**\n * Walk the string tracking whether we are inside a JSON string literal and\n * replace raw control characters (U+0000–U+001F) that appear inside strings\n * with their valid JSON escape sequences. Characters outside strings are left\n * untouched (insignificant whitespace stays as-is). Already-escaped sequences\n * are not double-escaped because we only act on *literal* control bytes.\n */\nfunction escapeControlCharsInStrings(s: string): string {\n let inString = false;\n let out = '';\n for (let i = 0; i < s.length; i++) {\n const c = s.charAt(i);\n if (c === '\"' && (i === 0 || s[i - 1] !== '\\\\')) {\n inString = !inString;\n out += c;\n continue;\n }\n const code = c.charCodeAt(0);\n if (inString && code < 0x20) {\n switch (c) {\n case '\\n':\n out += '\\\\n';\n break;\n case '\\r':\n out += '\\\\r';\n break;\n case '\\t':\n out += '\\\\t';\n break;\n case '\\b':\n out += '\\\\b';\n break;\n case '\\f':\n out += '\\\\f';\n break;\n default:\n out += `\\\\u${code.toString(16).padStart(4, '0')}`;\n }\n continue;\n }\n out += c;\n }\n return out;\n}\n\nfunction stripSingleLineComments(s: string): string {\n let inString = false;\n const chars: string[] = [];\n let i = 0;\n while (i < s.length) {\n const c = s.charAt(i);\n if (c === '\"' && (i === 0 || s.charAt(i - 1) !== '\\\\')) {\n inString = !inString;\n chars.push(c);\n } else if (c === '/' && s.charAt(i + 1) === '/' && !inString) {\n // skip to end of line\n while (i < s.length && s.charAt(i) !== '\\n') i++;\n } else {\n chars.push(c);\n }\n i++;\n }\n return chars.join('');\n}\n","import * as path from 'node:path';\nimport { ERROR_CODES, FsError } from '../types/errors.js';\n\n/**\n * Resolve `<dir>/<sessionId><suffix>` for per-session sidecar files\n * (annotations, audit chain, replay log, the session JSONL itself).\n *\n * Modern session ids are date-sharded (\"2026-06-11/sess_<ULID>\"),\n * so a forward slash is a legitimate shard separator — NOT traversal.\n * Escape attempts are blocked two ways: an explicit ban on `..` and\n * backslashes, plus a resolved-path containment check that rejects any\n * id whose resolved target leaves `dir`. Character bans alone are how\n * several stores ended up throwing on every modern session id.\n */\nexport function sessionScopedPath(dir: string, sessionId: string, suffix: string): string {\n if (!sessionId || sessionId.includes('\\\\') || sessionId.includes('..')) {\n throw invalid(sessionId);\n }\n const resolved = path.resolve(dir, `${sessionId}${suffix}`);\n const rel = path.relative(path.resolve(dir), resolved);\n if (rel.startsWith('..') || path.isAbsolute(rel)) {\n throw invalid(sessionId);\n }\n return resolved;\n}\n\nfunction invalid(sessionId: string): FsError {\n return new FsError({\n message: `Invalid sessionId: ${sessionId}`,\n code: ERROR_CODES.FS_DELETE_FAILED,\n path: sessionId,\n context: { reason: 'path_traversal' },\n });\n}\n","/**\n * Turn an arbitrary string into a filesystem- and URL-safe lowercase slug.\n *\n * Collapses every run of non-alphanumeric characters into a single hyphen,\n * trims leading/trailing hyphens, and caps the length. Returns `fallback`\n * when the input slugifies to the empty string.\n *\n * Used as the stable dedup + registry key for prompts. (Distinct from the\n * project-folder slug in `wstack-paths.ts`, which has its own `'project'`\n * fallback and shorter cap.)\n */\nexport function slugify(name: string, fallback = 'prompt', maxLen = 64): string {\n return (\n name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, maxLen)\n .replace(/-+$/g, '') || fallback\n );\n}\n","import { randomBytes } from 'node:crypto';\n\n/**\n * Crockford base32 alphabet (excludes I, L, O, U to avoid ambiguity).\n */\nconst ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';\nconst ENCODING_LEN = ENCODING.length;\nconst TIME_LEN = 10;\nconst RANDOM_LEN = 16;\n\nfunction encodeTime(now: number, len: number): string {\n let mod: number;\n let str = '';\n for (let i = len - 1; i >= 0; i--) {\n mod = now % ENCODING_LEN;\n str = ENCODING[mod] + str;\n now = (now - mod) / ENCODING_LEN;\n }\n return str;\n}\n\nfunction encodeRandom(len: number): string {\n const bytes = randomBytes(len);\n let str = '';\n for (let i = 0; i < len; i++) {\n str += ENCODING[(bytes[i] as number) % ENCODING_LEN];\n }\n return str;\n}\n\n/**\n * Generate a ULID — a 26-char Crockford-base32 identifier whose first 10 chars\n * encode the millisecond timestamp (so IDs sort lexicographically by creation\n * time) followed by 16 chars of randomness. Zero runtime dependencies.\n *\n * The codebase convention is \"IDs are ULIDs\"; use this for any new store key.\n */\nexport function ulid(seedTime: number = Date.now()): string {\n return encodeTime(seedTime, TIME_LEN) + encodeRandom(RANDOM_LEN);\n}\n\n/** True for a well-formed 26-char Crockford-base32 ULID. */\nexport function isUlid(value: string): boolean {\n if (value.length !== TIME_LEN + RANDOM_LEN) return false;\n for (const ch of value) {\n if (!ENCODING.includes(ch)) return false;\n }\n return true;\n}\n","import { createHash } from 'node:crypto';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\n\n/**\n * Path layout. All developer-level state lives in ~/.wrongstack/.\n * Per-project state is keyed by sha256(absoluteProjectRoot).slice(0,12)\n * under ~/.wrongstack/projects/<hash>/.\n *\n * The ONLY thing inside the project tree is the optional\n * .wrongstack/AGENTS.md (committed) and .wrongstack/skills/ (committed).\n */\n\nexport interface WstackPaths {\n /** ~/.wrongstack — global root. */\n globalRoot: string;\n /**\n * ~/.wrongstack — directory for user-global stateful config files\n * (mode.json, theme.json, …). Currently an alias for `globalRoot`;\n * separate name lets us split out per-OS XDG_CONFIG_HOME later\n * without rewriting callers.\n */\n configDir: string;\n /** ~/.wrongstack/config.json */\n globalConfig: string;\n /** ~/.wrongstack/.key — 32 random bytes, mode 0600, AES-GCM key for the secret vault. */\n secretsKey: string;\n /** ~/.wrongstack/memory.md — user-global memory. */\n globalMemory: string;\n /** ~/.wrongstack/skills — user-global skills. */\n globalSkills: string;\n /** ~/.wrongstack/design-kits — user-global Design Studio kits. */\n globalDesignKits: string;\n /** ~/.wrongstack/prompts — user-global prompt library. */\n globalPrompts: string;\n /** ~/.wrongstack/instructions — user-global system instruction overrides. */\n globalInstructions: string;\n /** ~/.wrongstack/prompt-usage.json — per-slug insert counts (recent/popular). */\n promptUsage: string;\n /** ~/.wrongstack/cache — fetched data (models.dev, etc.). */\n cacheDir: string;\n /** ~/.wrongstack/cache/models.dev.json */\n modelsCache: string;\n /** ~/.wrongstack/cache/models-overlay.json — cached curated overlay. */\n modelsOverlayCache: string;\n /**\n * Per-project codebase symbol index (SQLite). Lives under the global project\n * dir — NOT inside the repo — so it never clutters the working tree or needs\n * gitignoring. `~/.wrongstack/projects/<hash>/codebase-index`.\n */\n projectCodebaseIndex: string;\n /** ~/.wrongstack/history — REPL line history. */\n historyFile: string;\n /** ~/.wrongstack/logs/wrongstack.log */\n logFile: string;\n /** ~/.wrongstack/projects/<hash> */\n projectDir: string;\n /** ~/.wrongstack/projects/<hash>/memory.md */\n projectMemory: string;\n /** ~/.wrongstack/projects/<hash>/sessions */\n projectSessions: string;\n /** ~/.wrongstack/projects/<hash>/trust.json */\n projectTrust: string;\n /** ~/.wrongstack/projects/<hash>/meta.json */\n projectMeta: string;\n /** ~/.wrongstack/projects/<hash>/config.local.json — optional override */\n projectLocalConfig: string;\n /** <project>/.wrongstack/config.json — per-project settings (safe fields only).\n * This lives inside the project root so it can be gitignored or shared. */\n inProjectConfig: string;\n /** <project>/.wrongstack/AGENTS.md — committed project memory. */\n inProjectAgentsFile: string;\n /** <project>/.wrongstack/skills — committed project skills. */\n inProjectSkills: string;\n /** <project>/.wrongstack/prompts — committed project prompt library. */\n inProjectPrompts: string;\n /** <project>/.wrongstack/instructions — committed project instruction overrides. */\n inProjectInstructions: string;\n /** <project>/.wrongstack/design-kits — committed project Design Studio kits. */\n inProjectDesignKits: string;\n /** <project>/.wrongstack/worktrees — git worktrees for per-phase isolation (gitignored). */\n inProjectWorktrees: string;\n /** Stable hash for the project root. */\n projectHash: string;\n /** Human-readable project slug: `wrongstack-a1b2c3` instead of `3024e5e6fa58`. */\n projectSlug: string;\n /** ~/.wrongstack/projects/<hash>/goal.json — goal persistence */\n projectGoal: string;\n /** ~/.wrongstack/projects/<hash>/specs — SDD spec files */\n projectSpecs: string;\n /** ~/.wrongstack/projects/<hash>/task-graphs — SDD task graphs */\n projectTaskGraphs: string;\n /** ~/.wrongstack/projects/<hash>/sdd-session.json — SDD session state */\n projectSddSession: string;\n /** ~/.wrongstack/projects/<hash>/plan.json — plan persistence */\n projectPlan: string;\n /** ~/.wrongstack/projects/<hash>/autophase — AutoPhase phase-graph JSON files */\n projectAutophase: string;\n /** ~/.wrongstack/projects/<hash>/sdd-boards — live SDD board snapshots + JSONL event logs */\n projectSddBoards: string;\n /** ~/.wrongstack/sync.json — CloudSync configuration */\n syncConfig: string;\n /** Function to get the status.json path for a project given its hash. */\n projectStatus: (projectHash: string) => string;\n}\n\nexport function projectHash(absRoot: string): string {\n return createHash('sha256').update(path.resolve(absRoot)).digest('hex').slice(0, 12);\n}\n\n/**\n * Human-readable project directory name: slugified folder name + short hash\n * suffix for uniqueness. e.g. `wrongstack-a1b2c3` instead of `3024e5e6fa58`.\n */\nexport function projectSlug(absRoot: string): string {\n const base = slugify(path.basename(absRoot));\n const hash = createHash('sha256').update(path.resolve(absRoot)).digest('hex').slice(0, 6);\n return `${base}-${hash}`;\n}\n\n/** Turn a folder name into a filesystem-safe lowercase slug. */\nfunction slugify(name: string): string {\n return (\n name\n .toLowerCase()\n // Collapse any run of non-alphanumeric chars into a single hyphen.\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 40) || 'project'\n );\n}\n\nexport interface WstackPathOptions {\n userHome?: string | undefined;\n projectRoot: string;\n /** Override the global root (e.g. for tests). Default: `${userHome}/.wrongstack`. */\n globalRoot?: string | undefined;\n}\n\n/**\n * The global `~/.wrongstack` root, honoring the `WRONGSTACK_HOME` env\n * override. The override exists so tests (and sandboxed runs) can redirect\n * ALL global state — config, secrets, logs, projects/, mailboxes — away from\n * the real user home. Before it existed, `pnpm test` booted runtimes against\n * the real `~/.wrongstack`: it read the user's real config.json (starting a\n * second live Telegram poller), appended to the real wrongstack.log, and left\n * ~20k orphaned fixture dirs under projects/.\n *\n * Every code path that wants the global dir must come through here (or\n * through `resolveWstackPaths`) instead of `path.join(os.homedir(), '.wrongstack')`.\n */\nexport function wstackGlobalRoot(): string {\n const fromEnv = process.env['WRONGSTACK_HOME'];\n if (fromEnv && fromEnv.trim().length > 0) return path.resolve(fromEnv);\n return path.join(os.homedir(), '.wrongstack');\n}\n\nexport function resolveWstackPaths(opts: WstackPathOptions): WstackPaths {\n // Precedence: explicit globalRoot > explicit userHome (callers/tests that\n // pass one expect paths under it) > WRONGSTACK_HOME env > real home dir.\n const globalRoot =\n opts.globalRoot ?? (opts.userHome ? path.join(opts.userHome, '.wrongstack') : wstackGlobalRoot());\n const hash = projectHash(opts.projectRoot);\n const slug = projectSlug(opts.projectRoot);\n const projectDir = path.join(globalRoot, 'projects', slug);\n return {\n globalRoot,\n configDir: globalRoot,\n globalConfig: path.join(globalRoot, 'config.json'),\n secretsKey: path.join(globalRoot, '.key'),\n globalMemory: path.join(globalRoot, 'memory.md'),\n globalSkills: path.join(globalRoot, 'skills'),\n globalDesignKits: path.join(globalRoot, 'design-kits'),\n globalPrompts: path.join(globalRoot, 'prompts'),\n globalInstructions: path.join(globalRoot, 'instructions'),\n promptUsage: path.join(globalRoot, 'prompt-usage.json'),\n cacheDir: path.join(globalRoot, 'cache'),\n modelsCache: path.join(globalRoot, 'cache', 'models.dev.json'),\n modelsOverlayCache: path.join(globalRoot, 'cache', 'models-overlay.json'),\n historyFile: path.join(globalRoot, 'history'),\n logFile: path.join(globalRoot, 'logs', 'wrongstack.log'),\n projectDir,\n projectCodebaseIndex: path.join(projectDir, 'codebase-index'),\n projectMemory: path.join(projectDir, 'memory.md'),\n projectSessions: path.join(projectDir, 'sessions'),\n projectTrust: path.join(projectDir, 'trust.json'),\n projectMeta: path.join(projectDir, 'meta.json'),\n projectLocalConfig: path.join(projectDir, 'config.local.json'),\n inProjectConfig: path.join(opts.projectRoot, '.wrongstack', 'config.json'),\n inProjectAgentsFile: path.join(opts.projectRoot, '.wrongstack', 'AGENTS.md'),\n inProjectSkills: path.join(opts.projectRoot, '.wrongstack', 'skills'),\n inProjectPrompts: path.join(opts.projectRoot, '.wrongstack', 'prompts'),\n inProjectInstructions: path.join(opts.projectRoot, '.wrongstack', 'instructions'),\n inProjectDesignKits: path.join(opts.projectRoot, '.wrongstack', 'design-kits'),\n inProjectWorktrees: path.join(opts.projectRoot, '.wrongstack', 'worktrees'),\n projectHash: hash,\n projectSlug: slug,\n projectGoal: path.join(projectDir, 'goal.json'),\n projectSpecs: path.join(projectDir, 'specs'),\n projectTaskGraphs: path.join(projectDir, 'task-graphs'),\n projectSddSession: path.join(projectDir, 'sdd-session.json'),\n projectPlan: path.join(projectDir, 'plan.json'),\n projectAutophase: path.join(projectDir, 'autophase'),\n projectSddBoards: path.join(projectDir, 'sdd-boards'),\n syncConfig: path.join(globalRoot, 'sync.json'),\n projectStatus: (projectHash: string) => path.join(globalRoot, 'projects', projectHash, 'status.json'),\n };\n}\n","import { toErrorMessage } from '../utils/index.js';\n\n/**\n * WrongStack error hierarchy.\n *\n * Every error thrown by the framework is a `WrongStackError` with a\n * machine-readable `code`, a `subsystem` tag, and a `severity` level.\n * This lets consumers (CLI, TUI, plugins, tests) branch on structured\n * data instead of parsing error messages.\n */\n\n// ── Error codes ──────────────────────────────────────────────────────\n\n/**\n * Machine-readable error codes as frozen constants.\n *\n * Use `ERROR_CODES.X` instead of raw string literals for:\n * - IDE autocomplete and compile-time validation\n * - Safe refactoring (rename updates all usages)\n * - Plugin extensibility (extend the object to add custom codes)\n *\n * The `ErrorCode` type is derived from this object, so adding a new\n * code here automatically updates the type without extra changes.\n */\nexport const ERROR_CODES = {\n // Provider\n PROVIDER_RATE_LIMITED: 'PROVIDER_RATE_LIMITED',\n PROVIDER_AUTH_FAILED: 'PROVIDER_AUTH_FAILED',\n PROVIDER_OVERLOADED: 'PROVIDER_OVERLOADED',\n PROVIDER_INVALID_REQUEST: 'PROVIDER_INVALID_REQUEST',\n PROVIDER_SERVER_ERROR: 'PROVIDER_SERVER_ERROR',\n PROVIDER_NETWORK_ERROR: 'PROVIDER_NETWORK_ERROR',\n PROVIDER_CONTEXT_OVERFLOW: 'PROVIDER_CONTEXT_OVERFLOW',\n // Tool\n TOOL_NOT_FOUND: 'TOOL_NOT_FOUND',\n TOOL_PERMISSION_DENIED: 'TOOL_PERMISSION_DENIED',\n TOOL_EXECUTION_FAILED: 'TOOL_EXECUTION_FAILED',\n TOOL_TIMEOUT: 'TOOL_TIMEOUT',\n TOOL_INPUT_INVALID: 'TOOL_INPUT_INVALID',\n // Config\n CONFIG_INVALID: 'CONFIG_INVALID',\n CONFIG_NOT_FOUND: 'CONFIG_NOT_FOUND',\n CONFIG_PARSE_FAILED: 'CONFIG_PARSE_FAILED',\n CONFIG_MIGRATION_NEEDED: 'CONFIG_MIGRATION_NEEDED',\n // Plugin\n PLUGIN_LOAD_FAILED: 'PLUGIN_LOAD_FAILED',\n PLUGIN_API_MISMATCH: 'PLUGIN_API_MISMATCH',\n PLUGIN_MISSING_DEPENDENCY: 'PLUGIN_MISSING_DEPENDENCY',\n // Agent\n AGENT_ITERATION_LIMIT: 'AGENT_ITERATION_LIMIT',\n AGENT_CONTEXT_OVERFLOW: 'AGENT_CONTEXT_OVERFLOW',\n AGENT_ABORTED: 'AGENT_ABORTED',\n AGENT_RUN_FAILED: 'AGENT_RUN_FAILED',\n // Session\n SESSION_NOT_FOUND: 'SESSION_NOT_FOUND',\n SESSION_CORRUPTED: 'SESSION_CORRUPTED',\n SESSION_WRITE_FAILED: 'SESSION_WRITE_FAILED',\n // Container / Registry\n CONTAINER_TOKEN_ALREADY_BOUND: 'CONTAINER_TOKEN_ALREADY_BOUND',\n CONTAINER_TOKEN_NOT_BOUND: 'CONTAINER_TOKEN_NOT_BOUND',\n CONTAINER_CIRCULAR_DEPENDENCY: 'CONTAINER_CIRCULAR_DEPENDENCY',\n REGISTRY_DUPLICATE: 'REGISTRY_DUPLICATE',\n REGISTRY_NOT_FOUND: 'REGISTRY_NOT_FOUND',\n REGISTRY_INVALID: 'REGISTRY_INVALID',\n // File system\n FS_READ_FAILED: 'FS_READ_FAILED',\n FS_WRITE_FAILED: 'FS_WRITE_FAILED',\n FS_MKDIR_FAILED: 'FS_MKDIR_FAILED',\n FS_DELETE_FAILED: 'FS_DELETE_FAILED',\n FS_ATOMIC_WRITE_FAILED: 'FS_ATOMIC_WRITE_FAILED',\n // SDD (Spec-Driven Development)\n SDD_VALIDATION_FAILED: 'SDD_VALIDATION_FAILED',\n SDD_PARSE_FAILED: 'SDD_PARSE_FAILED',\n SDD_INVALID_STATE: 'SDD_INVALID_STATE',\n SDD_NOT_READY: 'SDD_NOT_READY',\n // General\n VALIDATION_ERROR: 'VALIDATION_ERROR',\n PARSE_FAILED: 'PARSE_FAILED',\n UNKNOWN: 'UNKNOWN',\n} as const;\n\n/**\n * Union type derived from `ERROR_CODES`. Using `typeof ERROR_CODES[keyof typeof ERROR_CODES]`\n * instead of a string literal union means TypeScript auto-updates the type whenever\n * a new code is added to `ERROR_CODES` — no need to keep two lists in sync.\n */\nexport type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES];\n\nexport type ErrorSubsystem =\n | 'provider'\n | 'tool'\n | 'config'\n | 'plugin'\n | 'agent'\n | 'session'\n | 'sdd'\n | 'container'\n | 'fs'\n | 'general';\nexport type ErrorSeverity = 'fatal' | 'error' | 'warning';\n\n// ── Base error class ─────────────────────────────────────────────────\n\nexport class WrongStackError extends Error {\n readonly code: ErrorCode;\n readonly subsystem: ErrorSubsystem;\n readonly severity: ErrorSeverity;\n readonly recoverable: boolean;\n readonly context?: Record<string, unknown> | undefined;\n\n constructor(opts: {\n message: string;\n code: ErrorCode;\n subsystem: ErrorSubsystem;\n severity?: ErrorSeverity | undefined;\n recoverable?: boolean | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super(opts.message, { cause: opts.cause });\n this.name = 'WrongStackError';\n this.code = opts.code;\n this.subsystem = opts.subsystem;\n this.severity = opts.severity ?? 'error';\n this.recoverable = opts.recoverable ?? false;\n this.context = opts.context;\n }\n\n /**\n * Render a one-line user-facing description.\n * Subclasses should override for domain-specific formatting.\n */\n describe(): string {\n const ctx = this.context ? ` ${formatContext(this.context)}` : '';\n return `${this.code}: ${this.message}${ctx}`;\n }\n}\n\nfunction formatContext(ctx: Record<string, unknown>): string {\n const parts = Object.entries(ctx)\n .filter(([, v]) => v !== undefined)\n .slice(0, 3)\n .map(([k, v]) => `${k}=${String(v)}`);\n return parts.length > 0 ? `[${parts.join(' ')}]` : '';\n}\n\n// ── Specific error classes ───────────────────────────────────────────\n\n/**\n * Tool execution errors — thrown by ToolExecutor and individual tools.\n */\nexport class ToolError extends WrongStackError {\n readonly toolName: string;\n\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n | 'TOOL_NOT_FOUND'\n | 'TOOL_PERMISSION_DENIED'\n | 'TOOL_EXECUTION_FAILED'\n | 'TOOL_TIMEOUT'\n | 'TOOL_INPUT_INVALID'\n >;\n toolName: string;\n recoverable?: boolean | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'tool',\n recoverable: opts.recoverable,\n context: { tool: opts.toolName, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'ToolError';\n this.toolName = opts.toolName;\n }\n}\n\n/**\n * Config loading / validation errors.\n */\nexport class ConfigError extends WrongStackError {\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'CONFIG_INVALID' | 'CONFIG_NOT_FOUND' | 'CONFIG_PARSE_FAILED' | 'CONFIG_MIGRATION_NEEDED'\n >;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'config',\n severity: 'fatal',\n recoverable: false,\n context: opts.context,\n cause: opts.cause,\n });\n this.name = 'ConfigError';\n }\n}\n\n/**\n * Plugin loading / lifecycle errors.\n */\nexport class PluginError extends WrongStackError {\n readonly pluginName: string;\n\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'PLUGIN_LOAD_FAILED' | 'PLUGIN_API_MISMATCH' | 'PLUGIN_MISSING_DEPENDENCY'\n >;\n pluginName: string;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'plugin',\n severity: 'error',\n recoverable: opts.code === ERROR_CODES.PLUGIN_MISSING_DEPENDENCY,\n context: { plugin: opts.pluginName, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'PluginError';\n this.pluginName = opts.pluginName;\n }\n}\n\n/**\n * Agent runtime errors — thrown by Agent.run when a non-WrongStackError\n * escapes the inner loop, so callers always see a structured error.\n */\nexport class AgentError extends WrongStackError {\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'AGENT_ITERATION_LIMIT' | 'AGENT_CONTEXT_OVERFLOW' | 'AGENT_ABORTED' | 'AGENT_RUN_FAILED'\n >;\n recoverable?: boolean | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'agent',\n severity: opts.code === ERROR_CODES.AGENT_ABORTED ? 'warning' : 'error',\n recoverable: opts.recoverable ?? opts.code === ERROR_CODES.AGENT_ITERATION_LIMIT,\n context: opts.context,\n cause: opts.cause,\n });\n this.name = 'AgentError';\n }\n}\n\n/**\n * Wrap an arbitrary thrown value into a `WrongStackError` so the caller\n * always gets a structured error. Pass-throughs WrongStackError instances\n * unchanged; raw `Error`s and primitives get an `AGENT_RUN_FAILED` wrapper\n * with the original preserved as `cause`.\n */\nexport function toWrongStackError(\n err: unknown,\n code: Extract<ErrorCode, 'AGENT_RUN_FAILED' | 'AGENT_ABORTED' | 'UNKNOWN'> = ERROR_CODES.AGENT_RUN_FAILED,\n): WrongStackError {\n if (err instanceof WrongStackError) return err;\n const message = toErrorMessage(err);\n return new AgentError({\n message,\n code: code === 'UNKNOWN' ? ERROR_CODES.AGENT_RUN_FAILED : code,\n cause: err,\n });\n}\n\n/**\n * Session storage errors.\n */\nexport class SessionError extends WrongStackError {\n readonly sessionId?: string | undefined;\n\n constructor(opts: {\n message: string;\n code: Extract<ErrorCode, 'SESSION_NOT_FOUND' | 'SESSION_CORRUPTED' | 'SESSION_WRITE_FAILED'>;\n sessionId?: string | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'session',\n severity: opts.code === ERROR_CODES.SESSION_WRITE_FAILED ? 'error' : 'warning',\n recoverable: opts.code !== ERROR_CODES.SESSION_CORRUPTED,\n context: { sessionId: opts.sessionId, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'SessionError';\n this.sessionId = opts.sessionId;\n }\n}\n\n/**\n * SDD (Spec-Driven Development) errors — spec validation, parsing, and\n * state machine violations in the AISpecBuilder, TaskFlow, and TaskTracker.\n */\nexport class SddError extends WrongStackError {\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'SDD_VALIDATION_FAILED' | 'SDD_PARSE_FAILED' | 'SDD_INVALID_STATE' | 'SDD_NOT_READY'\n >;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'sdd',\n severity: opts.code === ERROR_CODES.SDD_PARSE_FAILED ? 'warning' : 'error',\n recoverable: opts.code === ERROR_CODES.SDD_NOT_READY,\n context: opts.context,\n cause: opts.cause,\n });\n this.name = 'SddError';\n }\n}\n\n/**\n * File system operation errors.\n */\nexport class FsError extends WrongStackError {\n readonly path?: string | undefined;\n\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'FS_READ_FAILED' | 'FS_WRITE_FAILED' | 'FS_MKDIR_FAILED' | 'FS_DELETE_FAILED' | 'FS_ATOMIC_WRITE_FAILED'\n >;\n path?: string | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'fs',\n severity: 'error',\n recoverable: opts.code !== ERROR_CODES.FS_READ_FAILED,\n context: { path: opts.path, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'FsError';\n this.path = opts.path;\n }\n}\n\n/**\n * HTTP fetch error — thrown when a network request returns a non-OK status.\n * Carries the response status so {@link classifyToolError} can branch on it\n * (429 → transient, 404 → not_found, 401 → permission) without duck-typing\n * the error via `'response' in err`.\n *\n * P3 #18 (before-release.md): the previous `'response' in err` check caught\n * any Error with a `response` property, including custom errors, proxy\n * objects, or mocked errors in tests. `instanceof FetchError` is reliable.\n *\n * Tools and providers that make HTTP requests and need the executor to\n * classify their failures should throw `new FetchError({ status, message })`\n * instead of a bare `Error` with an ad-hoc `response` field.\n */\nexport class FetchError extends WrongStackError {\n readonly status: number;\n\n constructor(opts: {\n message: string;\n status: number;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: ERROR_CODES.VALIDATION_ERROR,\n subsystem: 'general',\n severity: 'error',\n recoverable: opts.status === 429 || opts.status >= 500,\n context: { status: opts.status, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'FetchError';\n this.status = opts.status;\n }\n}\n\n/**\n * Tool input validation error — thrown when a tool's input fails a validation\n * check that the JSON Schema cannot express (e.g. `old_string === new_string`\n * in edit, or a cross-field invariant). Use this instead of a bare\n * `throw new Error('...validation...')` so {@link classifyToolError} can\n * match on `instanceof` rather than a locale-dependent message substring.\n *\n * P2 #6 (before-release.md): the previous `err.message.includes('validation')`\n * check misclassified any error whose message happened to contain \"validation\"\n * (e.g. a third-party \"input validation timeout\") as a VALIDATION error.\n *\n * Named `ToolValidationError` (not `ValidationError`) to avoid colliding with\n * the existing `ValidationError` interface exported by json-schema-validate.ts\n * (a validation-result shape, not an Error subclass).\n */\nexport class ToolValidationError extends WrongStackError {\n constructor(opts: {\n message: string;\n /** Field path or tool name that failed validation, for diagnostics. */\n field?: string | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: ERROR_CODES.VALIDATION_ERROR,\n subsystem: 'general',\n severity: 'error',\n recoverable: false,\n context: { field: opts.field, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'ToolValidationError';\n }\n}\n\n/**\n * Response / payload parse error — thrown when an upstream HTTP response,\n * file, or data structure is well-formed at the transport layer (HTTP 200,\n * valid JSON) but is missing required fields or has an unexpected shape.\n *\n * Distinct from `ConfigError(CONFIG_PARSE_FAILED)` (which is specifically\n * for config-file parsing) and `FetchError` (which covers HTTP non-OK\n * responses). `ParseError` fills the gap: the request succeeded but the\n * response body couldn't be interpreted.\n *\n * Common sites: OAuth token responses missing `access_token`, device-code\n * responses missing `device_code`, registry responses with unexpected\n * schemas.\n */\nexport class ParseError extends WrongStackError {\n readonly source?: string | undefined;\n\n constructor(opts: {\n message: string;\n /**\n * What was being parsed — e.g. `'oauth-token-response'`,\n * `'device-code-response'`. Lets consumers distinguish parse failures\n * from different upstream APIs without parsing the message.\n */\n source?: string | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: ERROR_CODES.PARSE_FAILED,\n subsystem: 'general',\n severity: 'error',\n recoverable: false,\n context: { source: opts.source, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'ParseError';\n this.source = opts.source;\n }\n}\n\n// ── Type guards ──────────────────────────────────────────────────────\n\nexport function isWrongStackError(err: unknown): err is WrongStackError {\n return err instanceof WrongStackError;\n}\n\nexport function isToolError(err: unknown): err is ToolError {\n return err instanceof ToolError;\n}\n\nexport function isConfigError(err: unknown): err is ConfigError {\n return err instanceof ConfigError;\n}\n\nexport function isPluginError(err: unknown): err is PluginError {\n return err instanceof PluginError;\n}\n\nexport function isSessionError(err: unknown): err is SessionError {\n return err instanceof SessionError;\n}\n\nexport function isAgentError(err: unknown): err is AgentError {\n return err instanceof AgentError;\n}\n\nexport function isFsError(err: unknown): err is FsError {\n return err instanceof FsError;\n}\n\nexport function isToolValidationError(err: unknown): err is ToolValidationError {\n return err instanceof ToolValidationError;\n}\n\nexport function isFetchError(err: unknown): err is FetchError {\n return err instanceof FetchError;\n}\n\nexport function isParseError(err: unknown): err is ParseError {\n return err instanceof ParseError;\n}\n\nexport function isSddError(err: unknown): err is SddError {\n return err instanceof SddError;\n}\n","import { randomBytes } from 'node:crypto';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { FsError } from '../types/errors.js';\n\nexport interface AtomicWriteOptions {\n mode?: number | undefined;\n encoding?: BufferEncoding | undefined;\n}\n\nexport interface FileLockOptions {\n timeoutMs?: number | undefined;\n staleMs?: number | undefined;\n}\n\nexport async function atomicWrite(\n targetPath: string,\n content: string | Uint8Array,\n opts: AtomicWriteOptions = {},\n): Promise<void> {\n const dir = path.dirname(targetPath);\n await fs.mkdir(dir, { recursive: true });\n const tmp = path.join(dir, `.${path.basename(targetPath)}.${randomBytes(6).toString('hex')}.tmp`);\n\n // Write content to tmp first; 'wx' ensures exclusive creation (fails if\n // tmp already exists — extremely unlikely with 6-byte random suffix).\n try {\n if (typeof content === 'string') {\n await fs.writeFile(tmp, content, { flag: 'wx', encoding: opts.encoding ?? 'utf8' });\n } else {\n await fs.writeFile(tmp, content, { flag: 'wx' });\n }\n try {\n const fh = await fs.open(tmp, 'r+');\n try {\n await fh.sync();\n } finally {\n await fh.close();\n }\n } catch {\n // fsync best-effort\n }\n // Now safely read mode from target (if it exists) and apply to tmp before rename.\n // Prefer opts.mode for new files; for existing files preserve their mode.\n let mode: number | undefined;\n try {\n const stat = await fs.stat(targetPath);\n mode = stat.mode & 0o777;\n } catch {\n mode = opts.mode;\n }\n if (mode !== undefined) {\n await fs.chmod(tmp, mode);\n }\n await renameWithRetry(tmp, targetPath);\n // P3 #20 (before-release.md): on Windows, fs.rename (MoveFileExW) does\n // not preserve Unix permission bits — the chmod above applies to the tmp\n // file, but the rename may reset the destination's mode to the Windows\n // default. Re-apply the mode after rename on win32 so an edited file\n // keeps its executable bit (or any non-default permission). On POSIX,\n // rename preserves metadata so this is a no-op (chmod is idempotent and\n // cheap), but we gate it on win32 to avoid the extra stat+chmod on the\n // common path.\n if (mode !== undefined && process.platform === 'win32') {\n try {\n await fs.chmod(targetPath, mode);\n } catch {\n // Best-effort: a transient EPERM (antivirus lock) should not fail\n // the write — the content is already on disk.\n }\n }\n } catch (err) {\n try {\n await fs.unlink(tmp);\n } catch {\n // ignore cleanup error\n }\n throw err;\n }\n}\n\nexport async function ensureDir(dir: string): Promise<void> {\n await fs.mkdir(dir, { recursive: true });\n}\n\nexport async function withFileLock<T>(\n targetPath: string,\n fn: () => Promise<T>,\n opts: FileLockOptions = {},\n): Promise<T> {\n const dir = path.dirname(targetPath);\n await fs.mkdir(dir, { recursive: true });\n const lockPath = path.join(dir, `.${path.basename(targetPath)}.lock`);\n const timeoutMs = opts.timeoutMs ?? 5_000;\n const staleMs = opts.staleMs ?? 30_000;\n const started = Date.now();\n let handle: fs.FileHandle | undefined;\n\n for (;;) {\n try {\n handle = await fs.open(lockPath, 'wx');\n await handle.writeFile(`${process.pid}:${Date.now()}`);\n break;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n // ENOENT means the directory was deleted (e.g. by concurrent cleanup).\n // Recreate it and retry acquiring the lock.\n if (code === 'ENOENT') {\n await fs.mkdir(dir, { recursive: true });\n continue;\n }\n if (code !== 'EEXIST') throw err;\n try {\n const stat = await fs.stat(lockPath);\n if (Date.now() - stat.mtimeMs > staleMs) {\n await fs.unlink(lockPath);\n continue;\n }\n } catch {\n continue;\n }\n if (Date.now() - started >= timeoutMs) {\n throw new FsError({\n message: `Timed out waiting for file lock: ${targetPath}`,\n code: 'FS_ATOMIC_WRITE_FAILED',\n path: targetPath,\n context: { timeoutMs },\n });\n }\n await new Promise((resolve) => setTimeout(resolve, 25));\n }\n }\n\n try {\n return await fn();\n } finally {\n try {\n await handle?.close();\n } catch {\n // ignore\n }\n try {\n await fs.unlink(lockPath);\n } catch {\n // ignore\n }\n }\n}\n\n// On Windows, fs.rename over an existing file can fail with EPERM/EBUSY/EACCES\n// when antivirus, file indexers, editor file watchers, or a concurrent writer\n// briefly hold a handle on the destination. These are transient — retry with a\n// short backoff before giving up. POSIX renames are atomic and won't hit this.\nconst TRANSIENT_RENAME_CODES = new Set(['EPERM', 'EBUSY', 'EACCES', 'ENOTEMPTY']);\n\nasync function renameWithRetry(from: string, to: string): Promise<void> {\n if (process.platform !== 'win32') {\n await fs.rename(from, to);\n return;\n }\n const delays = [10, 25, 60, 120, 250];\n let lastErr: unknown;\n for (let i = 0; i <= delays.length; i++) {\n try {\n await fs.rename(from, to);\n return;\n } catch (err) {\n lastErr = err;\n const code = (err as NodeJS.ErrnoException)?.code;\n if (!code || !TRANSIENT_RENAME_CODES.has(code) || i === delays.length) {\n throw err;\n }\n await new Promise((resolve) => setTimeout(resolve, delays[i]));\n }\n }\n throw lastErr;\n}\n","import type { ContentBlock } from '../types/blocks.js';\n\n/**\n * Derive a short title from a user_input event's content. Used by both\n * `DefaultSessionStore.summarize()` (offline summary rebuild) and\n * `FileSessionWriter.observeForSummary()` (live tracking), so it lives\n * here to avoid a bidirectional import between those two modules.\n */\nexport function userInputTitle(content: string | ContentBlock[]): string {\n const text =\n typeof content === 'string'\n ? content\n : content\n .filter((b): b is { type: 'text'; text: string } => b.type === 'text')\n .map((b) => b.text)\n .join(' ');\n return (text || '(non-text input)').slice(0, 60);\n}\n","import * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { EventBus } from '../kernel/events.js';\nimport type {\n FileSnapshot,\n SessionEvent,\n SessionMetadata,\n SessionSummary,\n SessionWriter,\n} from '../types/session.js';\nimport type { SecretScrubber } from '../types/secret-scrubber.js';\nimport { atomicWrite } from '../utils/atomic-write.js';\nimport { toErrorMessage } from '../utils/index.js';\nimport { userInputTitle } from './session-helpers.js';\n\n/**\n * Append-mode JSONL session writer with batched writes, write serialization,\n * and enriched summary tracking.\n *\n * Extracted from session-store.ts to keep each module focused: this class\n * owns the per-session write path (append/flush/close/checkpoint/truncate),\n * while `DefaultSessionStore` owns the store-level read/list/index/delete path.\n */\nexport class FileSessionWriter implements SessionWriter {\n private closed = false;\n private closePromise: Promise<void> | null = null;\n private manifestFile: string;\n private summary: SessionSummary;\n private tokenIn = 0;\n private tokenOut = 0;\n private readonly filePath: string;\n get transcriptPath(): string | undefined {\n return this.filePath || undefined;\n }\n /**\n * Lazy session_start/session_resumed init, shared by all appenders.\n * A single promise (not a boolean) so a second append racing the first\n * can't push its event into the buffer BEFORE the first append's event —\n * every appender awaits the same init and resumes in FIFO call order.\n */\n private initPromise: Promise<void> | null = null;\n private ensureInit(): Promise<void> {\n if (!this.initPromise) this.initPromise = this.writeSessionStartLazy();\n return this.initPromise;\n }\n private readonly resumed: boolean;\n private appendFailCount = 0;\n private lastAppendWarnAt = 0;\n private readonly secretScrubber?: SecretScrubber | undefined;\n private readonly onCloseCb?: (((summary: SessionSummary) => void | Promise<void>)) | undefined;\n /** Implements SessionWriter.traceId — propagated from ContextInit.traceId. */\n traceId: string | undefined;\n\n // ── Write buffer — batches events to reduce per-event disk I/O ──────────────\n //\n // Every append() pushes the scrubbed event into an in-memory buffer instead\n // of calling handle.appendFile() synchronously. The buffer flushes to disk\n // when it reaches FLUSH_SIZE events OR after FLUSH_INTERVAL_MS of inactivity.\n // This cuts the number of disk writes by ~95% without changing the on-disk\n // format — the JSONL is still one JSON object per line.\n private writeBuffer: SessionEvent[] = [];\n private flushTimer: ReturnType<typeof setTimeout> | null = null;\n private static readonly FLUSH_INTERVAL_MS = 500;\n private static readonly FLUSH_SIZE = 50;\n\n // ── Write serialization ─────────────────────────────────────────────────────\n //\n // All disk writes are funneled through a FIFO promise chain. Without it,\n // a timer-driven flush racing an explicit flush()/close() issues two\n // concurrent appendFile() calls on the shared O_APPEND handle — the kernel\n // may complete them out of order (chronology breaks) or, for large\n // batches, interleave partial writes (torn JSONL lines). The chain keeps\n // exactly one write in flight; failures don't break the chain.\n private writeChain: Promise<void> = Promise.resolve();\n\n /** Enqueue a write on the FIFO chain. Resolves/rejects with that write. */\n private enqueueWrite(data: string): Promise<void> {\n const write = this.writeChain.then(() => this.handle.appendFile(data, 'utf8'));\n this.writeChain = write.then(\n () => undefined,\n () => undefined,\n );\n return write;\n }\n\n // ── Enriched summary tracking ───────────────────────────────────────────────\n private iterationCount = 0;\n private toolCallCount = 0;\n private toolErrorCount = 0;\n private toolBreakdown: Record<string, number> = {};\n private fileChangeCount = 0;\n private compactionCount = 0;\n private outcome: SessionSummary['outcome'] = undefined;\n\n /**\n * Scrub secrets out of conversation-turn events before they are observed\n * for the summary, written to the JSONL log, or surfaced on resume. Only\n * `user_input` / `llm_response` carry free-form user/model text; other event\n * types either have no secret-bearing content or are already scrubbed\n * upstream (tool results). Returns the event unchanged when no scrubber is\n * configured.\n */\n private scrubEvent(event: SessionEvent): SessionEvent {\n const s = this.secretScrubber;\n if (!s) return event;\n if (event.type === 'user_input') {\n return {\n ...event,\n content:\n typeof event.content === 'string' ? s.scrub(event.content) : s.scrubObject(event.content),\n };\n }\n if (event.type === 'llm_response') {\n return { ...event, content: s.scrubObject(event.content) };\n }\n return event;\n }\n\n private pendingFileSnapshots: Array<{\n path: string;\n action: 'created' | 'modified' | 'deleted';\n before: string | null;\n after: string | null;\n }> = [];\n /** Tracks open tool_use IDs during the current run to serialize on close for resume. */\n private openToolUses = new Set<string>();\n\n recordFileChange(input: {\n path: string;\n action: 'created' | 'modified' | 'deleted';\n before: string | null;\n after: string | null;\n }): void {\n this.pendingFileSnapshots.push(input);\n }\n\n recordSideEffect(input: {\n toolUseId: string;\n toolName: string;\n input: Record<string, unknown>;\n outcome?: string | undefined;\n risk: 'fs.write' | 'shell' | 'package' | 'network' | 'config';\n }): void {\n // Fire-and-forget — side-effect recording must never block tool execution.\n this.append({\n type: 'side_effect',\n ts: new Date().toISOString(),\n toolUseId: input.toolUseId,\n toolName: input.toolName,\n input: input.input,\n outcome: input.outcome,\n risk: input.risk,\n }).catch(() => { /* best-effort */ });\n }\n\n constructor(\n public readonly id: string,\n private handle: fsp.FileHandle,\n private readonly startedAt: string,\n private readonly meta: Omit<SessionMetadata, 'startedAt'>,\n private readonly events?: EventBus | undefined,\n opts: {\n resumed?: boolean | undefined;\n dir?: string | undefined;\n filePath?: string | undefined;\n secretScrubber?: SecretScrubber | undefined;\n /** Called on close() with the finalized summary for index/sidecar writes. */\n onClose?: (((summary: SessionSummary) => void | Promise<void>)) | undefined;\n } = {},\n traceId?: string | undefined,\n ) {\n this.resumed = opts.resumed ?? false;\n // id already contains a date-prefix shard (e.g. \"2026-06-06/sess_<ULID>\").\n // opts.dir is the shard directory — join with basename so the manifest\n // lives next to the JSONL file instead of creating a double-nested path.\n this.manifestFile = opts.dir ? path.join(opts.dir, `${path.basename(id)}.summary.json`) : '';\n this.filePath = opts.filePath ?? '';\n this.secretScrubber = opts.secretScrubber;\n this.onCloseCb = opts.onClose;\n this.summary = {\n id,\n title: '(empty session)',\n startedAt,\n model: meta.model ?? 'unknown',\n provider: meta.provider ?? 'unknown',\n tokenTotal: 0,\n };\n // Propagated from ContextInit.traceId via SessionWriter.traceId so that\n // storage events carry the run-level trace ID without needing a Context\n // handle in every storage operation.\n this.traceId = traceId;\n }\n\n get pendingToolUses(): string[] {\n return Array.from(this.openToolUses);\n }\n\n private async writeSessionStartLazy(): Promise<void> {\n // Write through the SAME file handle that flushBuffer() uses — avoids\n // cross-fd issues on Windows where a separate fsp.writeFile can contend\n // with the already-open append-mode handle. The handle was opened with\n // O_APPEND so this write lands at the current end-of-file regardless of\n // whether the file is empty or already contains prior session data.\n const record = `${JSON.stringify({\n type: this.resumed ? 'session_resumed' : 'session_start',\n ts: this.startedAt,\n id: this.id,\n model: this.meta.model ?? 'unknown',\n provider: this.meta.provider ?? 'unknown',\n })}\\n`;\n try {\n await this.enqueueWrite(record);\n } catch {\n // best-effort\n }\n }\n\n async append(event: SessionEvent): Promise<void> {\n if (this.closed) return;\n await this.ensureInit();\n // Scrub before observing (the summary title is derived from user_input\n // content) and before buffering, so neither the JSONL nor the sidecar\n // ever holds a cleartext secret.\n const scrubbed = this.scrubEvent(event);\n // observeForSummary MUST run synchronously here — the summary counters\n // (toolCallCount, tokenIn/Out, outcome) drive the .summary.json sidecar\n // and the session index. Deferring observation to flush time would leave\n // the summary stale if close() fires before the next timer tick.\n this.observeForSummary(scrubbed);\n this.writeBuffer.push(scrubbed);\n\n if (this.writeBuffer.length >= FileSessionWriter.FLUSH_SIZE) {\n // Buffer full — flush immediately. Cancel any pending timer so we\n // don't double-flush on the next tick.\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n await this.flushBuffer();\n } else {\n this.scheduleFlush();\n }\n }\n\n async appendBatch(events: SessionEvent[]): Promise<void> {\n if (this.closed || events.length === 0) return;\n await this.ensureInit();\n for (const event of events) {\n const scrubbed = this.scrubEvent(event);\n this.observeForSummary(scrubbed);\n this.writeBuffer.push(scrubbed);\n }\n if (this.writeBuffer.length >= FileSessionWriter.FLUSH_SIZE) {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n await this.flushBuffer();\n } else {\n this.scheduleFlush();\n }\n }\n\n /**\n * Flush buffered events to disk immediately. Critical events\n * (user_input, llm_response) call this so they survive SIGKILL/crash\n * instead of sitting in the in-memory buffer for up to 500ms.\n *\n * Idempotent — cancels any pending timer and writes whatever has\n * accumulated in the buffer. Safe to call even when the buffer\n * is empty (no-op).\n */\n async flush(): Promise<void> {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n await this.flushBuffer();\n }\n\n /** Schedule a deferred flush. No-op if a timer is already pending. */\n private scheduleFlush(): void {\n if (this.flushTimer) return;\n this.flushTimer = setTimeout(() => {\n this.flushTimer = null;\n /* v8 ignore start -- defensive: flushBuffer logs its own errors; this guards the timer callback */\n this.flushBuffer().catch(() => {\n // flushBuffer already logs via the throttled-warning path;\n // this catch prevents an unhandled rejection in the timer callback.\n });\n /* v8 ignore stop */\n }, FileSessionWriter.FLUSH_INTERVAL_MS);\n }\n\n /**\n * Flush all buffered events to disk as a single appendFile call.\n * Errors use the same throttled-warning pattern the old per-event\n * append path used — one warning every 5s with a suppressed count.\n * On failure the buffer is cleared (events are best-effort, same as\n * the old per-event path where a failed write was silently dropped).\n */\n private async flushBuffer(): Promise<void> {\n if (this.writeBuffer.length === 0) return;\n const eventCount = this.writeBuffer.length;\n const batch = this.writeBuffer.map((e) => JSON.stringify(e)).join('\\n') + '\\n';\n this.writeBuffer = [];\n const t0 = Date.now();\n let outcome: 'success' | 'failure' = 'success';\n let errorMsg: string | undefined;\n try {\n await this.enqueueWrite(batch);\n } catch (err) {\n outcome = 'failure';\n errorMsg = toErrorMessage(err);\n this.appendFailCount += eventCount;\n const now = Date.now();\n if (now - this.lastAppendWarnAt > 5000) {\n const suppressed = this.appendFailCount - 1;\n const tail = suppressed > 0 ? ` (+${suppressed} suppressed)` : '';\n console.warn(\n '[session] flush failed:',\n toErrorMessage(err),\n tail,\n );\n this.lastAppendWarnAt = now;\n this.appendFailCount = 0;\n }\n } finally {\n this.events?.emit('storage.write', {\n sessionId: this.id,\n store: 'session',\n filePath: this.filePath,\n operation: 'flush',\n outcome,\n durationMs: Date.now() - t0,\n ...(errorMsg !== undefined ? { error: errorMsg } : {}),\n ...(eventCount !== undefined ? { eventCount } : {}),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n }\n }\n\n private observeForSummary(event: SessionEvent): void {\n // Track open tool uses so we can serialize them on close for resume.\n // The authoritative source is the llm_response content (a core event,\n // always written at every audit level); the legacy 'tool_use' event is\n // kept for alternate writers that still emit it.\n if (event.type === 'llm_response') {\n for (const block of event.content) {\n if (block.type === 'tool_use') this.openToolUses.add(block.id);\n }\n }\n if (event.type === 'tool_use') {\n this.openToolUses.add(event.id);\n } else if (event.type === 'tool_call_start') {\n this.toolCallCount++;\n this.toolBreakdown[event.name] = (this.toolBreakdown[event.name] ?? 0) + 1;\n } else if (event.type === 'tool_result') {\n this.openToolUses.delete(event.id);\n if (event.isError) {\n this.toolErrorCount++;\n this.outcome = 'error';\n }\n } else if (event.type === 'file_snapshot') {\n this.fileChangeCount += event.files.length;\n } else if (event.type === 'compaction') {\n this.compactionCount++;\n }\n // Error events (provider errors, execution errors) mark the session as failed.\n if (event.type === 'error' || event.type === 'provider_error') {\n this.outcome = 'error';\n }\n if (event.type === 'user_input' && this.summary.title === '(empty session)') {\n this.summary = { ...this.summary, title: userInputTitle(event.content) };\n } else if (event.type === 'llm_response') {\n this.tokenIn += event.usage.input;\n this.tokenOut += event.usage.output;\n this.summary = { ...this.summary, tokenTotal: this.tokenIn + this.tokenOut };\n } else if (event.type === 'session_end') {\n const total = event.usage.input + event.usage.output;\n if (total > 0) this.summary = { ...this.summary, tokenTotal: total };\n } else if (event.type === 'in_flight_start') {\n this.iterationCount++;\n }\n }\n\n async close(): Promise<void> {\n // Idempotent AND awaitable: concurrent/repeat callers share the same\n // promise, so nobody proceeds (e.g. to tear down the session directory)\n // while the first close is still flushing.\n if (this.closePromise) return this.closePromise;\n this.closePromise = this.doClose();\n return this.closePromise;\n }\n\n private async doClose(): Promise<void> {\n this.closed = true;\n // Flush any buffered events before finalizing. The summary counters\n // (toolCallCount, tokenIn/Out, outcome) are already up to date because\n // observeForSummary runs synchronously on every append, but the JSONL\n // must have all events on disk before we write the .summary.json sidecar.\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n await this.flushBuffer();\n // Drain any write enqueued outside flushBuffer (e.g. the lazy\n // session_start record) before the handle is closed.\n await this.writeChain;\n // Finalize the summary before writing.\n this.summary = {\n ...this.summary,\n endedAt: new Date().toISOString(),\n iterationCount: this.iterationCount,\n toolCallCount: this.toolCallCount,\n toolErrorCount: this.toolErrorCount,\n fileChangeCount: this.fileChangeCount,\n compactionCount: this.compactionCount > 0 ? this.compactionCount : undefined,\n toolBreakdown:\n { ...this.toolBreakdown },\n outcome: this.outcome ?? 'completed',\n };\n // Emit storage.write for the manifest sidecar.\n if (this.manifestFile) {\n const t0 = Date.now();\n let outcome: 'success' | 'failure' = 'success';\n let errorMsg: string | undefined;\n try {\n await atomicWrite(this.manifestFile, JSON.stringify(this.summary), { mode: 0o600 });\n } catch (err) {\n outcome = 'failure';\n errorMsg = toErrorMessage(err);\n // manifest write is best-effort\n } finally {\n this.events?.emit('storage.write', {\n sessionId: this.id,\n store: 'session',\n filePath: this.manifestFile,\n operation: 'close',\n outcome,\n durationMs: Date.now() - t0,\n ...(errorMsg !== undefined ? { error: errorMsg } : {}),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n }\n }\n // Notify the store so it can update the session index. Await so the\n // index write completes before close() resolves — otherwise the\n // fire-and-forget _index.jsonl append races callers that tear down the\n // session directory right after close() (e.g. ENOTEMPTY on Windows).\n // Emit storage.write here so it carries this.traceId; the actual I/O\n // is delegated to onCloseCb (appendToIndex) which no longer emits.\n const idxT0 = Date.now();\n let idxOutcome: 'success' | 'failure' = 'success';\n let idxError: string | undefined;\n try {\n await this.onCloseCb?.(this.summary);\n /* v8 ignore start -- best-effort: appendToIndex swallows its own errors */\n } catch (err) {\n idxOutcome = 'failure';\n idxError = toErrorMessage(err);\n // best-effort\n } finally {\n /* v8 ignore stop */\n this.events?.emit('storage.write', {\n sessionId: this.summary.id,\n store: 'session',\n filePath: this.filePath,\n operation: 'index_append',\n outcome: idxOutcome,\n durationMs: Date.now() - idxT0,\n ...(idxError !== undefined ? { error: idxError } : {}),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n }\n try {\n await this.handle.close();\n } catch {\n // ignore\n }\n }\n\n async writeCheckpoint(promptIndex: number, promptPreview: string): Promise<void> {\n const fileCount = this.pendingFileSnapshots.length;\n if (fileCount > 0) {\n await this.writeFileSnapshot(promptIndex, [...this.pendingFileSnapshots]);\n this.pendingFileSnapshots = [];\n }\n await this.append({\n type: 'checkpoint',\n ts: new Date().toISOString(),\n promptIndex,\n promptPreview,\n });\n this.events?.emit('checkpoint.written', {\n sessionId: this.id,\n promptIndex,\n promptPreview,\n ts: new Date().toISOString(),\n fileCount,\n });\n }\n\n async writeFileSnapshot(\n promptIndex: number,\n files: FileSnapshot[],\n ): Promise<void> {\n await this.append({\n type: 'file_snapshot',\n ts: new Date().toISOString(),\n promptIndex,\n files,\n });\n }\n\n /**\n * Truncate the session file to the checkpoint with the given promptIndex,\n * removing all events that follow it. Uses a single-pass byte-offset scan\n * so post-checkpoint content is never read or parsed — O(1) memory instead\n * of O(N) JSON.parse calls over the full file.\n */\n async truncateToCheckpoint(targetPromptIndex: number): Promise<number> {\n /* v8 ignore next -- defensive: filePath is always set for a live writer */\n if (!this.filePath) return 0;\n\n // Flush buffered events to disk before reading — otherwise the in-memory\n // events that haven't hit the JSONL yet would be invisible to the\n // truncation logic and would be silently dropped by the rewrite.\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n await this.flushBuffer();\n // Drain the write chain so no in-flight write straddles the close/rename/reopen.\n await this.writeChain;\n\n // Single-pass scan: track byte offset of each line start. Stop as soon as\n // the target checkpoint is found — no I/O or parsing for post-checkpoint data.\n const CHUNK_SIZE = 65_536;\n let fd: fsp.FileHandle | undefined;\n let fileOffset = 0; // cumulative byte position of the start of the current chunk\n let lineStartOffset = 0; // byte offset within the file where the current line begins\n let checkpointByteOffset = -1; // byte offset where we will truncate the file\n let removedCount = 0;\n let targetCheckpointSeen = false; // has the target checkpoint been found yet?\n\n try {\n fd = await fsp.open(this.filePath, 'r', 0o600);\n\n while (true) {\n const buf = Buffer.alloc(CHUNK_SIZE);\n const { bytesRead } = await fd.read(buf, 0, CHUNK_SIZE, fileOffset);\n if (bytesRead === 0) break;\n\n let chunkPos = 0;\n while (chunkPos < bytesRead) {\n const idx = buf.indexOf('\\n', chunkPos);\n if (idx === -1) {\n // No complete line in this chunk — save partial for next iteration.\n lineStartOffset = fileOffset + chunkPos;\n break;\n }\n\n if (checkpointByteOffset !== -1) {\n // Target already found — every subsequent line is removed.\n removedCount++;\n } else {\n // Only parse lines that could precede or be the checkpoint.\n const lineBytes = buf.subarray(chunkPos, idx);\n // eslint-disable-next-line no-sync\n const line = new TextDecoder('utf-8', { fatal: false }).decode(lineBytes);\n if (line.trim()) {\n try {\n const event = JSON.parse(line) as { type?: string; promptIndex?: number };\n if (event.type === 'checkpoint') {\n if (event.promptIndex === targetPromptIndex) {\n // Target found — record its byte offset and stop scanning.\n checkpointByteOffset = lineStartOffset;\n targetCheckpointSeen = true;\n } else if (event.promptIndex !== undefined && event.promptIndex > targetPromptIndex) {\n // A checkpoint with a higher promptIndex means the target is absent.\n // Truncate before this line (exclusive) — it and all following events\n // will be replaced by the new rewinded history.\n checkpointByteOffset = lineStartOffset;\n }\n } else if (targetCheckpointSeen && event.promptIndex !== undefined && event.promptIndex > targetPromptIndex) {\n // Post-target event with a later promptIndex — count as removed.\n removedCount++;\n } else if (targetCheckpointSeen && event.promptIndex === undefined) {\n // After the target checkpoint was found: remove events with no\n // promptIndex. (In the original this is the afterTarget &&\n // targetCheckpointLine !== -1 branch.)\n removedCount++;\n } else if (!targetCheckpointSeen && event.promptIndex === undefined) {\n // Past a higher checkpoint but the target checkpoint not yet found.\n // Matches original: remove events with undefined promptIndex\n // (malformed lines, file_snapshots, etc.) that appear after a\n // higher checkpoint but before the target.\n removedCount++;\n } else if (!targetCheckpointSeen && event.promptIndex !== undefined && event.promptIndex > targetPromptIndex) {\n // Past a higher checkpoint but the target not yet found.\n // Matches original: remove events with promptIndex > target that\n // appear before the target checkpoint (e.g. user_inputs belonging\n // to a later prompt).\n removedCount++;\n }\n // Events with promptIndex <= targetPromptIndex (before the target is\n // found) are implicitly kept — no action needed.\n } catch {\n // Malformed JSON — matches original: keep it.\n }\n }\n }\n\n // Move to start of next line.\n chunkPos = idx + 1;\n lineStartOffset = fileOffset + chunkPos;\n }\n\n fileOffset += bytesRead;\n if (chunkPos >= bytesRead) {\n // Finished all complete lines; prepare for next chunk.\n lineStartOffset = fileOffset;\n }\n }\n } finally {\n await fd?.close();\n }\n\n if (checkpointByteOffset === -1) return 0;\n\n // Windows EPERM fix: close the append-mode handle before replacing the\n // file. Windows rejects rename() when the destination still has an open\n // handle, even if that handle belongs to this process.\n await this.writeChain;\n await this.handle.close();\n const tmpPath = `${this.filePath}.rewind.tmp`;\n const src = await fsp.open(this.filePath, 'r', 0o600);\n try {\n const statResult = await src.stat();\n const totalSize = statResult.size;\n // checkpointByteOffset points to the start of the checkpoint line.\n // We want to keep everything up to and including that line's '\\n'.\n // Since the file ends with '\\n', keeping bytes [0 .. lineStartAfterCheckpoint]\n // means we include the trailing newline. We find that '\\n' by scanning\n // from checkpointByteOffset forward (at most one chunk's worth).\n const prefixBytes = checkpointByteOffset;\n let newlineAfterCheckpoint = prefixBytes;\n\n if (prefixBytes < totalSize) {\n const probeBuf = Buffer.alloc(Math.min(CHUNK_SIZE, totalSize - prefixBytes));\n const { bytesRead: probeRead } = await src.read(probeBuf, 0, probeBuf.length, prefixBytes);\n if (probeRead > 0) {\n const nl = probeBuf.indexOf('\\n');\n newlineAfterCheckpoint = nl !== -1 ? prefixBytes + nl + 1 : totalSize;\n }\n } else {\n newlineAfterCheckpoint = totalSize;\n }\n\n const writeFd = await fsp.open(tmpPath, 'w', 0o600);\n try {\n let readOffset = 0;\n while (readOffset < newlineAfterCheckpoint) {\n const toCopy = Math.min(CHUNK_SIZE, newlineAfterCheckpoint - readOffset);\n const copyBuf = Buffer.alloc(toCopy);\n const { bytesRead: r } = await src.read(copyBuf, 0, toCopy, readOffset);\n if (r === 0) break;\n await writeFd.write(copyBuf, 0, r);\n readOffset += r;\n }\n\n // Preserve malformed JSONL records even after the rewind target. They\n // are not replayable session events, but keeping them avoids silently\n // deleting diagnostic/corruption evidence during a truncate.\n // Stream the tail from the already-open src handle instead of\n // re-reading the entire file — the prefix was already streamed above,\n // so reading via readFile() would duplicate all of that I/O.\n let tailOffset = newlineAfterCheckpoint;\n let leftover = '';\n while (tailOffset < totalSize) {\n const toRead = Math.min(CHUNK_SIZE, totalSize - tailOffset);\n const tailBuf = Buffer.alloc(toRead);\n const { bytesRead: tr } = await src.read(tailBuf, 0, toRead, tailOffset);\n if (tr === 0) break;\n const chunk = leftover + tailBuf.subarray(0, tr).toString('utf8');\n const lastNl = chunk.lastIndexOf('\\n');\n if (lastNl === -1) {\n // No complete line in this chunk — accumulate into leftover.\n leftover = chunk;\n } else {\n for (const line of chunk.slice(0, lastNl + 1).split('\\n')) {\n if (!line.trim()) continue;\n try {\n JSON.parse(line);\n } catch {\n await writeFd.write(`${line}\\n`, undefined, 'utf8');\n }\n }\n leftover = chunk.slice(lastNl + 1);\n }\n tailOffset += tr;\n }\n // Flush trailing partial line (file may not end with \\n).\n if (leftover.trim()) {\n try {\n JSON.parse(leftover);\n } catch {\n await writeFd.write(`${leftover}\\n`, undefined, 'utf8');\n }\n }\n } finally {\n await writeFd.close();\n }\n\n await src.close();\n await fsp.rename(tmpPath, this.filePath);\n // Re-open in append mode for continued use of this file.\n this.handle = await fsp.open(this.filePath, 'a', 0o600);\n /* v8 ignore start -- defensive: close/rename/reopen of a just-written temp file */\n } catch (err) {\n await fsp.unlink(tmpPath).catch(() => undefined);\n this.handle = await fsp.open(this.filePath, 'a', 0o600).catch(() => this.handle);\n throw err;\n }\n /* v8 ignore stop */\n\n await this.append({\n type: 'rewound',\n ts: new Date().toISOString(),\n toPromptIndex: targetPromptIndex,\n revertedFiles: [],\n });\n\n this.events?.emit('session.rewound', {\n sessionId: this.id,\n toPromptIndex: targetPromptIndex,\n revertedFiles: [],\n removedEvents: removedCount,\n });\n\n return removedCount;\n }\n\n async clearSession(): Promise<void> {\n /* v8 ignore next -- defensive: filePath is always set for a live writer */\n if (!this.filePath) return;\n // Discard any buffered events — the caller is explicitly resetting the\n // session to a clean slate. Cancel the timer so it doesn't fire and\n // append stale events to the freshly-cleared file.\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n this.writeBuffer = [];\n // Let any in-flight append land first — otherwise it would re-append\n // stale events AFTER the reset record below.\n await this.writeChain;\n const record = `${JSON.stringify({\n type: 'session_start',\n ts: new Date().toISOString(),\n id: this.id,\n model: this.meta.model ?? 'unknown',\n provider: this.meta.provider ?? 'unknown',\n })}\\n`;\n await fsp.writeFile(this.filePath, record, 'utf8');\n }\n\n /**\n * Write an in-flight marker. The agent loop should call\n * this at the start of each long-running operation; a matching\n * `clearInFlightMarker` follows on clean exit. A stale marker\n * (no end) is what `SessionRecovery.detectStale` looks for.\n */\n async writeInFlightMarker(context: string): Promise<void> {\n if (!context || context.length > 500) {\n throw new Error('In-flight context must be 1..500 chars');\n }\n await this.append({\n type: 'in_flight_start',\n ts: new Date().toISOString(),\n context,\n });\n this.events?.emit('in_flight.started', { sessionId: this.id, context, ts: new Date().toISOString() });\n }\n\n /**\n * Close the in-flight marker. Idempotent in spirit\n * (you can call it after a successful iteration even if you\n * didn't open one this round) — but the session log records\n * every call so postmortem tooling can see \"the agent finished\n * cleanly X times, then died without finishing Y\".\n */\n async clearInFlightMarker(reason: 'clean' | 'aborted' | 'recovered'): Promise<void> {\n await this.append({\n type: 'in_flight_end',\n ts: new Date().toISOString(),\n reason,\n });\n this.events?.emit('in_flight.ended', { sessionId: this.id, reason, ts: new Date().toISOString() });\n }\n}\n","/**\n * Session ID generation — extracted from session-store.ts.\n *\n * Pure functions: no I/O, no class state, no side effects.\n * Safe to unit-test in isolation.\n */\nimport { ulid } from '../utils/ulid.js';\n\n/**\n * @deprecated Legacy helper kept for callers that still need filename-safe\n * labels. New session ids are opaque and do not include model/provider names.\n */\nexport function sanitizeModel(model: string): string {\n return model\n .replace(/[^a-zA-Z0-9_-]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n .slice(0, 40);\n}\n\n/**\n * Generate a session ID in the format:\n * `YYYY-MM-DD/sess_<ULID>`\n *\n * Examples:\n * `2026-06-06/sess_01JX2S9V7T5M6N7P8Q9R0STXVW`\n *\n * The date prefix becomes a subdirectory so sessions group naturally by day.\n * The leaf is an opaque sortable id; provider/model names belong in metadata,\n * not file paths. Older IDs that contain model/provider text remain readable.\n */\nexport function generateSessionId(startedAt: string, _model?: string): string {\n const date = startedAt.slice(0, 10); // \"2026-06-06\"\n const seedTime = Number.isNaN(Date.parse(startedAt)) ? Date.now() : Date.parse(startedAt);\n return `${date}/sess_${ulid(seedTime)}`;\n}\n","import type { SessionSummary } from '../types/session.js';\n\nexport interface SessionFilterCriteria {\n since?: string | undefined;\n until?: string | undefined;\n provider?: string | undefined;\n model?: string | undefined;\n minTokens?: number | undefined;\n titleContains?: string | undefined;\n}\n\nexport function compareSessionSummaries(a: SessionSummary, b: SessionSummary): number {\n if (a.startedAt < b.startedAt) return 1;\n if (a.startedAt > b.startedAt) return -1;\n return a.id.localeCompare(b.id);\n}\n\nexport function matchesSessionFilter(summary: SessionSummary, criteria: SessionFilterCriteria): boolean {\n if (criteria.since && summary.startedAt < criteria.since) return false;\n if (criteria.until && summary.startedAt > criteria.until) return false;\n if (criteria.provider && summary.provider !== criteria.provider) return false;\n if (criteria.model && summary.model !== criteria.model) return false;\n if (criteria.minTokens !== undefined && summary.tokenTotal < criteria.minTokens) return false;\n if (criteria.titleContains) {\n const needle = criteria.titleContains.toLocaleLowerCase();\n if (!summary.title.toLocaleLowerCase().includes(needle)) return false;\n }\n return true;\n}\n","import type { SessionData, SessionEvent } from '../types/session.js';\n\ntype ToolCallEnd = SessionData['toolCallEnds'][number];\n\nexport function extractToolCallEnds(events: readonly SessionEvent[]): ToolCallEnd[] {\n const out: ToolCallEnd[] = [];\n for (const event of events) {\n if (event.type !== 'tool_call_end') continue;\n out.push({\n name: event.name,\n id: event.id,\n durationMs: event.durationMs,\n ok: event.ok ?? true,\n outputBytes: event.outputBytes ?? event.outputSize,\n outputTokens: event.outputTokens,\n outputLines: event.outputLines,\n });\n }\n return out;\n}\n","export async function mapWithConcurrency<T, R>(\n items: readonly T[],\n concurrency: number,\n mapper: (item: T, index: number) => Promise<R>,\n): Promise<R[]> {\n if (items.length === 0) return [];\n const limit = Math.max(1, Math.floor(concurrency));\n const results = new Array<R>(items.length);\n let next = 0;\n\n async function worker(): Promise<void> {\n while (true) {\n const index = next;\n next++;\n if (index >= items.length) return;\n results[index] = await mapper(items[index] as T, index);\n }\n }\n\n const workers = Array.from({ length: Math.min(limit, items.length) }, () => worker());\n await Promise.all(workers);\n return results;\n}\n","import { createReadStream, type Dirent } from 'node:fs';\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { createInterface } from 'node:readline';\nimport type { EventBus } from '../kernel/events.js';\nimport type { ContentBlock } from '../types/blocks.js';\nimport type { Message } from '../types/messages.js';\nimport type { SecretScrubber } from '../types/secret-scrubber.js';\nimport type {\n ResumedSession,\n SessionData,\n SessionEvent,\n SessionMetadata,\n SessionStore,\n SessionSummary,\n SessionWriter,\n} from '../types/session.js';\nimport { atomicWrite, ensureDir, withFileLock } from '../utils/atomic-write.js';\nimport { repairToolUseAdjacency } from '../utils/message-invariants.js';\nimport { toErrorMessage } from '../utils/index.js';\nimport { sessionScopedPath } from '../utils/session-scoped-path.js';\nimport { FileSessionWriter } from './file-session-writer.js';\nimport { userInputTitle } from './session-helpers.js';\nimport { generateSessionId } from './session-id.js';\nimport { compareSessionSummaries, matchesSessionFilter } from './session-summary.js';\nimport { extractToolCallEnds } from './session-tool-call-ends.js';\nimport { mapWithConcurrency } from './storage-concurrency.js';\n\nexport interface SessionStoreOptions {\n dir: string;\n /** Optional EventBus for emitting session diagnostics. */\n events?: EventBus | undefined;\n /**\n * Optional secret scrubber. When set, `user_input` and `llm_response` event\n * content is scrubbed before being persisted to the JSONL log and the\n * summary sidecar — so a secret a user pastes or the model echoes does not\n * sit in cleartext on disk (and does not ride along in history cloud-sync).\n * Tool output is already scrubbed upstream by the executor; this closes the\n * conversation-turn gap (finding F-06).\n */\n secretScrubber?: SecretScrubber | undefined;\n}\n\n/**\n * Cache entry for load() — stores the parsed SessionData along with the\n * file's mtimeMs and size at the time of loading. On subsequent calls,\n * if the file's mtimeMs+size match, we return the cached data without\n * re-reading or re-parsing the JSONL.\n */\ninterface LoadCacheEntry {\n mtimeMs: number;\n size: number;\n data: SessionData;\n}\n\ninterface IndexCacheEntry {\n mtimeMs: number;\n size: number;\n summaries: SessionSummary[];\n}\n\ninterface SessionFileRef {\n id: string;\n filePath: string;\n}\n\ninterface DirectorySummaryCandidate {\n summary: SessionSummary;\n needsBackfill: boolean;\n}\n\ninterface ShardManifestEntry {\n summaries: SessionSummary[];\n ids: string[];\n}\n\nexport class DefaultSessionStore implements SessionStore {\n private readonly dir: string;\n private readonly events?: EventBus | undefined;\n private readonly secretScrubber?: SecretScrubber | undefined;\n\n /**\n * In-memory cache for load() results, keyed by session ID. The cache is\n * invalidated when the file's mtimeMs or size changes (indicating the\n * file was written to). This eliminates redundant full-file reads and\n * JSON parses when the same session is loaded multiple times within the\n * store's lifetime (e.g., webui session detail views, list() fallbacks).\n *\n * Max size is capped to prevent unbounded memory growth in long-running\n * processes. When the limit is reached, the oldest entry is evicted.\n */\n private readonly _loadCache = new Map<string, LoadCacheEntry>();\n private _indexCache: IndexCacheEntry | null = null;\n private readonly shardManifestCache = new Map<string, ShardManifestEntry>();\n private static readonly LOAD_CACHE_MAX_ENTRIES = 50;\n private static readonly LIST_SCAN_CONCURRENCY = 32;\n\n constructor(opts: SessionStoreOptions) {\n this.dir = opts.dir;\n this.events = opts.events;\n this.secretScrubber = opts.secretScrubber;\n }\n\n /**\n * Clear the load() cache. Useful for testing or when the caller knows\n * the file has changed externally (e.g., another process wrote to it).\n */\n clearLoadCache(sessionId?: string): void {\n if (sessionId !== undefined) {\n this._loadCache.delete(sessionId);\n } else {\n this._loadCache.clear();\n }\n }\n\n // ── Storage event helpers ───────────────────────────────────────────────────\n\n private emitRead(\n sessionId: string,\n filePath: string,\n operation: 'load' | 'load_events_only' | 'list' | 'summary' | 'index_read',\n outcome: 'success' | 'failure',\n durationMs: number,\n error?: string,\n ): void {\n this.events?.emit('storage.read', {\n sessionId,\n store: 'session',\n filePath,\n operation,\n outcome,\n durationMs,\n ...(error !== undefined ? { error } : {}),\n });\n }\n\n private emitWrite(\n sessionId: string,\n filePath: string,\n operation: 'create' | 'resume' | 'append' | 'flush' | 'close' | 'index_append' | 'compact' | 'checkpoint',\n outcome: 'success' | 'failure',\n durationMs: number,\n eventCount?: number,\n error?: string,\n ): void {\n this.events?.emit('storage.write', {\n sessionId,\n store: 'session',\n filePath,\n operation,\n outcome,\n durationMs,\n ...(eventCount !== undefined ? { eventCount } : {}),\n ...(error !== undefined ? { error } : {}),\n });\n }\n\n private emitError(\n sessionId: string,\n filePath: string,\n operation: string,\n error: string,\n recoverable: boolean,\n ): void {\n this.events?.emit('storage.error', {\n sessionId,\n store: 'session',\n filePath,\n operation,\n error,\n recoverable,\n });\n }\n\n /** Absolute path to the session index file. */\n private get indexFile(): string {\n return path.join(this.dir, '_index.jsonl');\n }\n\n /** Join session ID to its absolute path within the store directory. */\n private sessionPath(id: string, ext: '.jsonl' | '.summary.json'): string {\n return sessionScopedPath(this.dir, id, ext);\n }\n\n private shardManifestPath(shardKey: string): string {\n return shardKey ? path.join(this.dir, shardKey, '_manifest.json') : path.join(this.dir, '_manifest.json');\n }\n\n private shardKeyForSessionId(id: string): string {\n const dirName = path.dirname(id);\n return dirName === '.' ? '' : dirName;\n }\n\n private invalidateShardManifestBySessionId(id: string): void {\n this.shardManifestCache.delete(this.shardKeyForSessionId(id));\n }\n\n /**\n * Ensure the directory implied by the session ID exists. When the ID\n * contains a date prefix like `2026-06-06/...`, this creates the date\n * subdirectory so sessions group naturally by day.\n */\n private async ensureShardDir(id: string): Promise<string> {\n const dirPath = path.dirname(sessionScopedPath(this.dir, id, ''));\n await ensureDir(dirPath);\n return dirPath;\n }\n\n async create(meta: Omit<SessionMetadata, 'startedAt'>): Promise<SessionWriter> {\n const startedAt = new Date().toISOString();\n const id =\n meta.id && meta.id.length > 0\n ? meta.id\n : generateSessionId(startedAt);\n const shardDir = await this.ensureShardDir(id);\n const file = this.sessionPath(id, '.jsonl');\n const t0 = Date.now();\n let handle: fsp.FileHandle;\n try {\n handle = await fsp.open(file, 'a', 0o600);\n } catch (err) {\n this.emitError(id, file, 'create', toErrorMessage(err), false);\n throw new Error(\n `Failed to open session file: ${toErrorMessage(err)}`,\n { cause: err },\n );\n }\n try {\n const writer = new FileSessionWriter(id, handle, startedAt, meta, this.events, {\n dir: shardDir,\n filePath: file,\n secretScrubber: this.secretScrubber,\n onClose: (s) => this.appendToIndex(s),\n });\n this.emitWrite(id, file, 'create', 'success', Date.now() - t0);\n return writer;\n /* v8 ignore start -- defensive: FileSessionWriter ctor does not throw in practice */\n } catch (err) {\n await handle.close().catch((e) => console.warn(JSON.stringify({\n level: 'warn',\n event: 'session_store.handle_close_failed',\n message: e instanceof Error ? e.message : String(e),\n timestamp: new Date().toISOString(),\n })));\n this.emitError(id, file, 'create', toErrorMessage(err), true);\n throw err;\n }\n /* v8 ignore stop */\n }\n\n async resume(id: string): Promise<ResumedSession> {\n const file = this.sessionPath(id, '.jsonl');\n const t0 = Date.now();\n const data = await this.load(id);\n let handle: fsp.FileHandle;\n try {\n handle = await fsp.open(file, 'a', 0o600);\n /* v8 ignore start -- defensive: load() above already validated the file is readable */\n } catch (err) {\n this.emitError(id, file, 'resume', toErrorMessage(err), false);\n throw new Error(\n `Failed to open session \"${id}\" for append: ${toErrorMessage(err)}`,\n { cause: err },\n );\n }\n /* v8 ignore stop */\n try {\n const writer = new FileSessionWriter(\n id,\n handle,\n new Date().toISOString(),\n {\n id,\n model: data.metadata.model,\n provider: data.metadata.provider,\n },\n this.events,\n {\n resumed: true,\n // Shard directory (sessions/<date>/) — must match create() so the\n // .summary.json sidecar lands next to the JSONL instead of the\n // sessions root (where summaryFor() would never find it).\n dir: path.dirname(file),\n filePath: file,\n secretScrubber: this.secretScrubber,\n onClose: (s) => this.appendToIndex(s),\n },\n );\n this.emitWrite(id, file, 'resume', 'success', Date.now() - t0);\n return { writer, data };\n /* v8 ignore start -- defensive: FileSessionWriter ctor does not throw in practice */\n } catch (err) {\n await handle.close().catch((e) => console.warn(JSON.stringify({\n level: 'warn',\n event: 'session_store.handle_close_failed',\n message: e instanceof Error ? e.message : String(e),\n timestamp: new Date().toISOString(),\n })));\n this.emitError(id, file, 'resume', toErrorMessage(err), true);\n throw err;\n }\n /* v8 ignore stop */\n }\n\n async load(id: string): Promise<SessionData> {\n return this.loadInternal(id, { full: true });\n }\n\n /**\n * Fast-path loader that skips message reconstruction and adjacency repair.\n *\n * Use this for callers that only need the raw event stream + session\n * metadata — e.g. session listers, analytics, audit, and the TUI's\n * \"events only\" views. It avoids the message array build and\n * repairToolUseAdjacency cost on large session files (a long agent\n * run can have 50k+ events; rebuilding messages is O(events) and\n * allocates per-block, so skipping it is a meaningful win).\n *\n * The returned data.messages is an empty array; data.toolCallEnds\n * is computed from the raw events. usage is the sum across all\n * llm_response events — same as full load().\n */\n async loadEventsOnly(id: string): Promise<SessionData> {\n return this.loadInternal(id, { full: false });\n }\n\n private async loadInternal(\n id: string,\n mode: { full: true } | { full: false },\n ): Promise<SessionData> {\n const file = this.sessionPath(id, '.jsonl');\n const t0 = Date.now();\n let outcome: 'success' | 'failure' = 'success';\n let errorMsg: string | undefined;\n let cacheHit = false;\n try {\n // Stat the file first to check the cache. The stat is cheap (no content\n // read) and lets us skip the full readFile + JSON parse when the file\n // hasn't changed since the last load.\n const s = await fsp.stat(file);\n const stat: { mtimeMs: number; size: number } = { mtimeMs: s.mtimeMs, size: s.size };\n\n // Check cache: if mtimeMs AND size match, the file hasn't changed.\n const cached = this._loadCache.get(id);\n if (cached && cached.mtimeMs === stat.mtimeMs && cached.size === stat.size) {\n cacheHit = true;\n // Update insertion order to prevent frequent-access sessions from being\n // evicted by the LRU eviction logic.\n this._loadCache.delete(id);\n this._loadCache.set(id, cached);\n if (mode.full) return cached.data;\n return { ...cached.data, messages: [] };\n }\n\n // Cache miss — do the full read + parse.\n // Fused single pass: parse events + build messages + extract metadata together.\n // Streams the file line-by-line so we don't materialize the whole JSONL\n // (multi-MB for long sessions). Events-only requests skip the message\n // build and the adjacency repair entirely.\n const events: SessionEvent[] = [];\n\n // Metadata extracted in the same single pass over the raw lines.\n let sessionStartEvent: SessionEvent | undefined;\n let sessionEndEvent: SessionEvent | undefined;\n let sessionModel: string | undefined;\n let sessionProvider: string | undefined;\n let sessionPendingToolUses: string[] | undefined;\n\n // Message builder state — only allocated when mode.full.\n const messages: Message[] | undefined = mode.full ? [] : undefined;\n const openToolUses: Set<string> | undefined = mode.full ? new Set<string>() : undefined;\n let usage = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };\n\n const stream = createReadStream(file, { encoding: 'utf8' });\n const rl = createInterface({ input: stream, crlfDelay: Infinity });\n\n try {\n for await (const line of rl) {\n if (!line.trim()) continue;\n try {\n const parsed: unknown = JSON.parse(line);\n if (\n parsed !== null &&\n typeof parsed === 'object' &&\n typeof (parsed as { type?: unknown | undefined }).type === 'string' &&\n typeof (parsed as { ts?: unknown | undefined }).ts === 'string'\n ) {\n const ev = parsed as SessionEvent;\n events.push(ev);\n\n // Track metadata in the same pass.\n if (ev.type === 'session_start' && !sessionStartEvent) {\n sessionStartEvent = ev;\n sessionModel = ev.model;\n sessionProvider = ev.provider;\n }\n if (ev.type === 'session_end') {\n sessionEndEvent = ev;\n sessionPendingToolUses = ev.pendingToolUses;\n }\n\n // Build messages in the same pass (replay() logic inlined).\n // Skipped entirely when mode.full is false.\n if (mode.full && messages !== undefined && openToolUses !== undefined) {\n if (ev.type === 'user_input') {\n openToolUses.clear();\n messages.push({ role: 'user', content: ev.content, ts: ev.ts });\n } else if (ev.type === 'llm_response') {\n messages.push({ role: 'assistant', content: ev.content, ts: ev.ts });\n for (const b of ev.content) {\n if (b.type === 'tool_use') openToolUses.add(b.id);\n }\n usage = {\n input: usage.input + (ev.usage.input ?? 0),\n output: usage.output + (ev.usage.output ?? 0),\n cacheRead: (usage.cacheRead ?? 0) + (ev.usage.cacheRead ?? 0),\n cacheWrite: (usage.cacheWrite ?? 0) + (ev.usage.cacheWrite ?? 0),\n };\n } else if (ev.type === 'tool_result') {\n if (!openToolUses.has(ev.id)) {\n this.events?.emit('session.damaged', {\n sessionId: id,\n detail: `Orphan tool_result \"${ev.id}\" has no matching tool_use`,\n });\n continue;\n }\n openToolUses.delete(ev.id);\n const resultBlock: ContentBlock = {\n type: 'tool_result',\n tool_use_id: ev.id,\n content: typeof ev.content === 'string' ? ev.content : JSON.stringify(ev.content),\n is_error: ev.isError,\n };\n const last = messages[messages.length - 1];\n const lastIsToolResultUser =\n last?.role === 'user' &&\n Array.isArray(last.content) &&\n last.content.every((b) => (b as ContentBlock).type === 'tool_result');\n if (lastIsToolResultUser && Array.isArray(last.content)) {\n last.content.push(resultBlock);\n } else {\n messages.push({ role: 'user', content: [resultBlock], ts: ev.ts });\n }\n }\n } else if (ev.type === 'llm_response') {\n // events-only path still accumulates usage.\n usage = {\n input: usage.input + (ev.usage.input ?? 0),\n output: usage.output + (ev.usage.output ?? 0),\n cacheRead: (usage.cacheRead ?? 0) + (ev.usage.cacheRead ?? 0),\n cacheWrite: (usage.cacheWrite ?? 0) + (ev.usage.cacheWrite ?? 0),\n };\n }\n }\n } catch {\n // skip malformed JSON\n }\n }\n } finally {\n rl.close();\n stream.close();\n }\n\n let finalMessages: Message[] = [];\n if (mode.full && messages !== undefined && openToolUses !== undefined) {\n // Repair tool adjacency after the single parse + replay loop.\n if (openToolUses.size > 0) {\n this.events?.emit('session.damaged', {\n sessionId: id,\n detail: `${openToolUses.size} tool_use blocks without matching results - replay repaired`,\n });\n }\n const repaired = repairToolUseAdjacency(messages);\n if (repaired.report.changed) {\n this.events?.emit('session.damaged', {\n sessionId: id,\n detail:\n `Repaired replay adjacency: removed ${repaired.report.removedToolUses.length} tool_use, ` +\n `${repaired.report.removedToolResults.length} tool_result, ` +\n `${repaired.report.removedMessages} empty messages`,\n });\n }\n finalMessages = repaired.messages;\n }\n\n // Build metadata from the extracted session_start/end events.\n const meta: SessionMetadata = {\n id,\n startedAt: sessionStartEvent?.ts ?? new Date(0).toISOString(),\n endedAt: sessionEndEvent?.ts,\n model: sessionModel,\n provider: sessionProvider,\n pendingToolUses: sessionPendingToolUses,\n };\n\n // Extract tool_call_end events for TUI tool entry rendering on resume.\n const toolCallEnds = extractToolCallEnds(events);\n const data: SessionData = { metadata: meta, events, messages: finalMessages, usage, toolCallEnds };\n\n // Update the cache. Evict oldest entry if at capacity.\n // Only full loads populate the cache; events-only loads always read\n // through (they're cheap, and a hot loop on events-only would\n // otherwise evict full-load entries that callers also need).\n if (mode.full) {\n if (this._loadCache.size >= DefaultSessionStore.LOAD_CACHE_MAX_ENTRIES) {\n // Map iteration order is insertion order — delete the first key.\n const oldest = this._loadCache.keys().next().value;\n if (oldest !== undefined) {\n this._loadCache.delete(oldest);\n }\n }\n this._loadCache.set(id, { mtimeMs: stat.mtimeMs, size: stat.size, data });\n }\n\n return data;\n } catch (err) {\n outcome = 'failure';\n errorMsg = toErrorMessage(err);\n throw err;\n } finally {\n this.emitRead(id, file, mode.full ? 'load' : 'load_events_only', outcome, Date.now() - t0, errorMsg);\n if (cacheHit) {\n this.events?.emit('storage.cache_hit', {\n sessionId: id,\n store: 'session',\n filePath: file,\n operation: mode.full ? 'load' : 'load_events_only',\n durationMs: Date.now() - t0,\n });\n }\n }\n }\n\n /**\n * Streaming search over a session's JSONL. Walks the file once, parses\n * each event lazily, and yields only the events that match `predicate`.\n * Stops as soon as `opts.limit` matches are collected.\n *\n * Why this exists: `load()` parses the entire file into memory and\n * rebuilds `messages`/`toolCallEnds` for every caller. `search()` only\n * needs to know which events contain matching text — a per-line\n * predicate is enough. The full parse work (and the `_loadCache` poll)\n * is wasted in that case.\n *\n * Memory: O(hits) regardless of file size. Disk: one linear scan,\n * terminated at `limit` if the caller asked for one.\n *\n * Errors: missing file yields []. Corrupt lines are skipped (same\n * policy as `load()`). Aborting via `signal` rejects with `AbortError`.\n */\n async searchEvents(\n id: string,\n predicate: (event: SessionEvent, eventIndex: number, ts: string) => boolean,\n opts?: { limit?: number | undefined; signal?: AbortSignal | undefined },\n ): Promise<Array<{ event: SessionEvent; eventIndex: number; ts: string }>> {\n const file = this.sessionPath(id, '.jsonl');\n const limit = opts?.limit;\n const signal = opts?.signal;\n const out: Array<{ event: SessionEvent; eventIndex: number; ts: string }> = [];\n\n // Try to stat first so a missing file returns [] instead of throwing\n // — matches `load()` ENOENT semantics that callers already depend on.\n let stat: import('node:fs').Stats;\n try {\n stat = await fsp.stat(file);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return [];\n throw err;\n }\n if (stat.size === 0) return [];\n\n let fh: fsp.FileHandle | undefined;\n try {\n fh = await fsp.open(file, 'r');\n // Read in 64KB chunks; lines can straddle a chunk boundary so we\n // carry the trailing partial line forward between iterations.\n const CHUNK = 64 * 1024;\n const buf = Buffer.alloc(CHUNK);\n let leftover = '';\n let eventIndex = 0;\n for (let position = 0; ; position += buf.byteLength) {\n if (signal?.aborted) {\n const reason = signal.reason ?? new DOMException('Aborted', 'AbortError');\n throw reason;\n }\n const { bytesRead } = await fh.read(buf, 0, CHUNK, position);\n if (bytesRead === 0) break;\n const text = leftover + buf.subarray(0, bytesRead).toString('utf8');\n // Split into lines; the last element is either '' (file ended on a\n // newline) or a partial line — keep it as the new leftover.\n const parts = text.split('\\n');\n leftover = parts.pop() ?? '';\n for (const line of parts) {\n if (!line) continue;\n let ev: SessionEvent;\n try {\n const parsed: unknown = JSON.parse(line);\n if (\n parsed === null ||\n typeof parsed !== 'object' ||\n typeof (parsed as { type?: unknown }).type !== 'string' ||\n typeof (parsed as { ts?: unknown }).ts !== 'string'\n ) {\n // Skip lines that don't match the SessionEvent shape — same\n // tolerance as `load()` (which silently drops non-events).\n continue;\n }\n ev = parsed as SessionEvent;\n } catch {\n // Skip malformed JSON, matching `load()` behavior.\n continue;\n }\n if (predicate(ev, eventIndex, ev.ts)) {\n out.push({ event: ev, eventIndex, ts: ev.ts });\n if (limit !== undefined && out.length >= limit) {\n return out;\n }\n }\n eventIndex++;\n }\n }\n // Flush a trailing line that lacks a final newline.\n if (leftover.trim()) {\n try {\n const parsed: unknown = JSON.parse(leftover);\n if (\n parsed !== null &&\n typeof parsed === 'object' &&\n typeof (parsed as { type?: unknown }).type === 'string' &&\n typeof (parsed as { ts?: unknown }).ts === 'string'\n ) {\n const ev = parsed as SessionEvent;\n if (predicate(ev, eventIndex, ev.ts)) {\n out.push({ event: ev, eventIndex, ts: ev.ts });\n }\n }\n } catch {\n /* partial trailing line — drop */\n }\n }\n return out;\n } finally {\n if (fh) await fh.close().catch(() => undefined);\n }\n }\n\n async list(limit = 20): Promise<SessionSummary[]> {\n try {\n await ensureDir(this.dir);\n // Try the index first; fall back to directory scan if the index is\n // missing, empty, or unreadable.\n const indexed = await this.readIndex();\n if (indexed.length > 0) {\n // `readIndex()` already sorted the array by startedAt DESC, id\n // ASC, so we just slice the prefix.\n return indexed.slice(0, limit);\n }\n // Index unavailable — fall back to a directory scan. Prefer summary\n // sidecars and only backfill full JSONL-derived summaries for the page\n // we are about to return.\n return await this.listFromDirectoryScan(limit);\n } catch {\n return [];\n }\n }\n\n /**\n * List sessions matching filter criteria, using the cached index.\n * Filters are applied BEFORE sorting and slicing, so the caller gets\n * exactly `limit` matching sessions — not a slice of a larger fetch.\n *\n * This avoids the DefaultSessionReader pattern of fetching 1000 sessions\n * then linear-filtering: the index is already in memory (readIndex\n * caches it), and the filter runs over the cached array without any\n * additional disk I/O.\n */\n async listFiltered(criteria: {\n since?: string | undefined;\n until?: string | undefined;\n provider?: string | undefined;\n model?: string | undefined;\n minTokens?: number | undefined;\n titleContains?: string | undefined;\n limit?: number | undefined;\n }): Promise<SessionSummary[]> {\n const limit = criteria.limit ?? 100;\n try {\n await ensureDir(this.dir);\n const indexed = await this.readIndex();\n if (indexed.length === 0) {\n // No index — fall back to list() + in-process filter.\n const raw = await this.list(Math.max(limit, 100));\n return raw.filter((s) => matchesSessionFilter(s, criteria)).slice(0, limit);\n }\n const filtered = indexed.filter((s) => matchesSessionFilter(s, criteria));\n filtered.sort((a, b) => {\n if (a.startedAt < b.startedAt) return 1;\n if (a.startedAt > b.startedAt) return -1;\n return a.id.localeCompare(b.id);\n });\n return filtered.slice(0, limit);\n } catch {\n return [];\n }\n }\n\n // ── Session index (_index.jsonl) ─────────────────────────────────────────\n //\n // One JSON line per closed session, appended atomically on close().\n // When a session is deleted, a tombstone {action:\"delete\",id:\"...\"} is\n // appended. On read, tombstones filter out matching session entries.\n // This keeps listing O(lines-in-index) instead of O(files-on-disk).\n //\n // The index auto-compacts every N appends to prevent unbounded growth\n // from tombstones and duplicate entries (resume cycles).\n\n private indexAppendCount = 0;\n private static readonly COMPACT_EVERY = 30;\n\n /** Append a session summary to the index. */\n private async appendToIndex(summary: SessionSummary): Promise<void> {\n // Note: storage.write for this operation is emitted by FileSessionWriter.doClose()\n // so it can include the traceId. Do NOT emit here to avoid duplicates.\n try {\n await ensureDir(this.dir);\n // Serialize the append (and any compaction it triggers) under the index\n // file lock. The lock is per-FILE, so it also guards against a SECOND\n // wstack process in the same project appending/compacting concurrently —\n // without it, a compact() rewrite racing an append() silently drops the\n // appended line (the source-of-truth .jsonl survives, but the listing\n // cache loses the entry until rebuildIndex()).\n let shouldCompact = false;\n await withFileLock(this.indexFile, async () => {\n const line = JSON.stringify(summary) + '\\n';\n await fsp.appendFile(this.indexFile, line, 'utf8');\n this._indexCache = null;\n this.invalidateShardManifestBySessionId(summary.id);\n this.indexAppendCount++;\n // Auto-compact periodically to remove tombstones and duplicates.\n // compactIndexInner() is called WHILE the lock is held — it must not\n // re-acquire it (withFileLock is not reentrant) or it would deadlock.\n if (this.indexAppendCount >= DefaultSessionStore.COMPACT_EVERY) {\n shouldCompact = true;\n this.indexAppendCount = 0;\n }\n });\n if (shouldCompact) {\n await withFileLock(this.indexFile, () => this.compactIndexInner());\n }\n } catch {\n // best-effort — error surfaced via the storage.write event in doClose()\n }\n }\n\n /** Append a tombstone entry for a deleted session. */\n private async writeTombstone(id: string): Promise<void> {\n try {\n await ensureDir(this.dir);\n await withFileLock(this.indexFile, async () => {\n const line = JSON.stringify({ action: 'delete', id }) + '\\n';\n await fsp.appendFile(this.indexFile, line, 'utf8');\n this._indexCache = null;\n this.invalidateShardManifestBySessionId(id);\n this.indexAppendCount++;\n });\n } catch {\n // best-effort\n }\n }\n\n /**\n * Compact the index: read all entries, drop tombstones, deduplicate\n * (keep latest per session), and rewrite atomically. Acquires the index\n * file lock so a concurrent append (this process or another wstack in the\n * same project) can't be overwritten by the rewrite.\n */\n private async compactIndex(): Promise<void> {\n const t0 = Date.now();\n let outcome: 'success' | 'failure' = 'success';\n let errorMsg: string | undefined;\n try {\n await withFileLock(this.indexFile, () => this.compactIndexInner());\n } catch (err) {\n outcome = 'failure';\n errorMsg = toErrorMessage(err);\n } finally {\n // Compact is internal — use 'session' as the session ID placeholder.\n this.emitWrite('~compact~', this.indexFile, 'compact', outcome, Date.now() - t0, undefined, errorMsg);\n }\n }\n\n /**\n * Lock-free compaction body. The caller MUST already hold the index file\n * lock (via withFileLock(this.indexFile, ...)). Uses atomicWrite for the\n * rewrite so the temp file gets a random suffix (no collision between two\n * compactions) and the Windows transient-EPERM rename retry.\n */\n private async compactIndexInner(): Promise<void> {\n const entries = await this.readIndex();\n if (entries.length === 0) return;\n const lines = entries.map((s) => JSON.stringify(s)).join('\\n') + '\\n';\n await atomicWrite(this.indexFile, lines, { mode: 0o600 });\n this._indexCache = null;\n }\n\n /**\n * Read the index file and return deduplicated session summaries.\n * Entries with a matching tombstone are filtered out.\n * Returns empty array when the index doesn't exist or is corrupt.\n */\n private async readIndex(): Promise<SessionSummary[]> {\n let stat: { mtimeMs: number; size: number };\n try {\n const s = await fsp.stat(this.indexFile);\n stat = { mtimeMs: s.mtimeMs, size: s.size };\n } catch {\n this._indexCache = null;\n return [];\n }\n\n if (\n this._indexCache !== null &&\n this._indexCache.mtimeMs === stat.mtimeMs &&\n this._indexCache.size === stat.size\n ) {\n return [...this._indexCache.summaries];\n }\n\n let raw: string;\n try {\n raw = await fsp.readFile(this.indexFile, 'utf8');\n } catch {\n this._indexCache = null;\n return [];\n }\n const deleted = new Set<string>();\n const seen = new Map<string, SessionSummary>();\n for (const line of raw.split('\\n')) {\n if (!line.trim()) continue;\n try {\n const entry = JSON.parse(line) as { action?: string | undefined; id?: string | undefined } & SessionSummary;\n if (entry.action === 'delete' && entry.id) {\n deleted.add(entry.id);\n seen.delete(entry.id);\n continue;\n }\n if (entry.id && !deleted.has(entry.id)) {\n // Keep the latest entry for each session (multiple appends on resume).\n seen.set(entry.id, entry as SessionSummary);\n }\n } catch {\n // skip corrupt lines\n }\n }\n const summaries = Array.from(seen.values());\n // Sort once when the index is (re)loaded so `list()` callers can\n // take a prefix without re-sorting the whole array per request.\n // Sort key mirrors the original `list()` comparator:\n // startedAt DESC, then id ASC for tie-breaks.\n summaries.sort((a, b) => {\n if (a.startedAt < b.startedAt) return 1;\n if (a.startedAt > b.startedAt) return -1;\n return a.id.localeCompare(b.id);\n });\n this._indexCache = { ...stat, summaries };\n return [...summaries];\n }\n\n /**\n * Rebuild the index from disk by scanning all sessions and writing a\n * fresh _index.jsonl. Useful after manual cleanup or index corruption.\n */\n async rebuildIndex(): Promise<number> {\n const ids = await this.collectSessionIds(this.dir);\n /* v8 ignore next -- summaryFor() never rejects for a collected id (its .jsonl exists) */\n const summaries = await Promise.all(ids.map((id) => this.summaryFor(id).catch(() => null))); /* best-effort */\n const valid = summaries.filter((s): s is SessionSummary => s !== null);\n // Atomic rewrite under the index lock so it can't clobber a concurrent\n // append (or be clobbered by a concurrent compaction). atomicWrite gives\n // a random temp suffix (no collision with compactIndexInner's temp) and\n // the Windows transient-EPERM rename retry. The expensive disk scan above\n // runs OUTSIDE the lock to avoid holding it for the whole rebuild.\n const lines = valid.map((s) => JSON.stringify(s)).join('\\n') + '\\n';\n await withFileLock(this.indexFile, async () => {\n await atomicWrite(this.indexFile, lines, { mode: 0o600 });\n this._indexCache = null;\n });\n return valid.length;\n }\n\n private async listFromDirectoryScan(limit: number): Promise<SessionSummary[]> {\n const shardKeys = await this.collectShardKeys();\n const shardEntries = await mapWithConcurrency(\n shardKeys,\n DefaultSessionStore.LIST_SCAN_CONCURRENCY,\n async (shardKey) => await this.readOrBuildShardManifest(shardKey),\n );\n\n const out: DirectorySummaryCandidate[] = [];\n for (const entry of shardEntries) {\n for (const summary of entry.summaries) {\n out.push({ summary, needsBackfill: false });\n }\n }\n out.sort((a, b) => compareSessionSummaries(a.summary, b.summary));\n\n const selected = out.slice(0, limit);\n const summaries = await mapWithConcurrency(\n selected,\n Math.min(DefaultSessionStore.LIST_SCAN_CONCURRENCY, Math.max(1, limit)),\n async (candidate): Promise<SessionSummary | null> => candidate.summary,\n );\n return summaries.filter((s): s is SessionSummary => s !== null);\n }\n\n private async collectShardKeys(): Promise<string[]> {\n let entries: Dirent[];\n try {\n entries = await fsp.readdir(this.dir, { withFileTypes: true });\n } catch {\n return [''];\n }\n\n const shardKeys = [''];\n for (const entry of entries) {\n if (entry.name.startsWith('.') && entry.name !== '.wrongstack') continue;\n if (entry.name === 'shared' || entry.name === 'subagents' || entry.name === 'attachments') continue;\n if (entry.isDirectory()) shardKeys.push(entry.name);\n }\n return shardKeys;\n }\n\n private async readOrBuildShardManifest(shardKey: string): Promise<ShardManifestEntry> {\n const cached = this.shardManifestCache.get(shardKey);\n if (cached) return cached;\n\n const manifestPath = this.shardManifestPath(shardKey);\n try {\n const raw = await fsp.readFile(manifestPath, 'utf8');\n const parsed = JSON.parse(raw) as ShardManifestEntry;\n const entry: ShardManifestEntry = {\n summaries: Array.isArray(parsed.summaries) ? parsed.summaries : [],\n ids: Array.isArray(parsed.ids) ? parsed.ids : [],\n };\n this.shardManifestCache.set(shardKey, entry);\n return entry;\n } catch {\n // build below\n }\n\n const refs = await this.collectSessionFilesInShard(shardKey);\n const candidates = await mapWithConcurrency(\n refs,\n DefaultSessionStore.LIST_SCAN_CONCURRENCY,\n async (ref): Promise<DirectorySummaryCandidate | null> => {\n const manifest = await this.readSummaryManifest(ref.id);\n if (manifest) return { summary: manifest, needsBackfill: false };\n const summary = await this.summaryHeaderFor(ref);\n if (!summary) return null;\n const hydrated = await this.summaryFor(summary.id).catch(() => summary);\n return { summary: hydrated, needsBackfill: false };\n },\n );\n const summaries = candidates\n .filter((candidate): candidate is DirectorySummaryCandidate => candidate !== null)\n .map((candidate) => candidate.summary);\n summaries.sort(compareSessionSummaries);\n const entry: ShardManifestEntry = { summaries, ids: summaries.map((summary) => summary.id) };\n this.shardManifestCache.set(shardKey, entry);\n await atomicWrite(manifestPath, JSON.stringify(entry), { mode: 0o600 }).catch(() => undefined);\n return entry;\n }\n\n private async collectSessionFilesInShard(shardKey: string): Promise<SessionFileRef[]> {\n const dir = shardKey ? path.join(this.dir, shardKey) : this.dir;\n const entries = await this.collectSessionFiles(dir, shardKey);\n return shardKey\n ? entries.filter((entry) => entry.id.startsWith(`${shardKey}/`))\n : entries.filter((entry) => !entry.id.includes('/'));\n }\n\n private async collectSessionFiles(\n dir: string,\n prefix = '',\n depth = 0,\n ): Promise<SessionFileRef[]> {\n let entries: Dirent[];\n try {\n entries = await fsp.readdir(dir, { withFileTypes: true });\n } catch {\n return [];\n }\n\n const dirEntries: Dirent[] = [];\n const files: SessionFileRef[] = [];\n for (const entry of entries) {\n if (entry.name.startsWith('.') && entry.name !== '.wrongstack') continue;\n if (entry.name === 'shared' || entry.name === 'subagents' || entry.name === 'attachments')\n continue;\n if (entry.isDirectory()) {\n dirEntries.push(entry);\n } else if (entry.isFile() && entry.name.endsWith('.jsonl')) {\n if (entry.name === '_index.jsonl') continue;\n const base = entry.name.replace(/\\.jsonl$/, '');\n const id = prefix ? `${prefix}/${base}` : base;\n files.push({ id, filePath: path.join(dir, entry.name) });\n }\n }\n\n const childFileArrays = await Promise.all(\n dirEntries.map((entry) => {\n const childPrefix = depth === 0 ? entry.name : `${prefix}/${entry.name}`;\n return this.collectSessionFiles(path.join(dir, entry.name), childPrefix, depth + 1);\n }),\n );\n\n return [...childFileArrays.flat(), ...files];\n }\n\n /** Recursively collect session IDs from date-shard subdirectories.\n * IDs include the date-prefix path (e.g. \"2026-06-06/17-46-57Z_…\").\n * Skips `.jsonl`/`.summary.json` root files, dot-files, and\n * sub-directories that belong to fleet/subagent sessions. */\n private async collectSessionIds(\n dir: string,\n prefix = '',\n depth = 0,\n ): Promise<string[]> {\n let entries: Dirent[];\n try {\n entries = await fsp.readdir(dir, { withFileTypes: true });\n } catch {\n return [];\n }\n\n // Separate dirs and files in one pass — avoids a second iteration.\n const dirEntries: Dirent[] = [];\n const fileIds: string[] = [];\n for (const entry of entries) {\n if (entry.name.startsWith('.') && entry.name !== '.wrongstack') continue;\n if (entry.name === 'shared' || entry.name === 'subagents' || entry.name === 'attachments')\n continue;\n if (entry.isDirectory()) {\n dirEntries.push(entry);\n } else if (entry.isFile() && entry.name.endsWith('.jsonl')) {\n if (entry.name === '_index.jsonl') continue;\n const base = entry.name.replace(/\\.jsonl$/, '');\n fileIds.push(prefix ? `${prefix}/${base}` : base);\n }\n }\n\n // At depth 0 the date-shard directories are independent — parallelize across\n // them. Deeper recursion (intra-shard) is sequential since shards are small.\n const childIdArrays = await Promise.all(\n dirEntries.map((entry) => {\n const childPrefix = depth === 0 ? entry.name : `${prefix}/${entry.name}`;\n return this.collectSessionIds(path.join(dir, entry.name), childPrefix, depth + 1);\n }),\n );\n\n return [...childIdArrays.flat(), ...fileIds];\n }\n\n private async summaryFor(id: string): Promise<SessionSummary> {\n const manifest = this.sessionPath(id, '.summary.json');\n const t0 = Date.now();\n let outcome: 'success' | 'failure' = 'success';\n let errorMsg: string | undefined;\n const fromManifest = await this.readSummaryManifest(id, t0);\n if (fromManifest) return fromManifest;\n\n try {\n const full = this.sessionPath(id, '.jsonl');\n const stat = await fsp.stat(full);\n const summary = await this.summarize(id, stat.mtime.toISOString());\n await atomicWrite(manifest, JSON.stringify(summary), { mode: 0o600 }).catch((err) => {\n const msg = toErrorMessage(err);\n this.emitError(id, manifest, 'summary_fallback', msg, true);\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'session_store.manifest_write_failed',\n sessionId: id,\n message: msg,\n timestamp: new Date().toISOString(),\n }));\n });\n outcome = 'failure';\n errorMsg = 'summary fallback — manifest rebuilt';\n this.emitRead(id, manifest, 'summary', outcome, Date.now() - t0, errorMsg);\n return summary;\n } catch (err) {\n outcome = 'failure';\n errorMsg = toErrorMessage(err);\n this.emitRead(id, manifest, 'summary', outcome, Date.now() - t0, errorMsg);\n return {\n id,\n title: '(damaged)',\n startedAt: new Date().toISOString(),\n model: 'unknown',\n provider: 'unknown',\n tokenTotal: 0,\n };\n }\n }\n\n private async readSummaryManifest(\n id: string,\n startTime = Date.now(),\n ): Promise<SessionSummary | null> {\n const manifest = this.sessionPath(id, '.summary.json');\n try {\n const raw = await fsp.readFile(manifest, 'utf8');\n this.emitRead(id, manifest, 'summary', 'success', Date.now() - startTime);\n return JSON.parse(raw) as SessionSummary;\n } catch {\n return null;\n }\n }\n\n private async summaryHeaderFor(ref: SessionFileRef): Promise<SessionSummary | null> {\n let mtime = new Date(0).toISOString();\n try {\n const stat = await fsp.stat(ref.filePath);\n if (!stat.isFile()) {\n return {\n id: ref.id,\n title: '(damaged)',\n startedAt: stat.mtime.toISOString(),\n model: 'unknown',\n provider: 'unknown',\n tokenTotal: 0,\n };\n }\n mtime = stat.mtime.toISOString();\n } catch {\n return null;\n }\n\n try {\n for await (const event of this.iterSessionEvents(ref.filePath)) {\n if (event.type === 'session_start') {\n return {\n id: ref.id,\n title: '(empty session)',\n startedAt: event.ts,\n model: event.model ?? 'unknown',\n provider: event.provider ?? 'unknown',\n tokenTotal: 0,\n };\n }\n }\n return {\n id: ref.id,\n title: '(empty session)',\n startedAt: new Date(0).toISOString(),\n model: 'unknown',\n provider: 'unknown',\n tokenTotal: 0,\n };\n } catch {\n return {\n id: ref.id,\n title: '(damaged)',\n startedAt: mtime,\n model: 'unknown',\n provider: 'unknown',\n tokenTotal: 0,\n };\n }\n }\n\n /**\n * Delete a session and all associated files: JSONL, summary, plan/todos\n * sidecars, and the session directory (fleet.json, shared/, subagents/).\n *\n * Individual file deletions are best-effort (logged as structured warnings),\n * but a tombstone is always written so readIndex() filters this session out.\n * If the session directory itself can't be removed, the error is surfaced\n * to the caller so prune() can report it.\n */\n private async deleteSession(id: string): Promise<void> {\n const jsonlPath = this.sessionPath(id, '.jsonl');\n const summaryPath = this.sessionPath(id, '.summary.json');\n const shardDir = path.dirname(jsonlPath);\n const base = path.basename(id);\n const sessDir = path.join(shardDir, base);\n\n const deletions: Array<Promise<void>> = [\n fsp.unlink(jsonlPath),\n fsp.unlink(summaryPath),\n fsp.unlink(sessionScopedPath(this.dir, id, '.plan.json')),\n fsp.unlink(sessionScopedPath(this.dir, id, '.tasks.json')),\n fsp.unlink(sessionScopedPath(this.dir, id, '.todos.json')),\n ];\n\n const results = await Promise.allSettled(deletions);\n for (const r of results) {\n if (r.status === 'rejected') {\n const msg = r.reason instanceof Error ? r.reason.message : String(r.reason);\n // ENOENT is expected (file may not exist — sidecars are optional).\n if ((r.reason as NodeJS.ErrnoException)?.code !== 'ENOENT') {\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'session_store.delete_failed',\n sessionId: id,\n message: msg,\n timestamp: new Date().toISOString(),\n }));\n }\n }\n }\n\n // Remove the session directory (may contain fleet.json, shared/, subagents/).\n /* v8 ignore start -- defensive: rm with force:true rarely rejects */\n await fsp.rm(sessDir, { recursive: true, force: true }).catch((err) => {\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'session_store.rmdir_failed',\n sessionId: id,\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n });\n /* v8 ignore stop */\n\n // Write an index tombstone so readIndex() filters this session out.\n await this.writeTombstone(id);\n }\n\n async delete(id: string): Promise<void> {\n await this.deleteSession(id);\n }\n\n async prune(maxAgeDays = 30): Promise<number> {\n const cutoff = Date.now() - maxAgeDays * 86_400_000;\n let deleted = 0;\n\n // Read the active session lock to avoid pruning the current session.\n let activeSessionId: string | null = null;\n try {\n const raw = await fsp.readFile(path.join(this.dir, 'active.json'), 'utf8');\n const active = JSON.parse(raw) as { sessionId?: string | undefined };\n activeSessionId = active.sessionId ?? null;\n } catch {\n // no active.json — nothing to protect\n }\n\n const isPrunableJsonl = (name: string): boolean =>\n name.endsWith('.jsonl') &&\n name !== '_index.jsonl' &&\n name !== '_mailbox.jsonl' &&\n !name.endsWith('.replay.jsonl') &&\n !name.endsWith('.audit.jsonl');\n\n const pruneFile = async (dir: string, name: string, prefix: string): Promise<void> => {\n const jsonlPath = path.join(dir, name);\n try {\n const stat = await fsp.stat(jsonlPath);\n if (stat.mtimeMs >= cutoff) return;\n /* v8 ignore start -- defensive: file vanished between readdir and stat */\n } catch {\n return;\n }\n /* v8 ignore stop */\n const base = name.replace(/\\.jsonl$/, '');\n const id = prefix ? `${prefix}/${base}` : base;\n // Never prune the currently active session.\n if (activeSessionId && id === activeSessionId) return;\n await this.deleteSession(id);\n deleted++;\n };\n\n /* v8 ignore next -- defensive: store dir is ensured before prune runs */\n const entries = await fsp.readdir(this.dir, { withFileTypes: true }).catch(() => []);\n for (const entry of entries) {\n if (entry.isFile()) {\n // Flat legacy sessions at the sessions root — pre-shard layout.\n // A shard-only scan left these accumulating forever.\n if (isPrunableJsonl(entry.name)) await pruneFile(this.dir, entry.name, '');\n continue;\n }\n /* v8 ignore next -- defensive: root entries are only files or directories */\n if (!entry.isDirectory()) continue;\n // entry.name is a date-shard like \"2026-06-06\"\n const dateDir = path.join(this.dir, entry.name);\n /* v8 ignore next -- defensive: dateDir came from readdir and is readable */\n const files = await fsp.readdir(dateDir, { withFileTypes: true }).catch(() => []);\n for (const file of files) {\n if (!file.isFile() || !isPrunableJsonl(file.name)) continue;\n await pruneFile(dateDir, file.name, entry.name);\n }\n }\n if (deleted > 0) {\n // Compact the index to remove tombstones for deleted sessions.\n /* v8 ignore next -- best-effort: compactIndex swallows its own errors */\n await this.compactIndex().catch(() => undefined); /* best-effort */\n }\n // Clean up empty date-shard directories left behind after pruning.\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const dateDir = path.join(this.dir, entry.name);\n try {\n const remaining = await fsp.readdir(dateDir);\n if (remaining.length === 0) {\n /* v8 ignore next -- best-effort: rmdir of a confirmed-empty dir does not reject */\n await fsp.rmdir(dateDir).catch(() => undefined);\n }\n } catch {\n // best-effort\n }\n }\n return deleted;\n }\n\n async clearHistory(id: string): Promise<void> {\n await this.ensureShardDir(id);\n const file = this.sessionPath(id, '.jsonl');\n const meta = this.sessionPath(id, '.summary.json');\n const record = `${JSON.stringify({\n type: 'session_start',\n ts: new Date().toISOString(),\n id,\n model: 'unknown',\n provider: 'unknown',\n })}\\n`;\n await fsp.writeFile(file, record, 'utf8');\n await fsp.unlink(meta).catch(() => undefined);\n }\n\n private async summarize(id: string, mtime: string): Promise<SessionSummary> {\n try {\n const file = this.sessionPath(id, '.jsonl');\n let title = '(empty session)';\n let startedAt = new Date(0).toISOString();\n let endedAt: string | undefined;\n let model = 'unknown';\n let provider = 'unknown';\n let tokenIn = 0;\n let tokenOut = 0;\n let iterationCount = 0;\n let toolCallCount = 0;\n let toolErrorCount = 0;\n let fileChangeCount = 0;\n const toolBreakdown: Record<string, number> = {};\n let outcome: SessionSummary['outcome'] ;\n let lastEventType: SessionEvent['type'] | undefined;\n let hasError = false;\n let sawStart = false;\n\n for await (const e of this.iterSessionEvents(file)) {\n lastEventType = e.type;\n if (e.type === 'session_start') {\n if (!sawStart) {\n sawStart = true;\n startedAt = e.ts;\n model = e.model ?? 'unknown';\n provider = e.provider ?? 'unknown';\n }\n } else if (e.type === 'session_end') {\n endedAt = e.ts;\n } else if (e.type === 'user_input') {\n if (title === '(empty session)') title = userInputTitle(e.content);\n } else if (e.type === 'llm_response') {\n tokenIn += e.usage.input ?? 0;\n tokenOut += e.usage.output ?? 0;\n } else if (e.type === 'in_flight_start') iterationCount++;\n else if (e.type === 'tool_call_start') {\n toolCallCount++;\n toolBreakdown[e.name] = (toolBreakdown[e.name] ?? 0) + 1;\n } else if (e.type === 'tool_result' && e.isError) toolErrorCount++;\n else if (e.type === 'file_snapshot') fileChangeCount += e.files.length;\n else if (e.type === 'error' || e.type === 'provider_error') hasError = true;\n }\n\n // Determine outcome from the last event.\n if (lastEventType === 'session_end') {\n outcome = 'completed';\n } else if (lastEventType === 'in_flight_start') {\n outcome = 'aborted';\n } else if (hasError) {\n outcome = 'error';\n }\n\n return {\n id,\n title,\n startedAt,\n endedAt,\n model,\n provider,\n tokenTotal: tokenIn + tokenOut,\n iterationCount: iterationCount > 0 ? iterationCount : undefined,\n toolCallCount: toolCallCount > 0 ? toolCallCount : undefined,\n toolErrorCount: toolErrorCount > 0 ? toolErrorCount : undefined,\n fileChangeCount: fileChangeCount > 0 ? fileChangeCount : undefined,\n toolBreakdown: Object.keys(toolBreakdown).length > 0 ? toolBreakdown : {},\n outcome,\n };\n } catch {\n return {\n id,\n title: '(damaged)',\n startedAt: mtime,\n model: 'unknown',\n provider: 'unknown',\n tokenTotal: 0,\n };\n }\n }\n\n private async *iterSessionEvents(file: string): AsyncGenerator<SessionEvent> {\n const stream = createReadStream(file, { encoding: 'utf8' });\n const lines = createInterface({ input: stream, crlfDelay: Infinity });\n try {\n for await (const line of lines) {\n if (!line.trim()) continue;\n try {\n const parsed: unknown = JSON.parse(line);\n if (\n parsed !== null &&\n typeof parsed === 'object' &&\n typeof (parsed as { type?: unknown | undefined }).type === 'string' &&\n typeof (parsed as { ts?: unknown | undefined }).ts === 'string'\n ) {\n yield parsed as SessionEvent;\n }\n } catch {\n // skip malformed JSON\n }\n }\n } finally {\n lines.close();\n stream.destroy();\n }\n }\n\n\n}\n","import * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { EventBus } from '../kernel/events.js';\nimport type { ContentBlock } from '../types/blocks.js';\nimport { atomicWrite } from '../utils/atomic-write.js';\nimport { toErrorMessage } from '../utils/error.js';\n\n/**\n * The persisted form of a single queued user message. The TUI's\n * in-memory QueueItem has a render id; that's pure UI bookkeeping, so\n * we drop it when serializing — fresh ids are assigned on rehydrate.\n */\nexport interface PersistedQueueItem {\n displayText: string;\n blocks: ContentBlock[];\n}\n\n/**\n * Side-file storage for a session's pending input queue. Lives at\n * `<sessionDir>/queue.json` next to the attachment spool. Reads are\n * tolerant (missing/malformed file → empty array); writes are atomic\n * (tmp + rename) so a crash mid-write can never leave a partial file\n * the next launch would choke on.\n *\n * The contract is \"snapshot replacement\": every mutation hands the\n * full queue and we rewrite the file. The queue is small (rarely more\n * than a handful of messages), so this is cheaper than delta logging\n * and avoids the replay complexity.\n */\nexport class QueueStore {\n private readonly file: string;\n // Use `| undefined` (not `?`) so exactOptionalPropertyTypes doesn't\n // reject assigning an optional constructor parameter to these fields.\n private readonly events: EventBus | undefined;\n private readonly traceId: string | undefined;\n\n constructor(opts: { dir: string; events?: EventBus; traceId?: string }) {\n this.file = path.join(opts.dir, 'queue.json');\n this.events = opts.events;\n this.traceId = opts.traceId;\n }\n\n async write(items: PersistedQueueItem[]): Promise<void> {\n const t0 = Date.now();\n if (items.length === 0) {\n // Empty queue → remove the file rather than write `[]`. Keeps\n // a clean idle state on disk and makes `read()` cheaper.\n await this.clear();\n return;\n }\n try {\n await atomicWrite(this.file, JSON.stringify(items), { mode: 0o600 });\n this.events?.emit('storage.write', {\n sessionId: this.traceId ?? '~boot~',\n store: 'queue',\n filePath: this.file,\n operation: 'write',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n } catch (err) {\n this.events?.emit('storage.error', {\n sessionId: this.traceId ?? '~boot~',\n store: 'queue',\n filePath: this.file,\n operation: 'write',\n outcome: 'failure',\n error: toErrorMessage(err),\n recoverable: false,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'queue_store.write_failed',\n path: this.file,\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n }\n }\n\n async read(): Promise<PersistedQueueItem[]> {\n const t0 = Date.now();\n let raw: string;\n try {\n raw = await fsp.readFile(this.file, 'utf8');\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') {\n this.events?.emit('storage.read', {\n sessionId: this.traceId ?? '~boot~',\n store: 'queue',\n filePath: this.file,\n operation: 'read',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n return [];\n }\n this.events?.emit('storage.error', {\n sessionId: this.traceId ?? '~boot~',\n store: 'queue',\n filePath: this.file,\n operation: 'read',\n outcome: 'failure',\n error: toErrorMessage(err),\n recoverable: true,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'queue_store.read_failed',\n path: this.file,\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n return [];\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n this.events?.emit('storage.read', {\n sessionId: this.traceId ?? '~boot~',\n store: 'queue',\n filePath: this.file,\n operation: 'read',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'parse_failed',\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n return [];\n }\n if (!Array.isArray(parsed)) {\n this.events?.emit('storage.read', {\n sessionId: this.traceId ?? '~boot~',\n store: 'queue',\n filePath: this.file,\n operation: 'read',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'invalid_schema',\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n return [];\n }\n this.events?.emit('storage.read', {\n sessionId: this.traceId ?? '~boot~',\n store: 'queue',\n filePath: this.file,\n operation: 'read',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n const out: PersistedQueueItem[] = [];\n for (const v of parsed) {\n if (isPersistedQueueItem(v)) out.push(v);\n }\n return out;\n }\n\n async clear(): Promise<void> {\n const t0 = Date.now();\n try {\n await fsp.unlink(this.file);\n this.events?.emit('storage.write', {\n sessionId: this.traceId ?? '~boot~',\n store: 'queue',\n filePath: this.file,\n operation: 'clear',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') return;\n this.events?.emit('storage.error', {\n sessionId: this.traceId ?? '~boot~',\n store: 'queue',\n filePath: this.file,\n operation: 'clear',\n outcome: 'failure',\n error: toErrorMessage(err),\n recoverable: true,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n // Best-effort: a permission/lock error during clear is rare and\n // the queue slash command is non-critical. Warn so it's observable\n // but don't throw so the slash command doesn't crash.\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'queue_store.clear_failed',\n path: this.file,\n message: (err as Error).message,\n timestamp: new Date().toISOString(),\n }));\n }\n }\n}\n\nfunction isPersistedQueueItem(v: unknown): v is PersistedQueueItem {\n if (typeof v !== 'object' || v === null) return false;\n const o = v as Record<string, unknown>;\n return typeof o['displayText'] === 'string' && Array.isArray(o['blocks']);\n}\n","import { randomBytes } from 'node:crypto';\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { atomicWrite } from '../utils/atomic-write.js';\nimport type {\n AddAttachmentInput,\n Attachment,\n AttachmentKind,\n AttachmentRef,\n AttachmentStore,\n} from '../types/attachment.js';\nimport type { ContentBlock } from '../types/blocks.js';\n\nexport interface AttachmentStoreOptions {\n /**\n * Directory for spooling payloads larger than `spoolThresholdBytes`.\n * When omitted, all payloads stay in memory.\n */\n spoolDir?: string | undefined;\n spoolThresholdBytes?: number | undefined;\n}\n\nconst DEFAULT_SPOOL_THRESHOLD = 256 * 1024; // 256 KB\n// Two placeholder shapes:\n// - seq-keyed `[<kind> #<seq>…]` — kind is `pasted` / `image` / `file`. A\n// cosmetic suffix after the seq (e.g. `, 123 lines`) is tolerated so the\n// TUI can render `[pasted #1, 123 lines]` while still resolving by seq.\n// - path-keyed `[file:<path>]` — resolves to the most recent file ref whose\n// stored path matches, so the TUI can show a human-readable file chip.\nconst PLACEHOLDER_RE = /\\[(pasted|image|file) #(\\d+)[^\\]]*\\]|\\[file:([^\\]]+)\\]/g;\n\n/**\n * In-memory attachment store with optional disk spool. Placeholder syntax\n * is `[<kind> #<seq>]` (seq-keyed) or `[file:<path>]` (path-keyed) where kind\n * is `pasted` / `image` / `file`. Unknown placeholders are passed through\n * as-is so users can write that literal text without losing it.\n */\nexport class DefaultAttachmentStore implements AttachmentStore {\n private readonly items = new Map<string, Attachment>();\n private readonly refs: AttachmentRef[] = [];\n private nextSeq: Record<AttachmentKind, number> = { text: 0, image: 0, file: 0 };\n private readonly spoolDir: string | undefined;\n private readonly spoolThreshold: number;\n\n constructor(opts: AttachmentStoreOptions = {}) {\n this.spoolDir = opts.spoolDir;\n this.spoolThreshold = opts.spoolThresholdBytes ?? DEFAULT_SPOOL_THRESHOLD;\n }\n\n async add(input: AddAttachmentInput): Promise<AttachmentRef> {\n const seq = ++this.nextSeq[input.kind];\n const id = `${kindPrefix(input.kind)}-${seq}-${randomBytes(3).toString('hex')}`;\n const bytes = Buffer.byteLength(input.data, input.kind === 'image' ? 'base64' : 'utf8');\n let spooledPath: string | undefined;\n let data: string | undefined = input.data;\n if (this.spoolDir && bytes >= this.spoolThreshold) {\n await fsp.mkdir(this.spoolDir, { recursive: true });\n spooledPath = path.join(this.spoolDir, `${id}.bin`);\n // atomicWrite: torn spool would silently corrupt the attachment;\n // the user would see garbled output the next time it's expanded.\n await atomicWrite(spooledPath, input.data, {\n encoding: input.kind === 'image' ? 'base64' : 'utf8',\n });\n data = undefined;\n }\n const att: Attachment = {\n id,\n kind: input.kind,\n meta: input.meta ?? {},\n data,\n path: spooledPath,\n bytes,\n createdAt: new Date().toISOString(),\n };\n this.items.set(id, att);\n const ref: AttachmentRef = { id, kind: input.kind, seq, meta: att.meta };\n this.refs.push(ref);\n return ref;\n }\n\n async get(id: string): Promise<Attachment | undefined> {\n return this.items.get(id);\n }\n\n list(): AttachmentRef[] {\n return [...this.refs];\n }\n\n async expand(text: string): Promise<ContentBlock[]> {\n const matches = [...text.matchAll(PLACEHOLDER_RE)];\n if (matches.length === 0) return text ? [{ type: 'text', text }] : [];\n const blocks: ContentBlock[] = [];\n let lastIndex = 0;\n for (const m of matches) {\n const idx = m.index ?? 0;\n const before = text.slice(lastIndex, idx);\n if (before) blocks.push({ type: 'text', text: before });\n let ref: AttachmentRef | undefined;\n if (m[3] !== undefined) {\n // Path-keyed `[file:<path>]` — most recent matching file ref wins.\n const wantPath = m[3];\n ref = findLast(this.refs, (r) => r.kind === 'file' && refPath(r) === wantPath);\n } else {\n const kind = prefixToKind(m[1] as string);\n const seq = Number(m[2]);\n ref = this.refs.find((r) => r.kind === kind && r.seq === seq);\n }\n const att = ref ? this.items.get(ref.id) : undefined;\n if (!att) {\n blocks.push({ type: 'text', text: m[0] });\n } else {\n blocks.push(await this.toBlock(att));\n }\n lastIndex = idx + m[0].length;\n }\n const tail = text.slice(lastIndex);\n if (tail) blocks.push({ type: 'text', text: tail });\n return mergeAdjacentText(blocks);\n }\n\n async clear(): Promise<void> {\n // Unlink any spooled files so we don't leak disk space.\n if (this.spoolDir) {\n const toDelete: string[] = [];\n for (const att of this.items.values()) {\n if (att.path) toDelete.push(att.path);\n }\n /* v8 ignore next -- best-effort: unlink of a just-spooled file does not reject */\n await Promise.all(toDelete.map((p) => fsp.unlink(p).catch(() => undefined)));\n }\n this.items.clear();\n this.refs.length = 0;\n this.nextSeq = { text: 0, image: 0, file: 0 };\n }\n\n private async toBlock(att: Attachment): Promise<ContentBlock> {\n if (att.kind === 'image') {\n const data =\n att.data ?? (att.path ? await fsp.readFile(att.path, { encoding: 'base64' }) : '');\n return {\n type: 'image',\n source: {\n type: 'base64',\n media_type: att.meta.mediaType ?? 'image/png',\n data,\n },\n };\n }\n const raw = att.data ?? (att.path ? await fsp.readFile(att.path, 'utf8') : '');\n const label = att.meta.filename ? `<file path=\"${att.meta.filename}\">` : '<pasted>';\n const close = att.meta.filename ? '</file>' : '</pasted>';\n return { type: 'text', text: `${label}\\n${raw}\\n${close}` };\n }\n}\n\nfunction kindPrefix(kind: AttachmentKind): string {\n return kind === 'text' ? 'pasted' : kind;\n}\n\nfunction prefixToKind(prefix: string): AttachmentKind {\n if (prefix === 'pasted') return 'text';\n if (prefix === 'image') return 'image';\n return 'file';\n}\n\n/** Path a file ref was registered under, for `[file:<path>]` lookup. */\nfunction refPath(ref: AttachmentRef): string | undefined {\n return ref.meta.filename ?? ref.meta.label;\n}\n\n/** Last element matching the predicate (Node < 20 lacks Array.findLast). */\nfunction findLast<T>(arr: readonly T[], pred: (v: T) => boolean): T | undefined {\n for (let i = arr.length - 1; i >= 0; i--) {\n if (pred(arr[i] as T)) return arr[i];\n }\n return undefined;\n}\n\nfunction mergeAdjacentText(blocks: ContentBlock[]): ContentBlock[] {\n const out: ContentBlock[] = [];\n for (const b of blocks) {\n const prev = out[out.length - 1];\n if (b.type === 'text' && prev && prev.type === 'text') {\n prev.text += b.text;\n } else {\n out.push(b);\n }\n }\n return out;\n}\n","export type MemoryScope = 'project-agents' | 'project-memory' | 'user-memory';\n\n// ── Memory categories ──────────────────────────────────────────────────\n\nexport type MemoryType = 'fact' | 'decision' | 'convention' | 'preference' | 'reference' | 'anti_pattern';\n\nexport const MEMORY_TYPE_LABELS: Record<MemoryType, string> = {\n fact: 'Fact',\n decision: 'Decision',\n convention: 'Convention',\n preference: 'Preference',\n reference: 'Reference',\n anti_pattern: 'Anti-pattern',\n};\n\nexport type MemoryPriority = 'critical' | 'high' | 'medium' | 'low';\n\nexport interface MemoryEntry {\n scope: MemoryScope;\n text: string;\n ts: string;\n /** Category — helps the agent decide whether to inject or ignore. */\n type?: MemoryType | undefined;\n /** Free-form tags for grouping (e.g. [\"build\", \"pnpm\", \"typescript\"]). */\n tags?: string[] | undefined;\n /** Priority — critical entries are always injected; low may be skipped. */\n priority?: MemoryPriority | undefined;\n /** Session or agent that created this entry. */\n source?: string | undefined;\n /** 0.0–1.0 confidence. Low-confidence entries are injected less often. */\n confidence?: number | undefined;\n /** ISO timestamp of last access (read or injection into context). */\n lastAccessed?: string | undefined;\n}\n\n// ── Memory events — emitted by DefaultMemoryStore so plugins can react ──\n\nexport interface MemoryRememberedPayload {\n scope: MemoryScope;\n text: string;\n ts: string;\n type?: MemoryType | undefined;\n tags?: string[] | undefined;\n priority?: MemoryPriority | undefined;\n}\n\nexport interface MemoryForgottenPayload {\n scope: MemoryScope;\n query: string;\n removed: number;\n}\n\nexport interface MemoryClearedPayload {\n /** Scope that was cleared, or undefined when all scopes were cleared. */\n scope?: MemoryScope | undefined;\n}\n\nexport interface MemoryConsolidatedPayload {\n scope: MemoryScope;\n /** Entries removed by deduplication. */\n removed: number;\n}\n\n// ── Relevance scoring ──────────────────────────────────────────────────\n\n/**\n * Context used to score memory relevance for context injection.\n * Passed by the system prompt builder.\n */\nexport interface MemoryRelevanceContext {\n /** Current user message or task description. */\n currentTask: string;\n /** Active skills in this session (e.g. [\"typescript-strict\", \"git-flow\"]). */\n activeSkills?: string[] | undefined;\n /** Active mode (e.g. \"Teach\", \"Brief\", \"Code Reviewer\"). */\n activeMode?: string | undefined;\n /** Available tools — memories referencing relevant tools score higher. */\n toolNames?: string[] | undefined;\n}\n\nexport interface ScoredEntry extends MemoryEntry {\n score: number;\n matchReason: string;\n}\n\n// ── Store interface ────────────────────────────────────────────────────\n\nexport interface MemoryStore {\n readAll(): Promise<string>;\n read(scope: MemoryScope): Promise<string>;\n remember(text: string, scope?: MemoryScope, metadata?: Omit<Partial<MemoryEntry>, 'scope' | 'text' | 'ts'>): Promise<void>;\n forget(query: string, scope?: MemoryScope): Promise<number>;\n consolidate(scope: MemoryScope): Promise<void>;\n clear(scope?: MemoryScope): Promise<void>;\n /** List entries, newest first. */\n list(scope?: MemoryScope, limit?: number): Promise<MemoryEntry[]>;\n /** Search by content (substring or semantic). */\n search(query: string, scope?: MemoryScope, limit?: number): Promise<MemoryEntry[]>;\n /** Access the backend for advanced queries. */\n getBackend?(): unknown;\n /** Graph-based related memory traversal. */\n findRelated?(text: string, scope?: MemoryScope, limit?: number): Promise<MemoryEntry[]>;\n /**\n * Score and rank memories by relevance to the current context.\n * Returns only entries that meet a relevance threshold.\n */\n scoreRelevant?(ctx: MemoryRelevanceContext, scope?: MemoryScope, limit?: number): Promise<ScoredEntry[]>;\n /**\n * Attach a trace ID to this store so that all subsequent `storage.*`\n * events include it for observability correlation. Mutates the store\n * in place and returns the same instance (convenience chaining).\n */\n withTraceId(traceId: string): MemoryStore;\n}\n","import { randomUUID } from 'node:crypto';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { MemoryEntry, MemoryScope } from '../types/memory.js';\nimport { MEMORY_TYPE_LABELS, type MemoryPriority, type MemoryType } from '../types/memory.js';\nimport { atomicWrite, ensureDir, withFileLock } from '../utils/atomic-write.js';\nimport type { WstackPaths } from '../utils/wstack-paths.js';\n\n// ── Backend interface ──────────────────────────────────────────────────\n\nexport interface MemoryBackend {\n readonly kind: string;\n remember(scope: MemoryScope, entry: MemoryEntry, filePath: string): Promise<void>;\n forget(scope: MemoryScope, query: string, filePath: string): Promise<number>;\n readAll(scope: MemoryScope, filePath: string): Promise<string>;\n list(scope: MemoryScope, filePath: string, limit?: number | undefined): Promise<MemoryEntry[]>;\n search(scope: MemoryScope, query: string, filePath: string, limit?: number | undefined): Promise<MemoryEntry[]>;\n /** Find memories related to the given text via graph traversal. Optional — falls back to search. */\n findRelated?(scope: MemoryScope, filePath: string, text: string, limit: number): Promise<MemoryEntry[]>;\n clear(scope: MemoryScope, filePath: string): Promise<void>;\n consolidate(scope: MemoryScope, filePath: string): Promise<number>;\n}\n\n// ── Entry serialization format ─────────────────────────────────────────\n//\n// Full format:\n// - [ISO] [TYPE|PRIORITY] mem_<id> text content #tag1 #tag2\n//\n// Examples:\n// - [2026-06-07T...] mem_1234_abcd Project uses pnpm #pnpm #build\n// - [2026-06-07T...] [convention|high] mem_5678_ef01 Use conventional commits #git #commit\n//\n// Old format (backward compatible):\n// - [ISO] mem_<id> text content\n\nconst TYPE_PRIORITY_RE = /^\\[(\\w+)\\|(\\w+)\\]\\s+/;\nconst TAG_RE = /#([\\w-]+)/g;\nconst MAX_MEMORY_CONSOLIDATE_BACKUPS = 5;\n\nfunction formatMetadata(entry: MemoryEntry): string {\n const parts: string[] = [];\n if (entry.type && entry.priority) {\n parts.push(`[${entry.type}|${entry.priority}]`);\n } else if (entry.type) {\n parts.push(`[${entry.type}]`);\n } else if (entry.priority) {\n parts.push(`[${entry.priority}]`);\n }\n if (entry.tags && entry.tags.length > 0) {\n parts.push(entry.tags.map((t) => `#${t}`).join(' '));\n }\n return parts.length > 0 ? ` ${parts.join(' ')}` : '';\n}\n\nfunction lineToEntry(line: string, scope: MemoryScope): MemoryEntry | null {\n const trimmed = line.trim();\n if (!trimmed.startsWith('- [')) return null;\n\n // Parse timestamp: `- [ISO] ...`\n const tsMatch = trimmed.match(/^-\\s*\\[([^\\]]+)\\]/);\n if (!tsMatch) return null;\n const ts = tsMatch[1] ?? '';\n\n let rest = trimmed.slice(tsMatch[0].length).trim();\n\n // Parse optional type|priority: `[convention|high]` or `[fact]`\n let type: MemoryType | undefined;\n let priority: MemoryPriority | undefined;\n const tpMatch = rest.match(TYPE_PRIORITY_RE);\n if (tpMatch) {\n const a = tpMatch[1] ?? '';\n const b = tpMatch[2] ?? '';\n if (isMemoryType(a)) {\n type = a;\n priority = isPriority(b) ? b : undefined;\n } else if (isPriority(a)) {\n priority = a;\n }\n rest = rest.slice(tpMatch[0].length).trim();\n }\n\n // Parse optional entry ID: `mem_<ts>_<rand>`\n const idMatch = rest.match(/^mem_\\d+_\\w+\\s+/);\n let text: string;\n if (idMatch) {\n text = rest.slice(idMatch[0].length).trim();\n } else {\n text = rest.trim();\n }\n\n // Extract #tags from text\n const tags: string[] = [];\n let tagMatch: RegExpExecArray | null;\n TAG_RE.lastIndex = 0;\n // biome-ignore lint/suspicious/noAssignInExpressions: standard regex loop\n while ((tagMatch = TAG_RE.exec(text)) !== null) {\n tags.push(tagMatch[1] ?? '');\n }\n // Remove tags from display text\n const cleanText = text.replace(TAG_RE, '').replace(/\\s{2,}/g, ' ').trim();\n\n if (!cleanText) return null;\n\n return {\n scope,\n text: cleanText,\n ts,\n type,\n priority,\n tags: tags.length > 0 ? tags : undefined,\n };\n}\n\nfunction isMemoryType(s: string): s is MemoryType {\n return s in MEMORY_TYPE_LABELS;\n}\n\nfunction isPriority(s: string): s is MemoryPriority {\n return s === 'critical' || s === 'high' || s === 'medium' || s === 'low';\n}\n\n// ── Inverted index for fast search ─────────────────────────────────────\n\ninterface IndexedEntry {\n entry: MemoryEntry;\n /** Lower-cased words extracted from text. */\n words: string[];\n /** Lower-cased tags. */\n tags: string[];\n}\n\ninterface InvertedIndex {\n /** word -> entry indices */\n wordMap: Map<string, number[]>;\n /** tag -> entry indices */\n tagMap: Map<string, number[]>;\n entries: IndexedEntry[];\n /** Last known file mtime for cache invalidation. */\n mtimeMs: number;\n}\n\n// Exported for the perf microbenchmark (tests/perf/memory-search.bench.ts),\n// which exercises the O(1) exact-lookup fast path against a large vocabulary.\n// Not part of the public API surface — internal to memory search.\nexport function buildInvertedIndex(entries: MemoryEntry[]): InvertedIndex {\n const wordMap = new Map<string, number[]>();\n const tagMap = new Map<string, number[]>();\n const indexed: IndexedEntry[] = new Array(entries.length);\n\n for (let i = 0; i < entries.length; i++) {\n const e = entries[i]!;\n const words = e.text.toLowerCase().split(/\\s+/).filter((w) => w.length > 0);\n const tags = (e.tags ?? []).map((t) => t.toLowerCase());\n indexed[i] = { entry: e, words, tags };\n\n for (const w of words) {\n const arr = wordMap.get(w);\n if (arr) arr.push(i);\n else wordMap.set(w, [i]);\n }\n for (const t of tags) {\n const arr = tagMap.get(t);\n if (arr) arr.push(i);\n else tagMap.set(t, [i]);\n }\n }\n\n return { wordMap, tagMap, entries: indexed, mtimeMs: 0 };\n}\n\n/**\n * Needles shorter than this skip the O(vocabulary) substring fallback. A\n * 1–2 char needle (e.g. \"a\", \"go\") otherwise forces a full-vocabulary walk\n * AND matches almost everything via `n.includes(word)`, so it's both the\n * slowest and least selective case. Exact-match lookups still run for any\n * length, so short whole-word queries (\"go\", \"ci\") keep working.\n */\nconst MIN_SUBSTRING_NEEDLE_LEN = 3;\n\n// Exported alongside buildInvertedIndex for the perf microbenchmark.\nexport function searchIndex(\n index: InvertedIndex,\n query: string,\n limit?: number,\n): MemoryEntry[] {\n const needles = query.toLowerCase().split(/\\s+/).filter((n) => n.length > 0);\n if (needles.length === 0) return [];\n\n const scores = new Map<number, number>();\n\n for (const n of needles) {\n // Fast path: exact word/tag hit via O(1) Map.get. This is the dominant\n // case (whole-word queries) and avoids walking the whole vocabulary.\n let matched = false;\n\n const wordExact = index.wordMap.get(n);\n if (wordExact) {\n for (const idx of wordExact) scores.set(idx, (scores.get(idx) ?? 0) + 1);\n matched = true;\n }\n const tagExact = index.tagMap.get(n);\n if (tagExact) {\n for (const idx of tagExact) scores.set(idx, (scores.get(idx) ?? 0) + 2);\n matched = true;\n }\n\n // Bounded substring fallback: only when the needle had no exact hit and is\n // long enough to be selective. Preserves partial-match recall (\"perf\" →\n // \"performance\", \"rebuilding\" → stored word \"build\") without paying the\n // full-vocabulary scan on every whole-word query.\n if (matched || n.length < MIN_SUBSTRING_NEEDLE_LEN) continue;\n\n for (const [word, indices] of index.wordMap) {\n if (word.includes(n) || n.includes(word)) {\n for (const idx of indices) {\n scores.set(idx, (scores.get(idx) ?? 0) + 1);\n }\n }\n }\n for (const [tag, indices] of index.tagMap) {\n if (tag.includes(n) || n.includes(tag)) {\n for (const idx of indices) {\n scores.set(idx, (scores.get(idx) ?? 0) + 2);\n }\n }\n }\n }\n\n if (scores.size === 0) return [];\n\n const scored = Array.from(scores.entries());\n scored.sort((a, b) => b[1] - a[1]);\n\n const result: MemoryEntry[] = [];\n const max = limit ? Math.min(limit, scored.length) : scored.length;\n for (let i = 0; i < max; i++) {\n result.push(index.entries[scored[i]![0]]!.entry);\n }\n return result;\n}\n\n// ── File-based backend ─────────────────────────────────────────────────\n\nexport interface FileMemoryBackendOptions {\n paths: WstackPaths;\n}\n\nexport class FileMemoryBackend implements MemoryBackend {\n readonly kind = 'file';\n private readonly files: Record<MemoryScope, string>;\n /** Cache of parsed entries per file path. */\n private readonly entryCache = new Map<string, MemoryEntry[]>();\n /** Inverted index per file path. */\n private readonly indexCache = new Map<string, InvertedIndex>();\n /** File mtime cache for invalidation. */\n private readonly mtimeCache = new Map<string, number>();\n\n constructor(opts: FileMemoryBackendOptions) {\n this.files = {\n 'project-agents': opts.paths.inProjectAgentsFile,\n 'project-memory': opts.paths.projectMemory,\n 'user-memory': opts.paths.globalMemory,\n };\n }\n\n private resolveFile(filePath: string, scope: MemoryScope): string {\n return filePath || this.files[scope];\n }\n\n private async getMtime(file: string): Promise<number> {\n try {\n const stat = await fs.stat(file);\n return stat.mtimeMs;\n } catch {\n return 0;\n }\n }\n\n private invalidateCache(file: string): void {\n this.entryCache.delete(file);\n this.indexCache.delete(file);\n this.mtimeCache.delete(file);\n }\n\n /**\n * Load (and cache) the parsed entries for a file. Callers that have already\n * stat'd the file this tick (e.g. `getIndex`) can pass the known `mtime` to\n * avoid a redundant `fs.stat` — otherwise it's fetched here.\n */\n private async loadEntries(\n file: string,\n scope: MemoryScope,\n mtime?: number,\n ): Promise<MemoryEntry[]> {\n const resolvedMtime = mtime ?? (await this.getMtime(file));\n const cachedMtime = this.mtimeCache.get(file);\n if (cachedMtime === resolvedMtime && this.entryCache.has(file)) {\n return this.entryCache.get(file)!;\n }\n\n const raw = await this.readAll(scope, file);\n if (!raw.trim()) {\n this.entryCache.set(file, []);\n this.mtimeCache.set(file, resolvedMtime);\n return [];\n }\n\n const entries = parseEntries(raw, scope);\n this.entryCache.set(file, entries);\n this.mtimeCache.set(file, resolvedMtime);\n return entries;\n }\n\n private async getIndex(file: string, scope: MemoryScope): Promise<InvertedIndex> {\n const mtime = await this.getMtime(file);\n const cached = this.indexCache.get(file);\n if (cached && cached.mtimeMs === mtime) {\n return cached;\n }\n\n // Reuse the mtime we just fetched — loadEntries would otherwise stat again.\n const entries = await this.loadEntries(file, scope, mtime);\n const index = buildInvertedIndex(entries);\n index.mtimeMs = mtime;\n this.indexCache.set(file, index);\n return index;\n }\n\n async remember(scope: MemoryScope, entry: MemoryEntry, filePath: string): Promise<void> {\n const file = this.resolveFile(filePath, scope);\n await ensureDir(path.dirname(file));\n let existing = '';\n try { existing = await fs.readFile(file, 'utf8'); } catch { /* new file */ }\n\n const id = `mem_${Date.now()}_${randomUUID().slice(0, 8)}`;\n const meta = formatMetadata(entry);\n const line = `\\n- [${entry.ts}] ${id}${meta} ${entry.text.replace(/\\n/g, ' ')}\\n`;\n const next = existing.trim()\n ? existing.replace(/\\n+$/, '') + line\n : `# Agent Memory\\n${line}`;\n await atomicWrite(file, next);\n this.invalidateCache(file);\n }\n\n async forget(scope: MemoryScope, query: string, filePath: string): Promise<number> {\n const file = this.resolveFile(filePath, scope);\n return withFileLock(file, async () => {\n let existing: string;\n try { existing = await fs.readFile(file, 'utf8'); } catch { return 0; /* best-effort */ }\n\n const needle = query.toLowerCase();\n const idMatcher = /mem_\\d+_\\w+/;\n let removed = 0;\n const lines = existing.split('\\n').filter((line) => {\n const trimmed = line.trim();\n if (!trimmed.startsWith('- ')) return true;\n if (idMatcher.test(query)) {\n const entryIdMatch = /mem_\\d+_\\w+/.exec(trimmed);\n if (entryIdMatch && entryIdMatch[0] === query) { removed++; return false; }\n }\n if (trimmed.toLowerCase().includes(needle)) { removed++; return false; }\n return true;\n });\n if (removed > 0) {\n if (lines.length === 0 || (lines.length === 1 && !lines[0]?.trim())) {\n await atomicWrite(file, '');\n } else {\n await atomicWrite(file, lines.join('\\n'));\n }\n }\n this.invalidateCache(file);\n return removed;\n });\n }\n\n async readAll(scope: MemoryScope, filePath: string): Promise<string> {\n const file = this.resolveFile(filePath, scope);\n try { return await fs.readFile(file, 'utf8'); } catch { return ''; /* best-effort */ }\n }\n\n async list(scope: MemoryScope, filePath: string, limit?: number): Promise<MemoryEntry[]> {\n const file = this.resolveFile(filePath, scope);\n const entries = await this.loadEntries(file, scope);\n return limit ? entries.slice(0, limit) : entries;\n }\n\n async search(scope: MemoryScope, query: string, filePath: string, limit?: number): Promise<MemoryEntry[]> {\n const file = this.resolveFile(filePath, scope);\n const index = await this.getIndex(file, scope);\n return searchIndex(index, query, limit);\n }\n\n async clear(scope: MemoryScope, filePath: string): Promise<void> {\n const file = this.resolveFile(filePath, scope);\n await atomicWrite(file, '');\n this.invalidateCache(file);\n }\n\n async consolidate(scope: MemoryScope, filePath: string): Promise<number> {\n const file = this.resolveFile(filePath, scope);\n let existing: string;\n try { existing = await fs.readFile(file, 'utf8'); } catch { return 0; /* best-effort */ }\n\n const seen = new Set<string>();\n let removed = 0;\n const lines = existing.split('\\n').filter((line) => {\n const trimmed = line.trim();\n if (!trimmed.startsWith('- ')) return true;\n // Normalize: strip timestamp, ID, type|priority, tags\n const norm = trimmed\n .replace(/\\[[^\\]]+\\]/g, '')\n .replace(/\\bmem_\\d+_\\w+\\s*/, '')\n .replace(/#[\\w-]+/g, '')\n .replace(/\\s+/g, ' ')\n .trim()\n .toLowerCase();\n if (seen.has(norm)) { removed++; return false; }\n seen.add(norm);\n return true;\n });\n\n const next = lines.join('\\n');\n const backup = `${file}.bak.${Date.now()}`;\n try {\n await fs.copyFile(file, backup);\n await pruneConsolidateBackups(file);\n } catch { /* best-effort */ }\n /* v8 ignore next -- best-effort: atomicWrite failure during consolidate is non-fatal */\n try { await atomicWrite(file, next); } catch { return 0; /* best-effort */ }\n this.invalidateCache(file);\n return removed;\n }\n}\n\nasync function pruneConsolidateBackups(file: string): Promise<void> {\n const dir = path.dirname(file);\n const base = path.basename(file);\n const prefix = `${base}.bak.`;\n const backups = (await fs.readdir(dir))\n .filter((name) => name.startsWith(prefix))\n .sort()\n .reverse();\n\n await Promise.all(\n backups.slice(MAX_MEMORY_CONSOLIDATE_BACKUPS).map(async (name) => {\n try {\n await fs.unlink(path.join(dir, name));\n } catch {\n // best-effort\n }\n }),\n );\n}\n\n// ── Entry parsing ──────────────────────────────────────────────────────\n\nexport function parseEntries(raw: string, scope: MemoryScope = 'project-memory'): MemoryEntry[] {\n const entries: MemoryEntry[] = [];\n for (const line of raw.split('\\n')) {\n const entry = lineToEntry(line, scope);\n if (entry) entries.push(entry);\n }\n return entries.reverse(); // newest first\n}\n","import type {\n MemoryClearedPayload,\n MemoryConsolidatedPayload,\n MemoryEntry,\n MemoryForgottenPayload,\n MemoryRelevanceContext,\n MemoryRememberedPayload,\n MemoryScope,\n MemoryStore,\n ScoredEntry,\n} from '../types/memory.js';\nimport type { EventBus } from '../kernel/events.js';\nimport type { WstackPaths } from '../utils/wstack-paths.js';\nimport { toErrorMessage } from '../utils/error.js';\nimport { type MemoryBackend, FileMemoryBackend } from './memory-backend.js';\n\nconst MAX_BYTES_TOTAL = 32_000; // ~8K tokens\n\nexport interface MemoryStoreOptions {\n paths: WstackPaths;\n /**\n * Optional event bus — when provided, mutations emit events so plugins\n * and other subsystems can react to memory changes.\n */\n events?: EventBus | undefined;\n /**\n * Storage backend. Defaults to FileMemoryBackend when omitted.\n * Plugins can register a custom backend (graph, semantic, vector)\n * via the DI container to override storage behavior.\n */\n backend?: MemoryBackend | undefined;\n}\n\n/**\n * Three scopes:\n * project-agents → <project>/.wrongstack/AGENTS.md (committed)\n * project-memory → ~/.wrongstack/projects/<hash>/memory.md (per-project agent notes)\n * user-memory → ~/.wrongstack/memory.md (global personal memory)\n */\nexport class DefaultMemoryStore implements MemoryStore {\n private readonly files: Record<MemoryScope, string>;\n private readonly events?: EventBus | undefined;\n private traceId?: string | undefined;\n private readonly backend: MemoryBackend;\n\n /**\n * Per-scope serialization queue. `remember` / `forget` / `consolidate` /\n * `clear` are read-modify-write against a single file; without a lock,\n * two concurrent calls on the same scope can read the same baseline and\n * the later write silently drops the earlier entry. We chain each\n * mutation onto the prior promise for the same scope so they run in\n * issue order. Different scopes still proceed in parallel.\n *\n * The chain tracks only the last pending write. If a write fails, its\n * error is caught and swallowed so the chain stays alive for subsequent\n * calls. The error is stored in `writeErrors` so callers can learn about\n * it on the next read operation.\n */\n private readonly writeChain = new Map<MemoryScope, Promise<unknown>>();\n /** Last write error per scope — surfaced as warnings on the next readAll(). */\n private readonly writeErrors = new Map<MemoryScope, Error>();\n\n /**\n * When the global root is a temporary directory (opencode, CI sandboxes),\n * memory files are also mirrored to the project tree so they survive\n * session cleanup. The primary path stays in the temp root for isolation;\n * this backup ensures memory is never lost.\n */\n private readonly persistBackup: boolean;\n private readonly backupDir: string;\n /**\n * Per-scope tracked byte sizes — incremented on `remember()`, decremented on\n * `forget()`, recalculated after `consolidate()`. Eliminates the redundant\n * readAll() call that previously checked the file size after every write.\n */\n private readonly _trackedByteSizes: Partial<Record<MemoryScope, number>> = {};\n\n /** Result cache for scoreRelevant() — keyed by scope + context hash, TTL 30s. */\n private readonly _scoreCache = new Map<string, { entries: MemoryEntry[]; scored: ScoredEntry[]; expiresAt: number }>();\n\n /**\n * Per-entry cached lowercase strings — lazily allocated once and reused\n * across scoreRelevant() calls so repeated scoring of the same entries skips\n * re-lowercasing. Keyed by entry object identity; cleared (set to null) on\n * every mutation (remember/forget/consolidate/clear) via invalidateScoreCaches().\n */\n private _cachedLower: WeakMap<MemoryEntry, { textLower: string; tagsLower: string[] }> | null = null;\n\n constructor(opts: MemoryStoreOptions) {\n this.files = {\n 'project-agents': opts.paths.inProjectAgentsFile,\n 'project-memory': opts.paths.projectMemory,\n 'user-memory': opts.paths.globalMemory,\n };\n this.events = opts.events;\n this.backend = opts.backend ?? new FileMemoryBackend({ paths: opts.paths });\n\n // Detect temporary global roots: opencode, CI, test sandboxes.\n // When detected, mirror writes to the project's .wrongstack/ dir.\n const root = opts.paths.globalRoot.toLowerCase();\n this.persistBackup = /[/\\\\](tmp|temp|cache)[/\\\\]/.test(root);\n this.backupDir = this.persistBackup\n ? opts.paths.inProjectAgentsFile.replace(/AGENTS\\.md$/, 'memory-persist')\n : '';\n }\n\n /** Expose the backend for plugin introspection and advanced queries. */\n getBackend(): MemoryBackend {\n return this.backend;\n }\n\n private async runSerialized<T>(scope: MemoryScope, work: () => Promise<T>): Promise<T> {\n const prior = this.writeChain.get(scope) ?? Promise.resolve();\n // Chain: catch errors from the prior write, then run the next work item.\n const next = prior\n .catch((err) => {\n this.writeErrors.set(scope, err as Error);\n })\n .then(() => work());\n this.writeChain.set(scope, next as Promise<unknown>);\n try {\n return await next;\n } catch (err) {\n this.writeErrors.set(scope, err as Error);\n throw err;\n } finally {\n if (this.writeChain.get(scope) === next) {\n this.writeChain.delete(scope);\n }\n }\n }\n\n /**\n * Recalculate the tracked byte size for a scope by re-reading the file and\n * summing the serialized byte length of each line. Called after consolidate()\n * (which modifies the file) to keep the tracker accurate.\n */\n private async _recalcTrackedByteSize(scope: MemoryScope): Promise<number> {\n const raw = await this.backend.readAll(scope, this.files[scope]);\n let total = 0;\n for (const line of raw.split('\\n')) {\n if (line.trim()) total += Buffer.byteLength(line, 'utf8');\n }\n this._trackedByteSizes[scope] = total;\n return total;\n }\n\n async readAll(): Promise<string> {\n const parts: string[] = [];\n for (const scope of ['project-agents', 'project-memory', 'user-memory'] as MemoryScope[]) {\n const writeErr = this.writeErrors.get(scope);\n if (writeErr) {\n parts.push(`> ⚠️ Memory write error (${labelOf(scope)}): ${writeErr.message}`);\n }\n const t0 = Date.now();\n const filePath = this.files[scope];\n try {\n const body = await this.backend.readAll(scope, filePath);\n const dur = Date.now() - t0;\n this.events?.emit('storage.read', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'readAll',\n outcome: 'success',\n durationMs: dur,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n if (body.trim()) parts.push(`## ${labelOf(scope)}\\n\\n${body.trim()}`);\n } catch (err) {\n const dur = Date.now() - t0;\n this.events?.emit('storage.read', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'readAll',\n outcome: 'failure',\n durationMs: dur,\n error: toErrorMessage(err),\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n throw err;\n }\n }\n return parts.join('\\n\\n');\n }\n\n async read(scope: MemoryScope): Promise<string> {\n const t0 = Date.now();\n const filePath = this.files[scope];\n try {\n const body = await this.backend.readAll(scope, filePath);\n const dur = Date.now() - t0;\n this.events?.emit('storage.read', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'read',\n outcome: 'success',\n durationMs: dur,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n return body;\n } catch (err) {\n const dur = Date.now() - t0;\n this.events?.emit('storage.read', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'read',\n outcome: 'failure',\n durationMs: dur,\n error: toErrorMessage(err),\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n throw err;\n }\n }\n\n /**\n * List entries from a scope, newest first. Delegates to the backend\n * so graph/semantic backends can return enriched or filtered results.\n */\n async list(scope: MemoryScope = 'project-memory', limit?: number): Promise<MemoryEntry[]> {\n return this.backend.list(scope, this.files[scope], limit);\n }\n\n /**\n * Find memories related to the given text via graph traversal.\n * Falls back to content search when no graph backend is available.\n */\n async findRelated(text: string, scope: MemoryScope = 'project-memory', limit = 5): Promise<MemoryEntry[]> {\n if (this.backend.findRelated) {\n return this.backend.findRelated(scope, this.files[scope], text, limit);\n }\n return this.search(text, scope, limit);\n }\n\n async search(query: string, scope: MemoryScope = 'project-memory', limit?: number): Promise<MemoryEntry[]> {\n return this.backend.search(scope, query, this.files[scope], limit);\n }\n\n async remember(\n text: string,\n scope: MemoryScope = 'project-memory',\n metadata?: Omit<Partial<MemoryEntry>, 'scope' | 'text' | 'ts'>,\n ): Promise<void> {\n const ts = new Date().toISOString();\n return this.runSerialized(scope, async () => {\n const entry: MemoryEntry = { scope, text, ts, ...metadata };\n const filePath = this.files[scope];\n const t0 = Date.now();\n try {\n await this.backend.remember(scope, entry, filePath);\n // Invalidate the relevance caches — entries have changed.\n this.invalidateScoreCaches();\n const dur = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'remember',\n outcome: 'success',\n durationMs: dur,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n } catch (err) {\n const dur = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'remember',\n outcome: 'failure',\n durationMs: dur,\n error: toErrorMessage(err),\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n throw err;\n }\n\n // Size check — consolidate if the tracked byte size exceeds the cap.\n // Tracked size is updated incrementally; lazily initialized from the file\n // on first mutation if not yet tracked (handles the case where the store was\n // constructed but not yet mutated, or after a restart).\n let trackedSize = this._trackedByteSizes[scope];\n if (trackedSize === undefined) {\n trackedSize = await this._recalcTrackedByteSize(scope);\n }\n if (trackedSize > MAX_BYTES_TOTAL) {\n const removed = await this.backend.consolidate(scope, this.files[scope]);\n if (removed > 0) {\n this.events?.emit('memory.consolidated', {\n scope,\n removed,\n } satisfies MemoryConsolidatedPayload);\n // Recalculate after consolidation so the tracked size stays accurate.\n await this._recalcTrackedByteSize(scope);\n }\n }\n\n // Increment the tracked byte size for this scope.\n this._trackedByteSizes[scope] = (this._trackedByteSizes[scope] ?? 0) + Buffer.byteLength(JSON.stringify(entry), 'utf8');\n\n // Mirror to persistent backup when running in a temp sandbox.\n await this.mirrorBackup(scope);\n\n this.events?.emit('memory.remembered', {\n scope,\n text,\n ts,\n type: entry.type,\n tags: entry.tags,\n priority: entry.priority,\n } satisfies MemoryRememberedPayload);\n });\n }\n\n /**\n * Drop the relevance caches after a mutation. Both the per-context score\n * cache and the per-entry lowercase cache are keyed on entry objects that a\n * mutation invalidates, so they must be cleared together when entries change.\n */\n private invalidateScoreCaches(): void {\n this._scoreCache.clear();\n this._cachedLower = null;\n }\n\n /**\n * Score and rank memories by relevance to the current context.\n * Returns entries with score >= MIN_RELEVANCE_SCORE, sorted highest first.\n */\n async scoreRelevant(\n ctx: MemoryRelevanceContext,\n scope: MemoryScope = 'project-memory',\n limit = 8,\n ): Promise<ScoredEntry[]> {\n const all = await this.list(scope);\n if (all.length === 0) return [];\n\n // Build a context fingerprint for cache lookup.\n const ctxHash =\n `${scope}|${ctx.currentTask}|${(ctx.activeSkills ?? []).join(',')}|${(ctx.toolNames ?? []).join(',')}`;\n const now = Date.now();\n const TTL_MS = 30_000; // 30-second cache window\n\n // Check the TTL cache first — return cached scored results if the same entries\n // and context were scored within the last 30 seconds.\n const cached = this._scoreCache.get(ctxHash);\n if (cached && cached.expiresAt > now && cached.entries === all) {\n return cached.scored.slice(0, Math.min(limit, 15));\n }\n\n const taskWords = ctx.currentTask.toLowerCase().split(/\\s+/).filter((w) => w.length > 2);\n const skillWords = (ctx.activeSkills ?? []).flatMap((s) => s.split('-'));\n const toolWords = (ctx.toolNames ?? []).flatMap((t) => t.toLowerCase().split('_'));\n\n // Per-entry lowercase caches. Lazily allocated once and reused across\n // scoring passes — the WeakMap is keyed by entry object identity, so its\n // entries stay valid as long as the same entry objects are scored, and\n // GC away once a mutation replaces them with freshly-parsed objects. It is\n // cleared explicitly alongside the score cache on every mutation\n // (remember/forget/consolidate/clear) via invalidateScoreCaches().\n this._cachedLower ??= new WeakMap<MemoryEntry, { textLower: string; tagsLower: string[] }>();\n const lowerCache = this._cachedLower;\n\n const scored: ScoredEntry[] = [];\n\n for (const entry of all) {\n let score = 0;\n const reasons: string[] = [];\n\n // Use cached lowercase strings from the WeakMap; compute and store on first use.\n let cachedLower = lowerCache.get(entry);\n if (!cachedLower) {\n cachedLower = {\n textLower: entry.text.toLowerCase(),\n tagsLower: (entry.tags ?? []).map((t) => t.toLowerCase()),\n };\n lowerCache.set(entry, cachedLower);\n }\n const { textLower, tagsLower } = cachedLower;\n\n // Word overlap with current task (primary signal)\n let taskHits = 0;\n for (const w of taskWords) {\n if (textLower.includes(w)) { taskHits++; score += 2; }\n if (tagsLower.some((t) => t.includes(w))) { taskHits++; score += 3; }\n }\n if (taskHits > 0) reasons.push(`task match (${taskHits})`);\n\n // Skill/tool relevance\n let skillHits = 0;\n for (const w of skillWords) {\n if (w.length > 2 && (textLower.includes(w) || tagsLower.some((t) => t.includes(w)))) {\n skillHits++;\n }\n }\n score += skillHits;\n if (skillHits > 0) reasons.push(`skill match (${skillHits})`);\n\n for (const w of toolWords) {\n if (w.length > 2 && (textLower.includes(w) || tagsLower.some((t) => t.includes(w)))) {\n score += 1;\n reasons.push(`tool mention: ${w}`);\n }\n }\n\n // Priority boost\n switch (entry.priority) {\n case 'critical': score += 5; reasons.push('critical'); break;\n case 'high': score += 3; reasons.push('high priority'); break;\n case 'medium': score += 1; break;\n case 'low': score -= 2; reasons.push('low priority'); break;\n }\n\n // Type boost — decisions, conventions, anti-patterns are high-value\n switch (entry.type) {\n case 'decision': score += 2; reasons.push('decision'); break;\n case 'convention': score += 2; reasons.push('convention'); break;\n case 'anti_pattern': score += 3; reasons.push('anti-pattern'); break;\n case 'preference': score += 1; reasons.push('preference'); break;\n case 'reference': break;\n case 'fact': break;\n }\n\n // Recency boost — newer entries get +1, very old get 0\n const ageDays = (now - new Date(entry.ts).getTime()) / (1000 * 60 * 60 * 24);\n if (ageDays < 1) score += 1;\n else if (ageDays > 30) score -= 1;\n\n // Confidence penalty\n if (entry.confidence !== undefined && entry.confidence < 0.5) {\n score -= 2;\n reasons.push('low confidence');\n }\n\n // Repetition avoidance — recently accessed entries get slight penalty\n if (entry.lastAccessed) {\n const hoursSinceAccess = (now - new Date(entry.lastAccessed).getTime()) / (1000 * 60 * 60);\n if (hoursSinceAccess < 1) score -= 1;\n }\n\n if (score > 0) {\n scored.push({\n ...entry,\n score,\n matchReason: reasons.join(', ') || 'keyword match',\n });\n }\n }\n\n scored.sort((a, b) => b.score - a.score);\n\n // Filter to entries that meet the minimum relevance threshold.\n // Critical or high-priority entries always pass.\n const threshold = 2;\n const relevant = scored.filter(\n (s) => s.score >= threshold || s.priority === 'critical' || s.priority === 'high',\n );\n\n // Cache the full scored result for 30 seconds — cleared on every mutation.\n this._scoreCache.set(ctxHash, { entries: all, scored: relevant, expiresAt: now + TTL_MS });\n\n return relevant.slice(0, Math.min(limit, 15));\n }\n\n async forget(query: string, scope: MemoryScope = 'project-memory'): Promise<number> {\n return this.runSerialized(scope, async () => {\n const filePath = this.files[scope];\n const t0 = Date.now();\n let removed = 0;\n try {\n removed = await this.backend.forget(scope, query, filePath);\n // Invalidate the relevance caches — entries have changed.\n this.invalidateScoreCaches();\n const dur = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'forget',\n outcome: 'success',\n durationMs: dur,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n } catch (err) {\n const dur = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'forget',\n outcome: 'failure',\n durationMs: dur,\n error: toErrorMessage(err),\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n throw err;\n }\n if (removed > 0) {\n this.events?.emit('memory.forgotten', {\n scope,\n query,\n removed,\n } satisfies MemoryForgottenPayload);\n await this.mirrorBackup(scope);\n await this._recalcTrackedByteSize(scope);\n }\n return removed;\n });\n }\n\n async consolidate(scope: MemoryScope): Promise<void> {\n return this.runSerialized(scope, async () => {\n const filePath = this.files[scope];\n const t0 = Date.now();\n let removed = 0;\n try {\n removed = await this.backend.consolidate(scope, filePath);\n // Invalidate the relevance caches — entries have changed.\n this.invalidateScoreCaches();\n const dur = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'consolidate',\n outcome: 'success',\n durationMs: dur,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n } catch (err) {\n const dur = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'consolidate',\n outcome: 'failure',\n durationMs: dur,\n error: toErrorMessage(err),\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n throw err;\n }\n if (removed > 0) {\n this.events?.emit('memory.consolidated', {\n scope,\n removed,\n } satisfies MemoryConsolidatedPayload);\n await this.mirrorBackup(scope);\n await this._recalcTrackedByteSize(scope);\n }\n });\n }\n\n async clear(scope?: MemoryScope): Promise<void> {\n if (scope) {\n await this.runSerialized(scope, async () => {\n const filePath = this.files[scope];\n const t0 = Date.now();\n try {\n await this.backend.clear(scope, filePath);\n // Invalidate the relevance caches — entries have changed.\n this.invalidateScoreCaches();\n const dur = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'clear',\n outcome: 'success',\n durationMs: dur,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n } catch (err) {\n const dur = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'clear',\n outcome: 'failure',\n durationMs: dur,\n error: toErrorMessage(err),\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n throw err;\n }\n this.events?.emit('memory.cleared', { scope } satisfies MemoryClearedPayload);\n await this.mirrorBackup(scope);\n this._trackedByteSizes[scope] = 0;\n });\n return;\n }\n await Promise.all(\n (['project-agents', 'project-memory', 'user-memory'] as MemoryScope[]).map(async (s) =>\n this.runSerialized(s, async () => {\n const filePath = this.files[s];\n const t0 = Date.now();\n try {\n await this.backend.clear(s, filePath);\n const dur = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'clear',\n outcome: 'success',\n durationMs: dur,\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n } catch (err) {\n const dur = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: '~memory~',\n store: 'memory',\n filePath,\n operation: 'clear',\n outcome: 'failure',\n durationMs: dur,\n error: toErrorMessage(err),\n ...(this.traceId !== undefined && { traceId: this.traceId }),\n });\n throw err;\n }\n this.events?.emit('memory.cleared', { scope: s } satisfies MemoryClearedPayload);\n await this.mirrorBackup(s);\n }),\n ),\n );\n // Every scope was just cleared — drop the relevance caches too.\n this.invalidateScoreCaches();\n }\n\n /**\n * Return a new MemoryStore proxy that carries `traceId` on every storage\n * event. The original store is left unchanged — callers that need a\n * trace-decorated view (e.g. session-run tools) receive the proxy while\n * the singleton remains trace-free for boot-time use.\n *\n * The proxy implements the full `MemoryStore` interface; all other\n * properties (backend, etc.) are delegated to the original store.\n */\n withTraceId(traceId: string): MemoryStore {\n // Mutate the singleton's traceId so that all subsequent I/O (including\n // calls from tools that captured the original store reference) emits\n // storage events with the correct session trace ID.\n this.traceId = traceId;\n return this;\n }\n private async mirrorBackup(scope: MemoryScope): Promise<void> {\n if (!this.persistBackup || scope === 'project-agents') return;\n try {\n const content = await this.backend.readAll(scope, this.files[scope]);\n const { writeFile, mkdir } = await import('node:fs/promises');\n await mkdir(this.backupDir, { recursive: true });\n await writeFile(`${this.backupDir}/${scope}.md`, content, 'utf8');\n } catch {\n // best-effort\n }\n }\n}\n\nfunction labelOf(scope: MemoryScope): string {\n switch (scope) {\n case 'project-agents':\n return 'Project AGENTS.md';\n case 'project-memory':\n return 'Project memory';\n case 'user-memory':\n return 'User memory';\n }\n}\n","import * as fs from 'node:fs/promises';\nimport type { MemoryEntry, MemoryScope } from '../types/memory.js';\nimport { type FileMemoryBackendOptions, FileMemoryBackend } from './memory-backend.js';\nimport type { MemoryBackend } from './memory-backend.js';\n\n// ── Graph node and edge types ──────────────────────────────────────────\n\ninterface GraphNode {\n id: string;\n entry: MemoryEntry;\n firstSeen: string;\n count: number;\n /** Extracted metadata for fast lookup. */\n type?: MemoryEntry['type'] | undefined;\n tags?: string[] | undefined;\n priority?: MemoryEntry['priority'] | undefined;\n}\n\ninterface GraphEdge {\n from: string;\n to: string;\n /** Why these nodes are related. */\n relation: 'co_occurring' | 'similar' | 'same_turn' | 'explicit';\n weight: number;\n ts: string;\n}\n\n// ── Backend ────────────────────────────────────────────────────────────\n\nexport interface GraphMemoryBackendOptions extends FileMemoryBackendOptions {\n /**\n * Path to the graph metadata file (edges + node metadata).\n * Defaults to `<projectDir>/memory-graph.json`.\n */\n graphPath?: string | undefined;\n}\n\n/**\n * Graph-based memory backend that tracks relationships between entries.\n * Builds on top of FileMemoryBackend — entries are still persisted as\n * markdown bullets, but the graph layer adds:\n *\n * - Co-occurrence edges (entries from the same remember() batch)\n * - Content similarity edges (simple Jaccard on word overlap)\n * - Turn-based edges (entries created in the same LLM turn)\n * - Graph traversal queries (find related memories)\n *\n * The graph metadata persists to `<projectDir>/memory-graph.json`.\n */\nexport class GraphMemoryBackend implements MemoryBackend {\n readonly kind = 'graph';\n\n private readonly file: FileMemoryBackend;\n private readonly graphFile: string;\n\n // In-memory graph state — lazily loaded, saved on mutation.\n private nodes = new Map<string, GraphNode>();\n private edges: GraphEdge[] = [];\n private loadedScope: MemoryScope | null = null;\n private loaded = false;\n\n /**\n * Inverted index for O(1) term → node lookup during search.\n * Built incrementally on remember/forget, rebuilt on loadGraph if absent.\n * Maps lowercase term (min 3 chars) → Set of node IDs containing that term.\n */\n private invertedIndex = new Map<string, Set<string>>();\n\n /** Minimum term length to index — avoids noise from 1-2 char fragments. */\n private static readonly MIN_TERM_LEN = 3;\n\n /**\n * Promise that resolves when the current in-flight _saveGraph completes.\n * Tests call flush() to await this before deleting the backend or its temp dir.\n * Each save operation chains onto the previous one so concurrent saves are serialised.\n */\n private _saveDone: Promise<void> = Promise.resolve();\n\n constructor(opts: GraphMemoryBackendOptions) {\n this.file = new FileMemoryBackend({ paths: opts.paths });\n this.graphFile = opts.graphPath ?? `${opts.paths.projectDir}/memory-graph.json`;\n }\n\n // ── Backend interface ──────────────────────────────────────────────\n\n async remember(scope: MemoryScope, entry: MemoryEntry, filePath: string): Promise<void> {\n await this.file.remember(scope, entry, filePath);\n await this.loadGraph(scope);\n\n const nodeId = this.nodeId(entry);\n const existing = this.nodes.get(nodeId);\n if (existing) {\n existing.count++;\n existing.entry = entry;\n existing.type = entry.type;\n existing.tags = entry.tags;\n existing.priority = entry.priority;\n // Update inverted index for the modified node's text and tags\n this.updateNodeIndex(nodeId, entry);\n } else {\n this.nodes.set(nodeId, {\n id: nodeId,\n entry,\n firstSeen: entry.ts,\n count: 1,\n type: entry.type,\n tags: entry.tags,\n priority: entry.priority,\n });\n\n // Index the new node in the inverted index\n this.indexNode(nodeId, entry);\n\n // Create similarity edges — but only against the last SIMILARITY_WINDOW most\n // recent nodes instead of the full in-memory set. This converts O(N²) on\n // every remember() into O(K) where K is a small constant (100), making\n // remember() O(1) amortized regardless of how many entries are stored.\n const SIMILARITY_WINDOW = 100;\n const recentNodes = [...this.nodes.values()].slice(-SIMILARITY_WINDOW);\n for (const other of recentNodes) {\n if (other.id === nodeId) continue;\n const sim = wordOverlap(entry.text, other.entry.text);\n const tagSim = sharedTags(entry.tags ?? [], other.tags ?? []);\n const weight = Math.max(sim, tagSim * 0.5);\n if (weight > 0.15) {\n this.edges.push({\n from: nodeId,\n to: other.id,\n relation: sim >= tagSim ? 'similar' : 'same_turn',\n weight,\n ts: entry.ts,\n });\n }\n }\n }\n\n // Await the graph save to ensure flush() sees the file on disk before\n // cleanup. Unlike memory-consolidator (LLM call, 15s), this is a fast fs operation\n // and the caller's event loop is already freed by not awaiting file.remember().\n this._saveDone = this._saveGraph(scope);\n await this._saveDone;\n }\n\n async forget(scope: MemoryScope, query: string, filePath: string): Promise<number> {\n const removed = await this.file.forget(scope, query, filePath);\n if (removed > 0) {\n await this.loadGraph(scope);\n // Remove nodes whose entry text matches the query\n const n = query.toLowerCase();\n const toRemove: string[] = [];\n for (const [id, node] of this.nodes) {\n if (node.entry.text.toLowerCase().includes(n)) {\n toRemove.push(id);\n }\n }\n for (const id of toRemove) {\n // Remove from inverted index before deleting the node\n this.removeNodeFromIndex(id, this.nodes.get(id)?.entry);\n this.nodes.delete(id);\n }\n this.edges = this.edges.filter((e) => !toRemove.includes(e.from) && !toRemove.includes(e.to));\n this._saveDone = this._saveGraph(scope);\n await this._saveDone;\n }\n return removed;\n }\n\n async readAll(scope: MemoryScope, filePath: string): Promise<string> {\n return this.file.readAll(scope, filePath);\n }\n\n async list(scope: MemoryScope, filePath: string, limit?: number): Promise<MemoryEntry[]> {\n await this.loadGraph(scope);\n // Merge: file entries are canonical, graph adds metadata and dedup\n const fileEntries = await this.file.list(scope, filePath);\n const nodeMap = new Map(this.nodes.entries());\n\n // Enrich file entries with graph metadata\n const enriched = fileEntries.map((fe) => {\n const nodeId = this.nodeId(fe);\n const node = nodeMap.get(nodeId);\n if (node) {\n return {\n ...fe,\n type: node.type ?? fe.type,\n tags: node.tags ?? fe.tags,\n priority: node.priority ?? fe.priority,\n };\n }\n return fe;\n });\n\n // Add graph-only nodes not in file (shouldn't happen normally, but safety)\n const fileIds = new Set(fileEntries.map((e) => this.nodeId(e)));\n for (const [id, node] of this.nodes) {\n if (!fileIds.has(id)) {\n enriched.push(node.entry);\n }\n }\n\n enriched.sort((a, b) => b.ts.localeCompare(a.ts));\n return limit ? enriched.slice(0, limit) : enriched;\n }\n\n async search(scope: MemoryScope, query: string, _filePath: string, limit?: number): Promise<MemoryEntry[]> {\n await this.loadGraph(scope);\n const needle = query.toLowerCase().split(/\\s+/).filter((t) => t.length >= GraphMemoryBackend.MIN_TERM_LEN);\n\n // Use inverted index to find candidate nodes — O(K * avg_results) instead of O(N)\n const candidates = new Map<string, number>();\n for (const term of needle) {\n const nodeIds = this.invertedIndex.get(term);\n if (!nodeIds) continue;\n for (const nodeId of nodeIds) {\n const node = this.nodes.get(nodeId);\n if (!node || node.entry.scope !== scope) continue;\n // Count how many terms matched this node\n candidates.set(nodeId, (candidates.get(nodeId) ?? 0) + 1);\n }\n }\n\n // Also include high-priority entries even without lexical matches (priority boost > 0)\n // This preserves the original behavior where priority/count could surface entries\n // that don't match any query terms.\n for (const [nodeId, node] of this.nodes) {\n if (node.entry.scope !== scope) continue;\n if (candidates.has(nodeId)) continue; // Already in candidates\n // Include if priority boost > 0 (critical=3, high=2)\n if (node.priority === 'critical' || node.priority === 'high') {\n candidates.set(nodeId, 0); // 0 lexical matches but priority boost applies\n }\n }\n\n // Score candidates: text match (1pt/term), tag match (2pts/term), priority, count\n const scored: { entry: MemoryEntry; score: number }[] = [];\n for (const [nodeId] of candidates) {\n const node = this.nodes.get(nodeId)!;\n let score = 0;\n // Text match score: 1pt per matching term\n score += (candidates.get(nodeId) ?? 0) * 1;\n // Tag match score: 2pts per term that appears in any tag\n for (const term of needle) {\n if (node.entry.tags?.some((t) => t.toLowerCase().includes(term))) score += 2;\n }\n if (node.priority === 'critical') score += 3;\n else if (node.priority === 'high') score += 2;\n score += node.count * 0.5;\n scored.push({ entry: node.entry, score });\n }\n\n scored.sort((a, b) => b.score - a.score);\n const matched = scored.map((s) => s.entry);\n return limit ? matched.slice(0, limit) : matched;\n }\n\n async clear(scope: MemoryScope, filePath: string): Promise<void> {\n await this.file.clear(scope, filePath);\n this.nodes.clear();\n this.edges = [];\n this.invertedIndex = new Map();\n this.loadedScope = scope;\n this.loaded = true;\n // Write empty graph\n try { await fs.unlink(this.graphFile); } catch { /* ok */ }\n }\n\n async consolidate(scope: MemoryScope, filePath: string): Promise<number> {\n return this.file.consolidate(scope, filePath);\n }\n\n // ── Graph-specific queries ─────────────────────────────────────────\n\n /**\n * Find memories related to the given entry, ordered by edge weight.\n */\n async findRelated(scope: MemoryScope, _filePath: string, entryText: string, limit = 5): Promise<MemoryEntry[]> {\n await this.loadGraph(scope);\n const targetId = this.nodeId({ scope, text: entryText, ts: '' });\n const related = this.edges\n .filter((e) => e.from === targetId || e.to === targetId)\n .sort((a, b) => b.weight - a.weight)\n .slice(0, limit);\n\n const result: MemoryEntry[] = [];\n for (const edge of related) {\n const otherId = edge.from === targetId ? edge.to : edge.from;\n const node = this.nodes.get(otherId);\n if (node) result.push(node.entry);\n }\n return result;\n }\n\n /**\n * Get all edges for visualization or traversal.\n */\n getGraph(): { nodes: GraphNode[]; edges: GraphEdge[] } {\n return {\n nodes: [...this.nodes.values()],\n edges: [...this.edges],\n };\n }\n\n // ── Persistence ────────────────────────────────────────────────────\n\n private nodeId(entry: MemoryEntry): string {\n // Stable ID from scope + normalized text\n const norm = entry.text.toLowerCase().trim().replace(/\\s+/g, ' ');\n return `${entry.scope ?? 'mem'}::${simpleHash(norm)}`;\n }\n\n private async loadGraph(scope: MemoryScope): Promise<void> {\n if (this.loaded && this.loadedScope === scope) return;\n try {\n const raw = await fs.readFile(this.graphFile, 'utf8');\n const data: { nodes: Array<[string, GraphNode]>; edges: GraphEdge[] } = JSON.parse(raw);\n this.nodes = new Map(data.nodes);\n this.edges = data.edges;\n } catch {\n this.nodes = new Map();\n this.edges = [];\n }\n // Build inverted index from loaded nodes\n this.buildInvertedIndex();\n this.loadedScope = scope;\n this.loaded = true;\n }\n\n /** Fire-and-forget graph persistence. Named _saveGraph to signal it must not be awaited. */\n private async _saveGraph(scope: MemoryScope): Promise<void> {\n this.loadedScope = scope;\n this.loaded = true;\n try {\n const data = {\n nodes: [...this.nodes.entries()],\n edges: this.edges,\n };\n const dir = this.graphFile.substring(0, this.graphFile.lastIndexOf('/'));\n await fs.mkdir(dir, { recursive: true });\n // Atomic write via temp file\n const tmp = `${this.graphFile}.tmp`;\n await fs.writeFile(tmp, JSON.stringify(data));\n await fs.rename(tmp, this.graphFile);\n } catch {\n // best-effort — graph is an enhancement, not critical\n }\n }\n\n /**\n * Wait for all in-flight _saveGraph operations to complete.\n * Call this before deleting the backend or its temp directory.\n */\n async flush(): Promise<void> {\n await this._saveDone;\n }\n\n // ── Inverted Index Helpers ───────────────────────────────────────────\n\n /**\n * Build the inverted index from all currently loaded nodes.\n * Called on loadGraph() to reconstruct the index after loading from disk.\n */\n private buildInvertedIndex(): void {\n this.invertedIndex = new Map();\n for (const [nodeId, node] of this.nodes) {\n for (const term of this.extractTerms(node.entry)) {\n let nodeIds = this.invertedIndex.get(term);\n if (!nodeIds) {\n nodeIds = new Set();\n this.invertedIndex.set(term, nodeIds);\n }\n nodeIds.add(nodeId);\n }\n }\n }\n\n /**\n * Index a node in the inverted index. Adds the node's ID to all term entries.\n */\n private indexNode(nodeId: string, entry: MemoryEntry): void {\n for (const term of this.extractTerms(entry)) {\n let nodeIds = this.invertedIndex.get(term);\n if (!nodeIds) {\n nodeIds = new Set();\n this.invertedIndex.set(term, nodeIds);\n }\n nodeIds.add(nodeId);\n }\n }\n\n /**\n * Remove a node's terms from the inverted index before deleting it.\n * Used in forget() and when updating existing nodes.\n */\n private removeNodeFromIndex(nodeId: string, entry?: MemoryEntry): void {\n if (!entry) return;\n for (const term of this.extractTerms(entry)) {\n const nodeIds = this.invertedIndex.get(term);\n if (nodeIds) {\n nodeIds.delete(nodeId);\n if (nodeIds.size === 0) {\n this.invertedIndex.delete(term);\n }\n }\n }\n }\n\n /**\n * Update an existing node's entries in the inverted index.\n * Removes old terms and adds new ones.\n */\n private updateNodeIndex(nodeId: string, entry: MemoryEntry): void {\n // Remove old entries for this node\n const existing = this.nodes.get(nodeId);\n if (existing) {\n this.removeNodeFromIndex(nodeId, existing.entry);\n }\n // Add new entries\n this.indexNode(nodeId, entry);\n }\n\n /**\n * Extract searchable terms from a memory entry.\n * Returns lowercase words from text (min length) and full tag strings.\n */\n private extractTerms(entry: MemoryEntry): string[] {\n const terms: string[] = [];\n // Extract words from text (only terms >= MIN_TERM_LEN to avoid noise)\n const words = entry.text.toLowerCase().split(/\\s+/);\n for (const word of words) {\n if (word.length >= GraphMemoryBackend.MIN_TERM_LEN) {\n terms.push(word);\n }\n }\n // Index full tags as complete strings (not individual words)\n if (entry.tags) {\n for (const tag of entry.tags) {\n const lower = tag.toLowerCase();\n if (lower.length >= GraphMemoryBackend.MIN_TERM_LEN && !terms.includes(lower)) {\n terms.push(lower);\n }\n }\n }\n return terms;\n }\n}\n\n// ── Helpers ────────────────────────────────────────────────────────────\n\n/** Jaccard-style word overlap between two strings. 0.0 = no overlap, 1.0 = identical. */\nfunction wordOverlap(a: string, b: string): number {\n const wordsA = new Set(a.toLowerCase().split(/\\s+/).filter((w) => w.length > 2));\n const wordsB = new Set(b.toLowerCase().split(/\\s+/).filter((w) => w.length > 2));\n if (wordsA.size === 0 || wordsB.size === 0) return 0;\n let intersection = 0;\n for (const w of wordsA) {\n if (wordsB.has(w)) intersection++;\n }\n return intersection / Math.max(wordsA.size, wordsB.size);\n}\n\n/** Tag overlap ratio — how many tags two nodes share. */\nfunction sharedTags(a: string[], b: string[]): number {\n if (a.length === 0 || b.length === 0) return 0;\n const setB = new Set(b);\n let shared = 0;\n for (const t of a) if (setB.has(t)) shared++;\n return shared / Math.max(a.length, b.length);\n}\n\n/** Fast non-crypto hash for stable node IDs. */\nfunction simpleHash(s: string): string {\n let h = 0;\n for (let i = 0; i < s.length; i++) {\n h = ((h << 5) - h + s.charCodeAt(i)) | 0;\n }\n return Math.abs(h).toString(36);\n}\n","import { readFileSync, statSync } from 'node:fs';\nimport * as path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nexport function readBundledInstructionText(relativePath: string): string {\n for (const root of instructionRootCandidates()) {\n try {\n return readFileSync(path.join(root, relativePath), 'utf8').trimEnd();\n } catch {\n // try next candidate\n }\n }\n return '';\n}\n\nexport function renderInstructionTemplate(\n template: string,\n values: Record<string, string>,\n): string {\n return template.replace(/\\{\\{\\s*([a-zA-Z0-9_.-]+)\\s*\\}\\}/g, (match, key: string) =>\n Object.prototype.hasOwnProperty.call(values, key) ? values[key] ?? '' : match,\n );\n}\n\nfunction instructionRootCandidates(): string[] {\n const here = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(here, '../../instructions'),\n path.resolve(here, '../instructions'),\n path.resolve(here, 'instructions'),\n ];\n return candidates.sort((a, b) => Number(!isDirectory(a)) - Number(!isDirectory(b)));\n}\n\nfunction isDirectory(candidate: string): boolean {\n try {\n return statSync(candidate).isDirectory();\n } catch {\n return false;\n }\n}\n","import type { RunResult } from '../core/agent-types.js';\nimport type { Context } from '../core/context.js';\nimport type { AfterRunHook, AgentExtension } from '../extension/extension-points.js';\nimport type { MemoryEntry, MemoryStore } from '../types/memory.js';\nimport type { Provider } from '../types/provider.js';\nimport {\n readBundledInstructionText,\n renderInstructionTemplate,\n} from '../utils/instruction-file.js';\n\n// ── Types ───────────────────────────────────────────────────────────────\n\nexport interface ConsolidationOp {\n action: 'add' | 'edit' | 'delete';\n /** For add: the fact to remember. For edit: the new text replacing the old. */\n text?: string | undefined;\n /** For edit/delete: the query to match existing entries. */\n query?: string | undefined;\n /** Memory type for categorization. */\n type?: string | undefined;\n /** Tags for grouping. */\n tags?: string[] | undefined;\n /** Priority level. */\n priority?: string | undefined;\n}\n\ninterface ConsolidationResponse {\n operations: ConsolidationOp[];\n summary?: string | undefined;\n}\n\nexport interface MemoryConsolidatorOptions {\n memoryStore: MemoryStore;\n /**\n * Provider used for the consolidation LLM call. Uses the session's\n * provider by default.\n */\n provider?: Provider | undefined;\n /**\n * Model override for the consolidation call. Uses the session's model\n * by default. A smaller/faster model is recommended (e.g. haiku, flash).\n */\n model?: string | undefined;\n /**\n * Minimum session iterations before consolidation fires.\n * Sessions shorter than this are skipped (default 2).\n */\n minIterations?: number | undefined;\n /**\n * Maximum memory entries to include in the prompt as context.\n */\n maxExistingEntries?: number | undefined;\n}\n\n// ── Prompt ──────────────────────────────────────────────────────────────\n\nfunction buildConsolidationPrompt(\n finalText: string,\n iterations: number,\n existingEntries: MemoryEntry[],\n): string {\n const existingBlock =\n existingEntries.length > 0\n ? `\\n\\nExisting memory entries:\\n${existingEntries\n .map((e) => `- [${e.ts.slice(0, 10)}] ${e.text}`)\n .join('\\n')}`\n : '';\n\n return renderInstructionTemplate(readBundledInstructionText('llm/memory-consolidator.md'), {\n iterations: String(iterations),\n summary: finalText.slice(0, 3000),\n existingEntries: existingBlock,\n });\n}\n\n// ── Consolidator ────────────────────────────────────────────────────────\n\nexport class SessionMemoryConsolidator implements AgentExtension {\n name = 'session-memory-consolidator';\n owner = 'core';\n\n private readonly memoryStore: MemoryStore;\n private readonly provider?: Provider | undefined;\n private readonly model?: string | undefined;\n private readonly minIterations: number;\n private readonly maxExistingEntries: number;\n\n constructor(opts: MemoryConsolidatorOptions) {\n this.memoryStore = opts.memoryStore;\n this.provider = opts.provider;\n this.model = opts.model;\n this.minIterations = opts.minIterations ?? 2;\n this.maxExistingEntries = opts.maxExistingEntries ?? 15;\n }\n\n afterRun: AfterRunHook = (ctx: Context, result: RunResult) => {\n // Only consolidate successful sessions with meaningful output\n if (result.status !== 'done') return;\n if (!result.finalText || result.finalText.trim().length < 20) return;\n if (result.iterations < this.minIterations) return;\n\n const provider = this.provider ?? ctx.provider;\n if (!provider?.complete) return;\n\n // Capture narrowed values for the fire-and-forget closure.\n const _finalText: string = result.finalText;\n const _iterations: number = result.iterations;\n const _model: string | undefined = this.model ?? ctx.model;\n\n // Fire-and-forget: consolidation is best-effort and should never block\n // session teardown (the LLM call can take up to 15s). The catch block\n // below prevents unhandled rejections.\n void (async () => {\n try {\n // Load existing memory for dedup context\n const existingEntries = await this.memoryStore.list('project-memory', this.maxExistingEntries);\n const prompt = buildConsolidationPrompt(\n _finalText,\n _iterations,\n existingEntries,\n );\n\n // Call the LLM with a focused, one-shot prompt\n const signal = AbortSignal.timeout(15_000);\n const response = await provider.complete(\n {\n model: _model,\n system: [{ type: 'text', text: prompt }],\n messages: [\n { role: 'user', content: 'Review the session and return memory operations as JSON.' },\n ],\n maxTokens: 500,\n },\n { signal },\n );\n\n const text = response.content\n .filter((b): b is { type: 'text'; text: string } => b.type === 'text')\n .map((b) => b.text)\n .join('')\n .trim();\n if (!text) return;\n\n // Extract JSON from possible markdown wrapper\n const jsonMatch = text.match(/\\{[\\s\\S]*\\}/);\n if (!jsonMatch) return;\n\n const parsed: ConsolidationResponse = JSON.parse(jsonMatch[0]);\n if (!Array.isArray(parsed.operations) || parsed.operations.length === 0) return;\n\n // Apply operations\n let added = 0;\n let edited = 0;\n let deleted = 0;\n\n for (const op of parsed.operations) {\n switch (op.action) {\n case 'add': {\n if (op.text?.trim()) {\n await this.memoryStore.remember(op.text.trim(), undefined, {\n type: op.type as MemoryEntry['type'],\n tags: op.tags,\n priority: op.priority as MemoryEntry['priority'],\n });\n added++;\n }\n break;\n }\n case 'edit': {\n if (op.query && op.text?.trim()) {\n await this.memoryStore.forget(op.query);\n await this.memoryStore.remember(op.text.trim(), undefined, {\n type: op.type as MemoryEntry['type'],\n tags: op.tags,\n priority: op.priority as MemoryEntry['priority'],\n });\n edited++;\n }\n break;\n }\n case 'delete': {\n if (op.query) {\n const n = await this.memoryStore.forget(op.query);\n deleted += n;\n }\n break;\n }\n }\n }\n\n if (added > 0 || edited > 0 || deleted > 0) {\n const parts: string[] = [];\n if (added) parts.push(`${added} added`);\n if (edited) parts.push(`${edited} edited`);\n if (deleted) parts.push(`${deleted} deleted`);\n // Log to stderr so it surfaces in the terminal\n process.stderr.write(`[memory] Session consolidation: ${parts.join(', ')}\\n`);\n }\n } catch {\n // Silent — memory consolidation is best-effort, never blocks session cleanup\n }\n })();\n };\n}\n","import type { Config, ConfigStore } from '../types/config.js';\nimport { ConfigError, ERROR_CODES } from '../types/errors.js';\nimport { toErrorMessage } from '../utils/error.js';\n\n\n/**\n * Strip fields that originated from environment variables so they are never\n * persisted back to disk. This prevents an env-sourced secret (e.g.\n * WRONGSTACK_API_KEY) from being accidentally written to ~/.wrongstack/config.json.\n */\nfunction stripEphemeralFields(cfg: Partial<Config>): Partial<Config> {\n const env = (cfg as Partial<Config & { _envSource?: Set<string> | undefined}>)._envSource;\n if (!env?.size) return cfg;\n const out: Partial<Config> = { ...cfg };\n for (const field of env) {\n delete (out as Record<string, unknown>)[field];\n }\n delete (out as Record<string, unknown>)._envSource;\n return out;\n}\n\n/**\n * Reference implementation of `ConfigStore`. Stores a single frozen Config\n * and notifies watchers synchronously on every update. Updates use a deep\n * clone so callers can mutate their `partial` argument freely without\n * tainting state.\n *\n * For the CLI: instantiate once at boot, pass the store (not the Config)\n * to subsystems that care about runtime changes (provider switching,\n * extension reload).\n */\nexport class DefaultConfigStore implements ConfigStore {\n private current: Readonly<Config>;\n private watchers = new Set<(next: Readonly<Config>, prev: Readonly<Config>) => void>();\n\n constructor(initial: Config) {\n this.current = deepFreeze(structuredClone(initial));\n }\n\n get(): Readonly<Config> {\n return this.current;\n }\n\n getSection<K extends keyof Config>(key: K): Readonly<Config[K]> {\n return this.current[key] as Readonly<Config[K]>;\n }\n\n getExtension(pluginName: string): Readonly<Record<string, unknown>> {\n const ext = this.current.extensions?.[pluginName];\n return ext ? (ext as Readonly<Record<string, unknown>>) : FROZEN_EMPTY;\n }\n\n update(partial: Partial<Config>): Readonly<Config> {\n // Strip env-sourced fields before persisting to prevent secrets leaking\n // from in-memory env-derived config values into the on-disk config file.\n const scrubbed = stripEphemeralFields(partial);\n // Shallow merge — top-level fields replace, nested objects do too unless\n // the caller passes a fully-formed sub-object. That matches the JSON\n // config user mental model (replace `tools.maxIterations` by passing\n // the whole `tools` block, or by patching `extensions.<name>`).\n const next = deepFreeze(structuredClone({ ...this.current, ...scrubbed })) as Readonly<Config>;\n\n if (next.version !== 1) {\n throw new ConfigError({\n message: `ConfigStore.update: version must remain 1, got ${String(next.version)}`,\n code: ERROR_CODES.CONFIG_INVALID,\n context: { field: 'version', actual: next.version },\n });\n }\n\n const prev = this.current;\n this.current = next;\n // Notify watchers AFTER mutating `current` so re-entrant watcher reads\n // see the new state. Watcher exceptions are caught individually so one\n // misbehaving subscriber can't block the others.\n for (const w of this.watchers) {\n try {\n w(next, prev);\n } catch (err) {\n // A plugin watcher that crashes on /model switch or similar would\n // otherwise leave the system in a quietly-inconsistent state. We\n // still don't propagate (one bad subscriber must not break the\n // others), but we surface the error so it's discoverable.\n console.error(JSON.stringify({\n level: 'error',\n event: 'config_store.watcher_threw',\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n }\n }\n return next;\n }\n\n watch(cb: (next: Readonly<Config>, prev: Readonly<Config>) => void): () => void {\n this.watchers.add(cb);\n return () => this.watchers.delete(cb);\n }\n}\n\nconst FROZEN_EMPTY: Readonly<Record<string, unknown>> = Object.freeze({});\n\nfunction deepFreeze<T>(obj: T): T {\n /* v8 ignore start -- defensive: callers (and the recursion guard below) only pass unfrozen objects */\n if (obj === null || typeof obj !== 'object') return obj;\n if (Object.isFrozen(obj)) return obj;\n /* v8 ignore stop */\n for (const key of Object.keys(obj as object)) {\n const v = (obj as Record<string, unknown>)[key];\n if (v !== null && typeof v === 'object' && !Object.isFrozen(v)) {\n deepFreeze(v);\n }\n }\n return Object.freeze(obj);\n}\n","import { createCipheriv, createDecipheriv, randomBytes, scryptSync } from 'node:crypto';\nimport * as fs from 'node:fs';\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { Logger } from '../types/logger.js';\nimport type { RotatableSecretVault, SecretVault } from '../types/secret-vault.js';\nimport { ConfigError, ERROR_CODES } from '../types/errors.js';\nimport {\n ENCRYPTED_PREFIX_PATTERN,\n encryptedPrefixForVersion,\n} from '../types/secret-vault.js';\nimport { atomicWrite } from '../utils/atomic-write.js';\n\nexport interface SecretVaultOptions {\n /** Absolute path to the key file. Created with mode 0o600 if missing. */\n keyFile: string;\n}\n\nconst KEY_BYTES = 32;\nconst IV_BYTES = 12;\nconst TAG_BYTES = 16;\nconst ALGO = 'aes-256-gcm';\n// Desired file mode for the key file on POSIX systems.\nconst KEY_FILE_MODE = 0o600;\n\n/**\n * Key file format v2+: 4-byte magic + 1-byte version + 32-byte key = 37 bytes.\n * The magic header distinguishes versioned key files from legacy 32-byte raw keys.\n */\nconst KEY_FILE_MAGIC = Buffer.from('WSKV', 'ascii');\nconst VERSIONED_KEY_FILE_SIZE = KEY_FILE_MAGIC.length + 1 + KEY_BYTES; // 37 bytes\n\n// ── WS-03: opt-in passphrase-wrapped key file (KEK) ─────────────────────────\n//\n// When WRONGSTACK_VAULT_PASSPHRASE is set, the data key is NOT stored in the\n// clear. Instead the key file holds the data key encrypted (AES-256-GCM) under\n// a key-encryption-key (KEK) derived from the passphrase with scrypt. This adds\n// at-rest protection beyond the file's 0o600 perms: an attacker who copies\n// ~/.wrongstack/.key + config.json off the disk still cannot decrypt without the\n// passphrase. When the env var is unset, behavior is byte-for-byte identical to\n// before (legacy raw / versioned formats) — this is purely additive and opt-in.\n//\n// Wrapped format v3: magic 'WSKW' (4) + keyVersion (1) + salt (16) + iv (12) +\n// tag (16) + ciphertext (32) = 81 bytes.\nconst KEK_MAGIC = Buffer.from('WSKW', 'ascii');\nconst KEK_SALT_BYTES = 16;\nconst WRAPPED_KEY_FILE_SIZE =\n KEK_MAGIC.length + 1 + KEK_SALT_BYTES + IV_BYTES + TAG_BYTES + KEY_BYTES; // 81 bytes\n// scrypt cost parameters. N=2^15 keeps derivation ~50-100ms — strong against\n// offline brute force while imperceptible for a one-time-per-process unlock.\nconst SCRYPT_N = 1 << 15;\nconst SCRYPT_R = 8;\nconst SCRYPT_P = 1;\nconst SCRYPT_MAXMEM = 64 * 1024 * 1024; // headroom above N*r*128 so derivation never throws\n\n/** Read the optional vault passphrase from the environment. Empty = unset. */\nfunction getVaultPassphrase(): string | undefined {\n const v = process.env['WRONGSTACK_VAULT_PASSPHRASE'];\n return v && v.length > 0 ? v : undefined;\n}\n\n/** True if `buf` is a passphrase-wrapped (v3) key file. */\nfunction isWrappedKeyFile(buf: Buffer): boolean {\n return buf.length === WRAPPED_KEY_FILE_SIZE && buf.subarray(0, KEK_MAGIC.length).equals(KEK_MAGIC);\n}\n\n/** Derive the 32-byte KEK from a passphrase + salt via scrypt. */\nfunction deriveKEK(passphrase: string, salt: Buffer): Buffer {\n return scryptSync(passphrase, salt, KEY_BYTES, {\n N: SCRYPT_N,\n r: SCRYPT_R,\n p: SCRYPT_P,\n maxmem: SCRYPT_MAXMEM,\n });\n}\n\n/** Serialize a data key into the wrapped (v3) on-disk format under `passphrase`. */\nfunction wrapDataKey(dataKey: Buffer, keyVersion: number, passphrase: string): Buffer {\n const salt = randomBytes(KEK_SALT_BYTES);\n const iv = randomBytes(IV_BYTES);\n const kek = deriveKEK(passphrase, salt);\n const cipher = createCipheriv(ALGO, kek, iv);\n const ct = Buffer.concat([cipher.update(dataKey), cipher.final()]);\n const tag = cipher.getAuthTag();\n const out = Buffer.alloc(WRAPPED_KEY_FILE_SIZE);\n let off = 0;\n KEK_MAGIC.copy(out, off); off += KEK_MAGIC.length;\n out[off] = keyVersion & 0xff; off += 1;\n salt.copy(out, off); off += KEK_SALT_BYTES;\n iv.copy(out, off); off += IV_BYTES;\n tag.copy(out, off); off += TAG_BYTES;\n ct.copy(out, off);\n return out;\n}\n\n/**\n * Parse a wrapped (v3) key file and return the data key + version. Throws a\n * clear ConfigError when the passphrase is missing or wrong (GCM auth failure).\n */\nfunction unwrapDataKey(buf: Buffer, keyFile: string): { key: Buffer; version: number } {\n const passphrase = getVaultPassphrase();\n if (!passphrase) {\n throw new ConfigError({\n message:\n `SecretVault: key file ${keyFile} is passphrase-protected — set the ` +\n `WRONGSTACK_VAULT_PASSPHRASE environment variable to unlock it.`,\n code: ERROR_CODES.CONFIG_INVALID,\n context: { keyFile },\n });\n }\n let off = KEK_MAGIC.length;\n const version = buf[off]!; off += 1;\n const salt = buf.subarray(off, off + KEK_SALT_BYTES); off += KEK_SALT_BYTES;\n const iv = buf.subarray(off, off + IV_BYTES); off += IV_BYTES;\n const tag = buf.subarray(off, off + TAG_BYTES); off += TAG_BYTES;\n const ct = buf.subarray(off, off + KEY_BYTES);\n const kek = deriveKEK(passphrase, salt);\n const decipher = createDecipheriv(ALGO, kek, iv);\n decipher.setAuthTag(tag);\n try {\n const key = Buffer.concat([decipher.update(ct), decipher.final()]);\n return { key: Buffer.from(key), version };\n } catch {\n throw new ConfigError({\n message:\n `SecretVault: failed to unlock key file ${keyFile} — wrong ` +\n `WRONGSTACK_VAULT_PASSPHRASE (key unwrap authentication failed).`,\n code: ERROR_CODES.CONFIG_INVALID,\n context: { keyFile },\n });\n }\n}\n\n/**\n * Check and warn if the key file has incorrect permissions on POSIX.\n * On Windows this is a no-op (mode bits don't apply).\n */\nfunction checkKeyFilePermissions(keyFile: string): void {\n if (process.platform === 'win32') return; // No mode bits on Windows\n try {\n const stat = fs.statSync(keyFile);\n const actualMode = stat.mode & 0o777;\n if (actualMode !== KEY_FILE_MODE) {\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'vault.key_file_wrong_permissions',\n message: `Key file ${keyFile} has mode ${actualMode.toString(8)} — expected ${KEY_FILE_MODE.toString(8)}. Run: chmod ${KEY_FILE_MODE.toString(8)} ${keyFile}`,\n keyFile,\n expectedMode: KEY_FILE_MODE,\n actualMode,\n timestamp: new Date().toISOString(),\n }));\n }\n } catch {\n // stat can fail for reasons other than the file not existing;\n // if it does, the ENOENT path handles it.\n }\n}\n\n/**\n * Default vault: AES-256-GCM with a key stored at `keyFile` (mode 0o600).\n * The key is loaded lazily on first encrypt/decrypt; if it does not exist,\n * a fresh one is generated. Decryption of plaintext values is a no-op so\n * legacy configs continue to work.\n *\n * Key file format:\n * - Legacy (v1): exactly 32 raw bytes\n * - Versioned (v2+): 4-byte magic `WSKV` + 1-byte version + 32-byte key (37 bytes)\n *\n * Encrypted value format: `enc:v<N>:<iv>:<tag>:<ciphertext>` where N is the\n * key version. After rotation, encrypt() emits the new version prefix.\n */\nexport class DefaultSecretVault implements RotatableSecretVault {\n private readonly keyFile: string;\n private key?: Buffer | undefined;\n private _keyVersion: number = 1;\n\n constructor(opts: SecretVaultOptions) {\n this.keyFile = opts.keyFile;\n }\n\n /** Current key version. Starts at 1; incremented by rotateKey(). */\n get keyVersion(): number {\n // Ensure key is loaded so version is accurate\n if (!this.key) this.loadOrCreateKey();\n return this._keyVersion;\n }\n\n isEncrypted(value: string): boolean {\n return typeof value === 'string' && ENCRYPTED_PREFIX_PATTERN.test(value);\n }\n\n encrypt(plaintext: string): string {\n if (this.isEncrypted(plaintext)) return plaintext;\n const key = this.loadOrCreateKey();\n const iv = randomBytes(IV_BYTES);\n const cipher = createCipheriv(ALGO, key, iv);\n const ct = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);\n const tag = cipher.getAuthTag();\n const prefix = encryptedPrefixForVersion(this._keyVersion);\n return `${prefix}${iv.toString('base64')}:${tag.toString('base64')}:${ct.toString('base64')}`;\n }\n\n decrypt(value: string): string {\n if (!this.isEncrypted(value)) return value;\n // Strip the versioned prefix (enc:v1:, enc:v2:, etc.)\n const prefixMatch = value.match(ENCRYPTED_PREFIX_PATTERN);\n if (!prefixMatch) {\n throw new ConfigError({\n message: 'SecretVault: malformed encrypted value',\n code: ERROR_CODES.CONFIG_PARSE_FAILED,\n context: { field: 'encrypted_value' },\n });\n }\n const rest = value.slice(prefixMatch[0].length);\n const parts = rest.split(':');\n if (parts.length !== 3) {\n throw new ConfigError({\n message: 'SecretVault: malformed encrypted value',\n code: ERROR_CODES.CONFIG_PARSE_FAILED,\n context: { field: 'encrypted_value' },\n });\n }\n const [ivB64, tagB64, ctB64] = parts as [string, string, string];\n const iv = Buffer.from(ivB64, 'base64');\n const tag = Buffer.from(tagB64, 'base64');\n const ct = Buffer.from(ctB64, 'base64');\n if (iv.length !== IV_BYTES) throw new ConfigError({\n message: 'SecretVault: bad IV length',\n code: ERROR_CODES.CONFIG_PARSE_FAILED,\n context: { expected: IV_BYTES, actual: iv.length },\n });\n if (tag.length !== TAG_BYTES) throw new ConfigError({\n message: 'SecretVault: bad tag length',\n code: ERROR_CODES.CONFIG_PARSE_FAILED,\n context: { expected: TAG_BYTES, actual: tag.length },\n });\n const key = this.loadOrCreateKey();\n const decipher = createDecipheriv(ALGO, key, iv);\n decipher.setAuthTag(tag);\n const pt = Buffer.concat([decipher.update(ct), decipher.final()]);\n return pt.toString('utf8');\n }\n\n /**\n * Generate a new encryption key, write it to disk, and increment the key version.\n * After rotation, encrypt() emits the new version prefix (e.g. enc:v2:).\n * The caller must re-encrypt existing config values (see rotateConfigKeys()).\n */\n rotateKey(): { oldVersion: number; newVersion: number } {\n const oldVersion = this._keyVersion;\n const newKey = randomBytes(KEY_BYTES);\n const newVersion = oldVersion + 1;\n\n fs.mkdirSync(path.dirname(this.keyFile), { recursive: true });\n const passphrase = getVaultPassphrase();\n if (passphrase) {\n // Keep the rotated key passphrase-wrapped (v3) so rotation never\n // downgrades a protected key file to plaintext.\n fs.writeFileSync(this.keyFile, wrapDataKey(newKey, newVersion, passphrase), { mode: 0o600 });\n } else {\n // Write versioned key file: WSKV + version byte + key\n const keyFileBuf = Buffer.alloc(VERSIONED_KEY_FILE_SIZE);\n KEY_FILE_MAGIC.copy(keyFileBuf, 0);\n keyFileBuf[KEY_FILE_MAGIC.length] = newVersion;\n newKey.copy(keyFileBuf, KEY_FILE_MAGIC.length + 1);\n fs.writeFileSync(this.keyFile, keyFileBuf, { mode: 0o600 });\n }\n checkKeyFilePermissions(this.keyFile);\n\n this.key = newKey;\n this._keyVersion = newVersion;\n return { oldVersion, newVersion };\n }\n\n /**\n * If WRONGSTACK_VAULT_PASSPHRASE is set but the key on disk is still stored\n * unwrapped (legacy v1 / versioned v2), re-write it in passphrase-wrapped (v3)\n * form. The data key is preserved, so all existing ciphertext keeps\n * decrypting. Best-effort: a write failure leaves the working unwrapped file\n * in place and is not fatal to load.\n */\n private migrateToWrappedIfPassphrase(): void {\n const passphrase = getVaultPassphrase();\n if (!passphrase || !this.key) return;\n try {\n fs.writeFileSync(this.keyFile, wrapDataKey(this.key, this._keyVersion, passphrase), {\n mode: 0o600,\n });\n checkKeyFilePermissions(this.keyFile);\n } catch {\n // Non-fatal: the at-rest upgrade failed, but the loaded key is valid.\n }\n }\n\n private loadOrCreateKey(): Buffer {\n // readFileSync blocks the event loop, but this is a one-time cost per\n // process: the key is cached after the first load and reused for every\n // subsequent encrypt/decrypt. For CLI usage (single run → exit) this is\n // negligible. For server contexts (eternal autonomy, MCP server mode),\n // the first encrypt/decrypt call causes a brief (<1ms) event loop stall.\n // Prefer calling vault.encrypt('') during boot to warm the cache if this\n // is a concern in your deployment.\n if (this.key) return this.key;\n try {\n const buf = fs.readFileSync(this.keyFile);\n\n // Passphrase-wrapped (v3): unwrap with WRONGSTACK_VAULT_PASSPHRASE.\n // Checked first because its size/magic are distinct from the others.\n if (isWrappedKeyFile(buf)) {\n const { key, version } = unwrapDataKey(buf, this.keyFile);\n this.key = key;\n this._keyVersion = version;\n checkKeyFilePermissions(this.keyFile);\n return this.key;\n }\n\n // Detect key file format:\n if (buf.length === KEY_BYTES) {\n // Legacy v1: raw 32-byte key\n this.key = buf;\n this._keyVersion = 1;\n checkKeyFilePermissions(this.keyFile);\n // Upgrade to passphrase-wrapped at rest if a passphrase is configured.\n this.migrateToWrappedIfPassphrase();\n return this.key;\n }\n\n if (buf.length === VERSIONED_KEY_FILE_SIZE) {\n // Versioned v2+: WSKV magic + version byte + 32-byte key\n const magic = buf.subarray(0, KEY_FILE_MAGIC.length);\n if (!magic.equals(KEY_FILE_MAGIC)) {\n throw new ConfigError({\n message: `SecretVault: key file ${this.keyFile} has invalid magic header`,\n code: ERROR_CODES.CONFIG_INVALID,\n context: { keyFile: this.keyFile },\n });\n }\n const version = buf[KEY_FILE_MAGIC.length]!;\n const key = buf.subarray(KEY_FILE_MAGIC.length + 1);\n if (key.length !== KEY_BYTES) {\n throw new ConfigError({\n message: `SecretVault: key file ${this.keyFile} has wrong key size (${key.length} bytes, expected ${KEY_BYTES})`,\n code: ERROR_CODES.CONFIG_INVALID,\n context: { keyFile: this.keyFile, expectedBytes: KEY_BYTES, actualBytes: key.length },\n });\n }\n this.key = Buffer.from(key);\n this._keyVersion = version;\n checkKeyFilePermissions(this.keyFile);\n // Upgrade to passphrase-wrapped at rest if a passphrase is configured.\n this.migrateToWrappedIfPassphrase();\n return this.key;\n }\n\n // Wrong size — neither legacy nor versioned format\n throw new ConfigError({\n message:\n `SecretVault: key file ${this.keyFile} is ${buf.length} bytes ` +\n `(expected ${KEY_BYTES} for v1 or ${VERSIONED_KEY_FILE_SIZE} for v2+). ` +\n `Remove it manually to generate a new key.`,\n code: ERROR_CODES.CONFIG_INVALID,\n context: { keyFile: this.keyFile, expectedBytes: KEY_BYTES, actualBytes: buf.length },\n });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;\n }\n // Create a fresh key. Use sync APIs so the constructor-free getter\n // remains synchronous from the caller's perspective.\n fs.mkdirSync(path.dirname(this.keyFile), { recursive: true });\n const key = randomBytes(KEY_BYTES);\n // When a passphrase is configured, a brand-new key is written wrapped (v3)\n // from the start; otherwise the legacy raw-32-byte format is preserved.\n const passphrase = getVaultPassphrase();\n const initialBytes = passphrase ? wrapDataKey(key, 1, passphrase) : key;\n // Use exclusive-create flag 'wx' to prevent races: if two processes race\n // to create the key file, only one succeeds and the loser gets EEXIST.\n try {\n fs.writeFileSync(this.keyFile, initialBytes, { mode: 0o600, flag: 'wx' });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'EEXIST') throw err;\n // Another process won the race — re-read what they wrote.\n const buf = fs.readFileSync(this.keyFile);\n if (isWrappedKeyFile(buf)) {\n const { key: winnerKey, version } = unwrapDataKey(buf, this.keyFile);\n this.key = winnerKey;\n this._keyVersion = version;\n checkKeyFilePermissions(this.keyFile);\n return this.key;\n }\n if (buf.length === KEY_BYTES) {\n // Legacy v1 format\n this.key = buf;\n this._keyVersion = 1;\n checkKeyFilePermissions(this.keyFile);\n return this.key;\n }\n if (buf.length === VERSIONED_KEY_FILE_SIZE) {\n // Versioned format\n const magic = buf.subarray(0, KEY_FILE_MAGIC.length);\n if (!magic.equals(KEY_FILE_MAGIC)) {\n throw new ConfigError({\n message: `SecretVault: key file ${this.keyFile} has invalid magic header`,\n code: ERROR_CODES.CONFIG_INVALID,\n context: { keyFile: this.keyFile },\n });\n }\n const version = buf[KEY_FILE_MAGIC.length]!;\n const winnerKey = buf.subarray(KEY_FILE_MAGIC.length + 1);\n this.key = Buffer.from(winnerKey);\n this._keyVersion = version;\n checkKeyFilePermissions(this.keyFile);\n return this.key;\n }\n throw new ConfigError({\n message:\n `SecretVault: key file ${this.keyFile} is ${buf.length} bytes ` +\n `(expected ${KEY_BYTES} for v1 or ${VERSIONED_KEY_FILE_SIZE} for v2+). ` +\n `Remove it manually to generate a new key.`,\n code: ERROR_CODES.CONFIG_INVALID,\n context: { keyFile: this.keyFile, expectedBytes: KEY_BYTES, actualBytes: buf.length },\n });\n }\n this.key = key;\n this._keyVersion = 1;\n return key;\n }\n}\n\n/**\n * Walk a Config-shaped object and decrypt any apiKey-like fields in place,\n * returning a new object. Used by the config loader so the rest of the\n * system never has to know about the wire format.\n *\n * @param warn — callback for decryption warnings. Defaults to `console.warn`\n * for backward compatibility; pass `logger.warn` when a structured logger\n * is available (preferred in long-running/server contexts).\n */\nexport function decryptConfigSecrets<T>(\n cfg: T,\n vault: SecretVault,\n opts?: { warn?: (msg: string) => void },\n): T {\n const warn = opts?.warn ?? ((msg: string) => console.warn(msg));\n // A single corrupted/malformed encrypted field should not kill the entire\n // config load. Swallow per-field decrypt errors (zero the field so callers\n // see \"missing key\" instead of holding ciphertext) and surface a warning.\n return walk(cfg, vault, (v, key) => {\n try {\n return vault.decrypt(v);\n } catch (err) {\n warn(\n `[secret-vault] Failed to decrypt \"${key}\": ${err instanceof Error ? err.message : err}`,\n );\n return '';\n }\n });\n}\n\nexport function encryptConfigSecrets<T>(\n cfg: T,\n vault: SecretVault,\n _opts?: { warn?: (msg: string) => void },\n): T {\n return walk(cfg, vault, (v) => vault.encrypt(v));\n}\n\nfunction walk<T>(node: T, vault: SecretVault, transform: (s: string, key: string) => string): T {\n if (node === null || node === undefined) return node;\n if (typeof node !== 'object') return node;\n if (Array.isArray(node)) {\n return node.map((item) => walk(item, vault, transform)) as never as T;\n }\n const out: Record<string, unknown> = Object.create(null);\n for (const [k, v] of Object.entries(node as Record<string, unknown>)) {\n if (typeof v === 'string' && isSecretField(k)) {\n out[k] = transform(v, k);\n } else if (typeof v === 'object' && v !== null) {\n out[k] = walk(v, vault, transform);\n } else {\n out[k] = v;\n }\n }\n return out as T;\n}\n\n/**\n * A key is treated as secret-bearing if its name (case-insensitive) contains\n * one of these tokens. Captures common variants like `apiKey`, `authToken`,\n * `refreshToken`, `sessionKey`, `password`, `client_secret`, `bearer`, etc.\n * Use a named field with `isSecret: false` annotation if you must opt out —\n * see `NON_SECRET_OVERRIDES` below.\n */\nconst SECRET_KEY_PATTERN =\n /(?:apikey|api_key|authtoken|auth_token|bearer|secret|password|passwd|pwd|refreshtoken|refresh_token|sessionkey|session_key|access[_-]?token|private[_-]?key)/i;\n\n// Field names that contain the literal substring \"key\" but are not secrets.\n// Keep this list short; the substring rule itself is intentionally narrow.\nconst NON_SECRET_OVERRIDES = new Set(['publickey', 'public_key']);\n\nexport function isSecretField(name: string): boolean {\n const lc = name.toLowerCase();\n if (NON_SECRET_OVERRIDES.has(lc)) return false;\n return SECRET_KEY_PATTERN.test(lc);\n}\n\n/**\n * Re-write `~/.wrongstack/config.json` (or any path) with all secret-bearing\n * fields encrypted. Used by the `wstack auth` subcommand.\n */\nexport async function rewriteConfigEncrypted(\n configPath: string,\n vault: SecretVault,\n patch?: Record<string, unknown>,\n): Promise<void> {\n let current: Record<string, unknown> = {};\n try {\n const raw = await fsp.readFile(configPath, 'utf8');\n current = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n // start from empty\n }\n const merged = deepMerge(current, patch ?? {});\n const encrypted = encryptConfigSecrets(merged, vault);\n await fsp.mkdir(path.dirname(configPath), { recursive: true });\n // atomicWrite: torn write here would erase every saved encrypted API key.\n await atomicWrite(configPath, JSON.stringify(encrypted, null, 2), { mode: 0o600 });\n await restrictFilePermissions(configPath);\n}\n\n/**\n * Scan a config file on disk for plaintext secret-bearing fields and\n * rewrite the file with them encrypted in place. Returns a count of how\n * many fields were migrated. Idempotent — calling on a fully-encrypted\n * file is a no-op and writes nothing. Used by the CLI on every boot so\n * users who had plaintext keys before the vault landed are upgraded\n * transparently.\n */\nexport async function migratePlaintextSecrets(\n configPath: string,\n vault: SecretVault,\n logger?: Pick<Logger, 'warn'>,\n): Promise<{ migrated: number; file: string }> {\n let raw: string;\n try {\n raw = await fsp.readFile(configPath, 'utf8');\n } catch {\n return { migrated: 0, file: configPath };\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return { migrated: 0, file: configPath };\n }\n const counter = { n: 0 };\n const migrated = walkCount(parsed, vault, counter);\n if (counter.n === 0) return { migrated: 0, file: configPath };\n // atomicWrite: runs on every boot for legacy users — torn write = wipe.\n await atomicWrite(configPath, JSON.stringify(migrated, null, 2), { mode: 0o600 });\n await restrictFilePermissions(\n configPath,\n logger ? { warn: (msg) => logger.warn(msg) } : undefined,\n );\n return { migrated: counter.n, file: configPath };\n}\n\n/**\n * Rotate the vault's encryption key and re-encrypt all secret-bearing\n * fields in a config file. This is the atomic key rotation operation:\n *\n * 1. Read the config file\n * 2. Decrypt all encrypted values with the old key\n * 3. Generate a new key (vault.rotateKey())\n * 4. Re-encrypt all values with the new key (new version prefix)\n * 5. Write the config file atomically\n *\n * Returns the number of fields re-encrypted and the version transition.\n * If the config file doesn't exist or has no encrypted fields, returns\n * { rotated: 0 } without modifying the key.\n */\nexport async function rotateConfigKeys(\n configPath: string,\n vault: RotatableSecretVault,\n logger?: Pick<Logger, 'warn' | 'info'>,\n): Promise<{ rotated: number; oldVersion: number; newVersion: number; file: string }> {\n const log = logger?.info ?? (() => {});\n const warn = logger?.warn ?? ((msg: string) => console.warn(msg));\n\n // Read the config file\n let raw: string;\n try {\n raw = await fsp.readFile(configPath, 'utf8');\n } catch {\n // No config file — just rotate the key without re-encrypting anything\n const { oldVersion, newVersion } = vault.rotateKey();\n log(`[secret-vault] Key rotated (v${oldVersion} → v${newVersion}) — no config file to re-encrypt`);\n return { rotated: 0, oldVersion, newVersion, file: configPath };\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n warn(`[secret-vault] Config file ${configPath} is not valid JSON — skipping rotation`);\n return { rotated: 0, oldVersion: vault.keyVersion, newVersion: vault.keyVersion, file: configPath };\n }\n\n // Count encrypted fields and decrypt them\n const counter = { n: 0, failed: [] as string[] };\n const decrypted = walkDecryptCount(parsed, vault, counter);\n\n // Abort BEFORE rotating if any encrypted field could not be decrypted with\n // the current key. Rotation would discard the old key while these fields\n // still hold old-key ciphertext, and walkReencrypt skips already-encrypted\n // values — so they would become permanently undecryptable. Surface the\n // corruption and leave the key intact for the operator to investigate.\n if (counter.failed.length > 0) {\n throw new Error(\n `[secret-vault] Aborting key rotation: ${counter.failed.length} field(s) could not be decrypted ` +\n `with the current key and would be permanently lost on rotation: ${counter.failed.join(', ')}. ` +\n `Restore or remove these fields before rotating.`,\n );\n }\n\n if (counter.n === 0) {\n // No encrypted fields — just rotate the key\n const { oldVersion, newVersion } = vault.rotateKey();\n log(`[secret-vault] Key rotated (v${oldVersion} → v${newVersion}) — no encrypted fields to re-encrypt`);\n return { rotated: 0, oldVersion, newVersion, file: configPath };\n }\n\n // Rotate the key (generates new key, increments version)\n const { oldVersion, newVersion } = vault.rotateKey();\n\n // Re-encrypt all secret fields with the new key\n const reencrypted = walkReencrypt(decrypted, vault);\n\n // Write the config file atomically\n await atomicWrite(configPath, JSON.stringify(reencrypted, null, 2), { mode: 0o600 });\n await restrictFilePermissions(configPath, { warn });\n\n log(`[secret-vault] Key rotated (v${oldVersion} → v${newVersion}) — re-encrypted ${counter.n} field(s)`);\n return { rotated: counter.n, oldVersion, newVersion, file: configPath };\n}\n\n/**\n * Walk a config object, decrypt all encrypted values, and count them.\n * Returns a new object with decrypted values.\n *\n * `counter.failed` collects the key paths of any field that is encrypted but\n * could NOT be decrypted with the current key. These are left as-is (old\n * ciphertext). The caller MUST treat a non-empty `failed` list as a hard stop\n * before rotating: rotation discards the old key, and `walkReencrypt` skips\n * already-encrypted values, so a retained old-key ciphertext would become\n * permanently undecryptable. Surfacing it is strictly safer than entombing it.\n */\nfunction walkDecryptCount<T>(\n node: T,\n vault: SecretVault,\n counter: { n: number; failed: string[] },\n pathPrefix = '',\n): T {\n if (node === null || node === undefined) return node;\n if (typeof node !== 'object') return node;\n if (Array.isArray(node)) {\n return node.map((item, i) =>\n walkDecryptCount(item, vault, counter, `${pathPrefix}[${i}]`),\n ) as never as T;\n }\n const out: Record<string, unknown> = Object.create(null);\n for (const [k, v] of Object.entries(node as Record<string, unknown>)) {\n const keyPath = pathPrefix ? `${pathPrefix}.${k}` : k;\n if (typeof v === 'string' && vault.isEncrypted(v)) {\n try {\n out[k] = vault.decrypt(v);\n counter.n++;\n } catch {\n // Decryption failed — record the path and keep the old ciphertext.\n // The caller aborts rotation when counter.failed is non-empty, so\n // the old key is never discarded while this value still depends on it.\n counter.failed.push(keyPath);\n out[k] = v;\n }\n } else if (typeof v === 'object' && v !== null) {\n out[k] = walkDecryptCount(v, vault, counter, keyPath);\n } else {\n out[k] = v;\n }\n }\n return out as T;\n}\n\n/**\n * Walk a config object and re-encrypt all secret-bearing fields.\n * Unlike encryptConfigSecrets, this encrypts ALL string values that\n * were previously decrypted (they're now plaintext), not just those\n * matching the secret field pattern. This ensures we re-encrypt values\n * that were successfully decrypted in walkDecryptCount.\n */\nfunction walkReencrypt<T>(node: T, vault: SecretVault): T {\n if (node === null || node === undefined) return node;\n if (typeof node !== 'object') return node;\n if (Array.isArray(node)) {\n return node.map((item) => walkReencrypt(item, vault)) as never as T;\n }\n const out: Record<string, unknown> = Object.create(null);\n for (const [k, v] of Object.entries(node as Record<string, unknown>)) {\n if (typeof v === 'string' && isSecretField(k) && v.length > 0 && !vault.isEncrypted(v)) {\n // This was a decrypted secret — re-encrypt it\n out[k] = vault.encrypt(v);\n } else if (typeof v === 'object' && v !== null) {\n out[k] = walkReencrypt(v, vault);\n } else {\n out[k] = v;\n }\n }\n return out as T;\n}\n\n/**\n * Restrict a file to owner-only access. On POSIX this is chmod 0o600.\n * On Windows, chmod is a no-op — we use icacls to remove inherited\n * permissions and grant only the current user. Failures are logged\n * but not thrown so callers are not blocked on unsupported platforms.\n */\nasync function restrictFilePermissions(\n filePath: string,\n opts?: { warn?: (msg: string) => void },\n): Promise<void> {\n const warn = opts?.warn ?? ((msg: string) => console.warn(msg));\n if (process.platform === 'win32') {\n try {\n const { execFile } = await import('node:child_process');\n const { promisify } = await import('node:util');\n const execFileAsync = promisify(execFile);\n const user = windowsAccountName();\n if (!user) {\n warn(\n `[secret-vault] Could not determine the current Windows user for ${filePath}; skipping icacls hardening.`,\n );\n return;\n }\n // Remove inherited ACEs, grant full control only to current user.\n await execFileAsync('icacls', [filePath, '/inheritance:r', '/grant:r', `${user}:(F)`]);\n } catch {\n // Best-effort: icacls may not be available in all environments.\n warn(\n `[secret-vault] Could not restrict permissions on ${filePath} — config file may be readable by other users on this system.`,\n );\n }\n } else {\n try {\n await fsp.chmod(filePath, 0o600);\n } catch {\n // Best-effort\n }\n }\n}\n\nfunction windowsAccountName(): string | undefined {\n const username = process.env.USERNAME || process.env.USER;\n if (!username || username.includes('\\0')) return undefined;\n const domain = process.env.USERDOMAIN;\n if (domain && !domain.includes('\\0')) return `${domain}\\\\${username}`;\n return username;\n}\n\nfunction walkCount<T>(node: T, vault: SecretVault, counter: { n: number }): T {\n if (node === null || node === undefined) return node;\n if (typeof node !== 'object') return node;\n if (Array.isArray(node)) {\n return node.map((item) => walkCount(item, vault, counter)) as never as T;\n }\n const out: Record<string, unknown> = Object.create(null);\n for (const [k, v] of Object.entries(node as Record<string, unknown>)) {\n if (typeof v === 'string' && isSecretField(k) && !vault.isEncrypted(v) && v.length > 0) {\n out[k] = vault.encrypt(v);\n counter.n++;\n } else if (typeof v === 'object' && v !== null) {\n out[k] = walkCount(v, vault, counter);\n } else {\n out[k] = v;\n }\n }\n return out as T;\n}\n\n/** Keys that, when written into a plain object, can poison the prototype\n * chain. We never want user config to carry these. */\nimport { deepMerge } from '../utils/deep-merge.js';\n","/**\n * provider-config-watcher — live hot-reload of provider credentials.\n *\n * Provider API keys are read from `config.json` once at boot and baked into\n * the constructed `Provider`. When a user adds/removes/replaces a key in\n * another process (a second terminal running `wstack auth`, or either WebUI\n * provider panel), a *running* session would otherwise keep using the\n * boot-time key until restart.\n *\n * This watcher closes that gap: it tails the global `config.json`, re-reads\n * and decrypts its `providers` map on change, and hands a fresh snapshot to\n * the caller, who updates in-memory config and rebuilds the active provider.\n *\n * It mirrors {@link module:hq/auth-store.watchHqAuthFile}:\n * - Watches the *directory* (not the file) so atomic tmp+rename writes\n * (see {@link module:utils/atomic-write.atomicWrite}) surface reliably.\n * - Debounces events (most writers do a tmp+rename dance emitting several).\n * - Reads leniently — a missing/corrupt/torn file yields a warning, never a\n * throw, and the watcher stays live for the next valid write.\n *\n * A `lastSerialized` guard suppresses the callback when the on-disk providers\n * map is byte-for-byte identical to the last one we surfaced. This makes the\n * watcher a no-op for self-induced writes (e.g. the same process's `/model`\n * switch or a WebUI key save), so there is no rebuild storm.\n *\n * `fs.watch` is best-effort across platforms; on some network filesystems\n * events may not fire and the operator must restart to pick up changes.\n *\n * @module storage/provider-config-watcher\n */\nimport * as syncFs from 'node:fs';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\nimport { decryptConfigSecrets } from '../security/secret-vault.js';\nimport type { ProviderConfig } from '../types/config.js';\nimport type { SecretVault } from '../types/secret-vault.js';\n\n/**\n * A decrypted snapshot of the credential-bearing slice of `config.json`.\n * `providers` is always present (empty object when the file has none);\n * `apiKey`/`baseUrl` are the top-level fallbacks a provider inherits when its\n * saved entry omits them.\n */\nexport interface ProviderConfigSnapshot {\n providers: Record<string, ProviderConfig>;\n apiKey?: string;\n baseUrl?: string;\n}\n\nexport interface WatchProviderConfigOptions {\n /** Surface non-fatal read/parse/decrypt issues. */\n warn?: (msg: string) => void;\n /** Coalesce bursts of fs events (default 200ms). */\n debounceMs?: number;\n}\n\n/**\n * Read and decrypt the credential slice of a config file. Returns `undefined`\n * when the file is missing or unparseable (the `warn` callback carries the\n * detail); never throws for routine I/O.\n */\nasync function readProviderSnapshot(\n configPath: string,\n vault: SecretVault,\n warn?: (msg: string) => void,\n): Promise<ProviderConfigSnapshot | undefined> {\n let raw: string;\n try {\n raw = await fs.readFile(configPath, 'utf8');\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n warn?.(`Could not read ${configPath}: ${(err as Error).message}`);\n }\n return undefined;\n }\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(raw) as Record<string, unknown>;\n } catch (err) {\n // A torn read mid-rename can surface as invalid JSON; treat as transient.\n warn?.(`Config at ${configPath} is not valid JSON: ${(err as Error).message}`);\n return undefined;\n }\n const decrypted = decryptConfigSecrets(parsed, vault, warn ? { warn } : {}) as {\n providers?: Record<string, ProviderConfig>;\n apiKey?: string;\n baseUrl?: string;\n };\n const snapshot: ProviderConfigSnapshot = {\n providers: decrypted.providers ?? {},\n };\n if (typeof decrypted.apiKey === 'string') snapshot.apiKey = decrypted.apiKey;\n if (typeof decrypted.baseUrl === 'string') snapshot.baseUrl = decrypted.baseUrl;\n return snapshot;\n}\n\n/** Stable serialization for the no-op guard (key order independent). */\nfunction serializeSnapshot(s: ProviderConfigSnapshot): string {\n return JSON.stringify({\n providers: s.providers,\n apiKey: s.apiKey ?? null,\n baseUrl: s.baseUrl ?? null,\n });\n}\n\n/**\n * Watch `configPath` for credential changes and invoke `onChange` with a\n * freshly-decrypted snapshot whenever the `providers`/`apiKey`/`baseUrl` slice\n * actually changes. Returns a `close()` that stops watching.\n *\n * The initial on-disk state is read once to seed the no-op guard but does NOT\n * fire `onChange` — only subsequent changes do.\n */\nexport function watchProviderConfig(\n configPath: string,\n vault: SecretVault,\n onChange: (snapshot: ProviderConfigSnapshot) => void,\n opts: WatchProviderConfigOptions = {},\n): { close: () => void } {\n const debounceMs = opts.debounceMs ?? 200;\n const warn = opts.warn;\n const base = path.basename(configPath);\n let timer: ReturnType<typeof setTimeout> | undefined;\n let closed = false;\n let lastSerialized: string | undefined;\n\n // Seed the guard with current on-disk content so the first *change* fires\n // rather than re-applying what we already have.\n void readProviderSnapshot(configPath, vault, warn).then((seed) => {\n if (!closed && seed && lastSerialized === undefined) {\n lastSerialized = serializeSnapshot(seed);\n }\n });\n\n let watcher: syncFs.FSWatcher;\n try {\n // Watch the directory (not the file) so atomic-rename events surface\n // reliably across platforms.\n watcher = syncFs.watch(path.dirname(configPath), { recursive: false });\n } catch (err) {\n warn?.(`Provider config watcher could not start: ${(err as Error).message}`);\n return { close: () => {} };\n }\n\n const trigger = (): void => {\n if (closed) return;\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n timer = undefined;\n void readProviderSnapshot(configPath, vault, warn).then(\n (next) => {\n if (closed || !next) return;\n const serialized = serializeSnapshot(next);\n if (serialized === lastSerialized) return; // no-op / self-write\n lastSerialized = serialized;\n onChange(next);\n },\n () => {\n // readProviderSnapshot never rejects for routine I/O — guard only.\n },\n );\n }, debounceMs);\n };\n\n watcher.on('change', (eventType: string, filename: string | Buffer | null) => {\n const name = typeof filename === 'string' ? filename : '';\n if (eventType === 'rename' || eventType === 'change') {\n if (!name || name === base) trigger();\n }\n });\n\n watcher.on('error', (err: Error) => {\n warn?.(`Provider config watcher error: ${err.message}`);\n });\n\n return {\n close: () => {\n closed = true;\n if (timer) clearTimeout(timer);\n watcher.close();\n },\n };\n}\n","import { expectDefined } from '../utils/expect-defined.js';\nexport type ContextWindowModeId = 'balanced' | 'frugal' | 'deep' | 'archival';\n\nexport type ContextWindowAggressiveOn = 'hard' | 'soft' | 'warn';\n\nexport interface ContextWindowThresholds {\n warn: number;\n soft: number;\n hard: number;\n}\n\nexport interface ContextWindowMode {\n id: ContextWindowModeId;\n name: string;\n description: string;\n thresholds: ContextWindowThresholds;\n aggressiveOn: ContextWindowAggressiveOn;\n preserveK: number;\n eliseThreshold: number;\n targetLoad: number;\n}\n\nexport interface ContextWindowPolicy extends ContextWindowMode {}\n\nexport interface ContextWindowConfigLike {\n mode?: ContextWindowModeId | string | undefined;\n warnThreshold?: number | undefined;\n softThreshold?: number | undefined;\n hardThreshold?: number | undefined;\n preserveK?: number | undefined;\n eliseThreshold?: number | undefined;\n}\n\nexport const DEFAULT_CONTEXT_WINDOW_MODE_ID: ContextWindowModeId = 'balanced';\n\nexport const CONTEXT_WINDOW_MODES: readonly ContextWindowMode[] = Object.freeze([\n {\n id: 'balanced',\n name: 'Balanced',\n description: 'Default rolling compaction: recent work stays verbatim, old tool output is trimmed.',\n thresholds: { warn: 0.6, soft: 0.75, hard: 0.9 },\n aggressiveOn: 'soft',\n preserveK: 10,\n eliseThreshold: 2000,\n targetLoad: 0.65,\n },\n {\n id: 'frugal',\n name: 'Frugal',\n description: 'Token-saver mode: compacts early and keeps a tighter verbatim tail.',\n thresholds: { warn: 0.45, soft: 0.6, hard: 0.75 },\n aggressiveOn: 'warn',\n preserveK: 6,\n eliseThreshold: 700,\n targetLoad: 0.5,\n },\n {\n id: 'deep',\n name: 'Deep',\n description: 'Long-reasoning mode: delays compaction and keeps more recent turns intact.',\n thresholds: { warn: 0.72, soft: 0.86, hard: 0.96 },\n aggressiveOn: 'hard',\n preserveK: 18,\n eliseThreshold: 5000,\n targetLoad: 0.78,\n },\n {\n id: 'archival',\n name: 'Archival',\n description: 'Decision-preserving mode: compacts steadily while keeping summaries prominent.',\n thresholds: { warn: 0.55, soft: 0.7, hard: 0.84 },\n aggressiveOn: 'soft',\n preserveK: 8,\n eliseThreshold: 1200,\n targetLoad: 0.58,\n },\n]);\n\nexport function listContextWindowModes(): ContextWindowMode[] {\n return CONTEXT_WINDOW_MODES.map((m) => ({ ...m, thresholds: { ...m.thresholds } }));\n}\n\nexport function getContextWindowMode(id: string | null | undefined): ContextWindowMode | null {\n if (!id) return null;\n const mode = CONTEXT_WINDOW_MODES.find((m) => m.id === id);\n return mode ? { ...mode, thresholds: { ...mode.thresholds } } : null;\n}\n\nexport function isContextWindowModeId(id: string): id is ContextWindowModeId {\n return CONTEXT_WINDOW_MODES.some((m) => m.id === id);\n}\n\nexport function resolveContextWindowPolicy(\n config: ContextWindowConfigLike = {},\n overrideMode?: string | null | undefined,\n): ContextWindowPolicy {\n const requested = overrideMode ?? config.mode ?? DEFAULT_CONTEXT_WINDOW_MODE_ID;\n const mode = getContextWindowMode(requested) ?? expectDefined(getContextWindowMode(DEFAULT_CONTEXT_WINDOW_MODE_ID));\n\n if (mode.id !== DEFAULT_CONTEXT_WINDOW_MODE_ID) {\n return mode;\n }\n\n return {\n ...mode,\n thresholds: {\n warn: config.warnThreshold ?? mode.thresholds.warn,\n soft: config.softThreshold ?? mode.thresholds.soft,\n hard: config.hardThreshold ?? mode.thresholds.hard,\n },\n preserveK: config.preserveK ?? mode.preserveK,\n eliseThreshold: config.eliseThreshold ?? mode.eliseThreshold,\n };\n}\n\nexport function formatContextWindowModeList(activeId?: string | null): string {\n return CONTEXT_WINDOW_MODES.map((m) => {\n const marker = m.id === activeId ? '*' : ' ';\n return `${marker} ${m.id.padEnd(9)} ${m.name} - ${m.description}`;\n }).join('\\n');\n}\n","import type { ContextWindowModeId } from './context-window.js';\nimport type { HookEvent, ShellHook } from './hooks.js';\nimport type { WireFamily } from './models-registry.js';\nimport type { CacheTtl, Capabilities, ReasoningEffort } from './provider.js';\nimport type { Permission } from './tool.js';\n\n/**\n * Runtime reasoning controls the user can set per-session/project. Mapped into\n * the provider `Request.reasoning` field by the model-runtime request\n * middleware, gated by the active model's `reasoningConfig` capabilities so\n * unsupported values are omitted (and warned) instead of triggering provider\n * 400s. See `resolveReasoningForRequest()` in packages/core.\n */\nexport interface ModelRuntimeReasoningConfig {\n /**\n * Whether to send explicit reasoning enable/disable.\n * - 'auto' → do not send explicit fields; provider/model default wins\n * - 'on' → send `reasoning.enabled = true`\n * - 'off' → send `reasoning.enabled = false` only when the model supports disable\n */\n mode?: 'auto' | 'on' | 'off' | undefined;\n /** Reasoning effort. Only sent when the model advertises `effortSupported`. */\n effort?: ReasoningEffort | undefined;\n /** Preserve thinking across turns. Only sent when `preserveThinking !== 'unsupported'`. */\n preserve?: boolean | undefined;\n}\n\n/**\n * Runtime prompt-cache controls mapped into `Request.cache`. Currently only the\n * Anthropic TTL toggle (5m vs 1h) is exposed; other providers ignore it.\n */\nexport interface ModelRuntimeCacheConfig {\n ttl?: CacheTtl | undefined;\n}\n\n/**\n * Shared runtime controls applied to every provider request, regardless of host\n * (REPL / TUI / WebUI). The CLI installs a single request-pipeline middleware\n * that reads these and mutates the outgoing `Request`.\n */\nexport interface ModelRuntimeConfig {\n reasoning?: ModelRuntimeReasoningConfig | undefined;\n cache?: ModelRuntimeCacheConfig | undefined;\n /**\n * Generic generation parameters mapped directly onto `Request` fields.\n * Only sent when the active model's `Capabilities` advertise support.\n */\n parameters?: ModelRuntimeParametersConfig | undefined;\n}\n\n/**\n * Generic generation parameters the user can set per-session / per-project.\n * Each field maps to a `Request` field of the same name and is gated by the\n * corresponding `Capabilities` flag so unsupported models don't receive\n * parameters they'd reject.\n */\nexport interface ModelRuntimeParametersConfig {\n /** Top-K sampling (Anthropic, Gemini). Gated by `capabilities.topK`. */\n topK?: number | undefined;\n /** Frequency penalty (OpenAI, Gemini). Gated by `capabilities.frequencyPenalty`. */\n frequencyPenalty?: number | undefined;\n /** Presence penalty (OpenAI, Gemini). Gated by `capabilities.presencePenalty`. */\n presencePenalty?: number | undefined;\n /** Random seed (OpenAI, Gemini). Gated by `capabilities.seed`. */\n seed?: number | undefined;\n /** End-user identifier for abuse monitoring. */\n user?: string | undefined;\n /** Log probabilities (OpenAI, Gemini). Gated by `capabilities.logprobs`. */\n logprobs?: boolean | undefined;\n /** Number of top logprobs to return (OpenAI). Only when `logprobs` is true. */\n topLogprobs?: number | undefined;\n}\n\n/**\n * HQ client connection settings. Same-machine clients can auto-discover the\n * local HQ auth file; remote clients use this config-backed URL/token pair.\n */\nexport interface HqClientConfig {\n /** Enable HQ publishing. Env WRONGSTACK_HQ_ENABLED still overrides at runtime. */\n enabled?: boolean | undefined;\n /** HQ HTTP base URL, e.g. http://host:3499. */\n url?: string | undefined;\n /** Client token for /ws/client. Stored encrypted by SecretVault when persisted. */\n token?: string | undefined;\n /** Optional HQ data dir for same-machine auth.json discovery. */\n dataDir?: string | undefined;\n /** Send raw content previews to HQ instead of redacted previews. */\n rawContent?: boolean | undefined;\n /** Override project display name in HQ. */\n projectAlias?: string | undefined;\n}\n\n/**\n * Token-saving mode tier levels. Controls how aggressively the system prompt\n * is compacted to reduce per-request token consumption.\n *\n * - 'off' — Full prompt, all tools, complete guidance (no reduction)\n * - 'minimal' — TIER1 tools only (~10), stripped guidance (~3-4k tokens saved)\n * - 'light' — Core + memory tools (~14), common patterns, minimal guidance\n * - 'medium' — Most development tools (~24), some guidance (default when `true`)\n * - 'aggressive' — Maximum savings before tools become unusable (~4-5k tokens saved)\n */\nexport type TokenSavingTier = 'off' | 'minimal' | 'light' | 'medium' | 'aggressive';\n\n/**\n * Normalize a TokenSavingTier value, handling backward-compatible boolean inputs.\n * - `true` → 'medium' (existing behavior)\n * - `false` → 'off'\n * - string values are returned as-is after validation\n * - `undefined` → 'off'\n */\nexport function normalizeTokenSavingTier(\n val?: TokenSavingTier | boolean,\n): TokenSavingTier {\n if (val === undefined) return 'off';\n if (typeof val === 'boolean') return val ? 'medium' : 'off';\n const validTiers = new Set<TokenSavingTier>([\n 'off',\n 'minimal',\n 'light',\n 'medium',\n 'aggressive',\n ]);\n return validTiers.has(val) ? val : 'off';\n}\n\nexport const DEFAULT_TUI_THINKING_WORD = 'thinking';\nexport const MAX_TUI_THINKING_WORD_LENGTH = 16;\n\n/**\n * Normalize the configurable statusline word shown while the TUI is working.\n * The value must be a single short word; invalid values fall back to the default.\n */\nexport function normalizeTuiThinkingWord(value: unknown): string {\n if (typeof value !== 'string') return DEFAULT_TUI_THINKING_WORD;\n const word = value.trim();\n if (word.length === 0 || word.length > MAX_TUI_THINKING_WORD_LENGTH) {\n return DEFAULT_TUI_THINKING_WORD;\n }\n if (!/^[\\p{L}\\p{N}_-]+$/u.test(word)) return DEFAULT_TUI_THINKING_WORD;\n return word;\n}\n\nexport interface ContextConfig {\n /** Context-window policy mode. Controls compaction thresholds and preservation depth. */\n mode?: ContextWindowModeId | undefined;\n warnThreshold: number;\n softThreshold: number;\n hardThreshold: number;\n /** Enable automatic compaction when thresholds are crossed (default: true). */\n autoCompact?: boolean | undefined;\n /**\n * Model used for LLM-assisted summarization in IntelligentCompactor.\n * Falls back to the main model when omitted.\n */\n summarizerModel?: string | undefined;\n /**\n * Override the effective context window size (in tokens). Use this when\n * you want the compactor to trigger earlier than the provider's actual\n * maxContext. Defaults to the provider's reported maxContext.\n */\n effectiveMaxContext?: number | undefined;\n maxSessionTokens?: number | undefined;\n maxDailyTokens?: number | undefined;\n preserveK: number;\n eliseThreshold: number;\n /** Compactor strategy: 'hybrid' (default, fast rules), 'intelligent' (LLM summarization), 'selective' (LLM-driven selection). */\n strategy?: 'hybrid' | 'intelligent' | 'selective' | undefined;\n /** Enable LLM-driven selective compaction (default: false for backward compat). */\n llmSelector?: boolean | undefined;\n}\n\n/**\n * Runtime configuration for the process circuit breaker (the one owned by the\n * ProcessRegistry that gates `bash`/`exec`). Toggle via `/settings breaker`.\n *\n * The breaker itself is a low-level primitive (`packages/tools/.../circuit-breaker.ts`)\n * that is on by default; this section controls whether the registry actually\n * participates in it and how it auto-recovers.\n */\nexport interface CircuitBreakerRuntimeConfig {\n /**\n * Enable circuit-breaker protection. When false (the default), the breaker\n * is bypassed — `bash`/`exec` calls always proceed regardless of failure\n * history. When true, the breaker trips on repeated failures / slow calls /\n * bursts and blocks further calls until it recovers.\n */\n enabled?: boolean | undefined;\n /**\n * When the breaker trips, automatically kill all tracked processes AND\n * reset the breaker to closed after this delay (ms). 0 = disabled (manual\n * recovery only via `/kill reset`). Only effective when `enabled` is true.\n * While armed, the statusline shows a live countdown to the kill/reset.\n */\n autoKillResetMs?: number | undefined;\n}\n\n/**\n * Adaptive concurrency controller configuration. When enabled, the controller\n * automatically adjusts `maxConcurrent` based on rate-limit (429) errors:\n * - On 429: halves `maxConcurrent` (floor at 1)\n * - On sustained success (no 429 for `recoveryIntervalMs`): increases `maxConcurrent` by 1\n */\nexport interface AdaptiveConcurrencyConfig {\n /** Enable adaptive concurrency. Default: false (disabled). */\n enabled?: boolean | undefined;\n /**\n * Minimum concurrency floor. The controller never drops below this.\n * Default: 1.\n */\n minConcurrent?: number | undefined;\n /**\n * Maximum concurrency ceiling. The controller never exceeds this.\n * Default: 16 (matches MultiAgentCoordinator default).\n */\n maxConcurrent?: number | undefined;\n /**\n * Multiplicative decrease factor when a 429 is hit.\n * `newConcurrency = floor(currentConcurrency * decreaseFactor)`.\n * Default: 0.5 (halves concurrency).\n */\n decreaseFactor?: number | undefined;\n /**\n * Number of consecutive successful requests before increasing concurrency by 1.\n * Default: 10.\n */\n successThreshold?: number | undefined;\n /**\n * How often (ms) to check for recovery and bump concurrency.\n * Default: 30_000 (30 seconds).\n */\n recoveryIntervalMs?: number | undefined;\n}\n\nexport interface ToolsConfig {\n defaultExecutionStrategy: 'parallel' | 'sequential' | 'smart';\n maxIterations: number;\n iterationTimeoutMs: number;\n sessionTimeoutMs: number;\n perIterationOutputCapBytes: number;\n /**\n * Per-tool prose budget for the tool's top-level description and usage hint.\n * Missing entries default to \"extend\".\n */\n descriptionMode?: ToolDescriptionModeConfig | undefined;\n /**\n * Per-tool on-screen result rendering mode (terminal / WebUI / TUI).\n * Missing entries default to \"extend\". Independent of `descriptionMode`:\n * `/tool <name> result simple` toggles this without touching the\n * LLM-side description length.\n */\n resultRenderMode?: ToolResultRenderModeConfig | undefined;\n /**\n * Tool names to disable. Disabled tools are excluded from the tool registry\n * (`ToolRegistry.list()` / `get()`), so they do NOT appear in the system\n * prompt's \"## Tool usage\" block — reducing per-request token consumption.\n * Override per-session with `/tool enable <name>` or re-enable all via\n * `/tool enable-all`.\n */\n disabledTools?: string[] | undefined;\n /**\n * When true (default), the agent automatically extends its iteration\n * limit by 100 when hit. Set to false to require user confirmation.\n */\n autoExtendLimit?: boolean | undefined;\n /**\n * When true, file tools (read/write/edit/grep/glob/install) are confined to\n * the project root and `set_working_dir` may not leave it. Default: false —\n * tools may access paths outside the project root, still subject to each\n * tool's permission tier (writes/edits prompt for confirmation). Toggle via\n * `/settings` (\"Filesystem access\").\n */\n restrictToProjectRoot?: boolean | undefined;\n /**\n * Per-command policy for the `exec` tool's allowlist. The tool ships a\n * curated default allowlist of dev/build commands; this extends or trims it.\n *\n * SECURITY: `allow` EXPANDS what the agent may execute, so it is honored only\n * from TRUSTED config (`~/.wrongstack/config.json`) — the config loader\n * strips `tools.exec.allow` from the untrusted, repo-committed\n * `<project>/.wrongstack/config.json`. `deny` only ever REMOVES commands, so\n * it is honored from any source.\n */\n exec?: ExecToolConfig | undefined;\n}\n\n/** Allow/deny extension of the `exec` tool's built-in command allowlist. */\nexport interface ExecToolConfig {\n /**\n * Extra command names to add to the allowlist (e.g. `[\"make\", \"dotnet\"]`).\n * Trusted sources only — stripped from in-project repo config.\n */\n allow?: string[] | undefined;\n /**\n * Command names to remove from the allowlist. Honored from any source —\n * removing a command can only narrow what runs, so it is always safe.\n */\n deny?: string[] | undefined;\n}\n\nexport type ToolDescriptionMode = 'extend' | 'simple';\nexport type ToolDescriptionModeConfig = Record<string, ToolDescriptionMode | undefined>;\n\n/**\n * Per-tool on-screen result rendering mode. Independent of\n * {@link ToolDescriptionMode}: `descriptionMode` controls the prose the\n * model sees in the system prompt, `resultRenderMode` controls how the\n * tool's RESULT is printed to the user (terminal / WebUI / TUI).\n *\n * - `simple` — meta only (filename, line count, exit code). Body is hidden\n * by default; the user can still expand on demand where the renderer\n * supports it.\n * - `extend` — full preview, up to 10 lines for read-like tools.\n *\n * The two modes are toggled independently via `/tool <name> desc simple`\n * and `/tool <name> result simple`. The legacy `/tool <name> simple`\n * command sets BOTH at once for backward compatibility.\n */\nexport type ToolResultRenderMode = 'extend' | 'simple';\nexport type ToolResultRenderModeConfig = Record<string, ToolResultRenderMode | undefined>;\n\nexport interface ProviderApiKey {\n /** Short human-readable label (e.g. \"personal\", \"work\", \"rate-limit-backup\"). */\n label: string;\n /**\n * The key itself. The field name contains `apiKey` so the secret-vault\n * walker will encrypt it on write and decrypt it on read.\n */\n apiKey: string;\n /** ISO-8601 timestamp the key was added. */\n createdAt: string;\n /**\n * How this credential was obtained.\n * - `api_key` — manually pasted API key (default)\n * - `oauth` — OAuth 2.0 device-code / authorization-code flow\n * - `session_token` — extracted from browser session (ChatGPT web, etc.)\n */\n authMethod?: 'api_key' | 'oauth' | 'session_token' | undefined;\n /** ISO-8601 expiry. When set, the token manager will refresh before this time. */\n expiresAt?: string | undefined;\n /**\n * OAuth refresh token. Stored encrypted by the secret-vault walker because\n * the field name contains `Token` (case-insensitive match by vault).\n */\n refreshToken?: string | undefined;\n /** Token type as returned by the OAuth endpoint (e.g. \"bearer\"). */\n tokenType?: string | undefined;\n /** OAuth scope string (e.g. \"openai.models.read openai.models.use\"). */\n scope?: string | undefined;\n /**\n * ChatGPT account id, extracted from the OAuth access-token JWT\n * (`https://api.openai.com/auth`.chatgpt_account_id). Sent as the\n * `chatgpt-account-id` header by the `openai-codex` wire family. Cached\n * here for display/diagnostics; the provider re-derives it from the live\n * token at request time so it can never go stale after a refresh.\n */\n accountId?: string | undefined;\n}\n\nexport interface ProviderConfig {\n type: string;\n /**\n * Legacy single-key field. Still honored as a read fallback when `apiKeys`\n * is empty (for configs not yet migrated to multi-key format). After key\n * management operations (`writeKeysBack`), this field is **cleared** to\n * prevent accidental serialization of the plaintext key. Consumers that\n * need the active API key should use `resolveActiveApiKey()` (cli) or\n * resolve from `apiKeys[]` directly — never read `cfg.apiKey` in new code.\n */\n apiKey?: string | undefined;\n /** Multiple keys for the same provider — pick one with `activeKey`. */\n apiKeys?: ProviderApiKey[] | undefined;\n /** Label of the entry in `apiKeys` to use. Defaults to the first one. */\n activeKey?: string | undefined;\n baseUrl?: string | undefined;\n headers?: Record<string, string>;\n model?: string | undefined;\n quirks?: Record<string, unknown>;\n capabilities?: Record<string, unknown>;\n /**\n * Optional wire-family override. When present, the provider can be\n * constructed without consulting the models.dev catalog — useful for\n * self-hosted endpoints, internal proxies, or for working offline.\n */\n family?: WireFamily | undefined;\n /** Custom env var names to probe when `apiKey` is missing. */\n envVars?: string[] | undefined;\n /** Optional list of models the user wants visible for this provider. */\n models?: string[] | undefined;\n /**\n * Fetch this provider's model list + per-model capabilities from its\n * `{baseUrl}/models` endpoint at startup and inject them into the catalog.\n * For openai-compatible gateways/proxies (omniroute, LiteLLM, vLLM, …) that\n * expose rich metadata there. Defaults on for presets that set it (omniroute).\n * Discovery is best-effort: a down server or missing key is a no-op.\n */\n autoDiscoverModels?: boolean | undefined;\n /**\n * Provider-relative custom model definitions (maps modelId → definition).\n * Each entry adds/overrides a model for this provider with optional\n * capability overrides. The model id is the key, not a fully qualified id.\n */\n customModels?: Record<string, CustomModelDefinition>;\n /**\n * Per-provider OAuth configuration. When present, `wstack auth login <id>`\n * uses this instead of prompting for a raw API key. Set by the catalog or\n * by the user via `/settings`.\n */\n oauthConfig?: {\n /** OAuth client id registered with the provider. */\n clientId?: string | undefined;\n /** Device authorization endpoint (RFC 8628). */\n deviceCodeEndpoint?: string | undefined;\n /** Token endpoint for code exchange and refresh. */\n tokenEndpoint?: string | undefined;\n /** Authorization server URL shown to the user for opening in browser. */\n authorizationEndpoint?: string | undefined;\n /** Default OAuth scopes to request. */\n scopes?: string[] | undefined;\n } | undefined;\n}\n\n/**\n * One entry in the per-task model matrix. Pins a catalog role, a phase, or\n * the `*` default to a specific model (and, optionally, a specific provider).\n * Resolved at subagent-spawn time so e.g. `security-scanner` can run a\n * different model than `documentation` while the leader stays on its own.\n */\nexport interface ModelMatrixEntry {\n /** Provider registry id (e.g. \"anthropic\", \"minimax\", \"zai\"). When omitted,\n * the leader's provider is used with this entry's model. */\n provider?: string | undefined;\n /** Model id to run for the matched role/phase/default. */\n model?: string | undefined;\n /**\n * Named fallback profile to use for the matched role/phase/default. When\n * `model` is omitted, the first model in the profile becomes the primary and\n * the remaining entries become that subagent's fallback chain.\n */\n fallbackProfile?: string | undefined;\n}\n\nexport interface MCPServerConfig {\n /** Human-readable description shown in `wstack mcp list`. */\n description?: string | undefined;\n name: string;\n transport: 'stdio' | 'sse' | 'streamable-http';\n command?: string | undefined;\n args?: string[] | undefined;\n env?: Record<string, string>;\n url?: string | undefined;\n headers?: Record<string, string>;\n enabled?: boolean | undefined;\n allowedTools?: string[] | undefined;\n permission?: Permission | undefined;\n startupTimeoutMs?: number | undefined;\n requestTimeoutMs?: number | undefined;\n /**\n * Lazy connect: when true, the server process is NOT spawned at boot. Its\n * tools are registered from a cached manifest (discovered on the first ever\n * connect) and the server only spawns when one of its tools is actually\n * called, then auto-sleeps after an idle period. Default (false/undefined) =\n * eager connect at boot.\n */\n lazy?: boolean | undefined;\n}\n\nexport interface LogConfig {\n level: 'error' | 'warn' | 'info' | 'debug' | 'trace';\n file?: string | undefined;\n}\n\nexport interface PluginConfig {\n name: string;\n enabled?: boolean | undefined;\n options?: Record<string, unknown>;\n}\n\n/**\n * Optional subsystems that the CLI can boot without. The core flow\n * (provider + agent loop + bundled tools + session) always works; these\n * just add capabilities. `--no-features` flips all of these off, which\n * is the minimum viable WrongStack: a single provider, a fixed config,\n * no network calls at startup.\n */\nexport interface FeaturesConfig {\n /** Load MCP servers declared in `mcpServers`. */\n mcp: boolean;\n /** Load + initialise npm plugins declared in `plugins`. */\n plugins: boolean;\n /** Register `remember` / `forget` tools backed by memory store. */\n memory: boolean;\n /**\n * Automatically consolidate session learnings into long-term memory\n * after each completed run. The agent extracts key facts, conventions,\n * and decisions via a lightweight LLM call and persists them.\n * Enabled by default when `memory` is on; set to false to opt out.\n */\n memoryConsolidation?: boolean | undefined;\n /** Fetch the models.dev catalog at startup. When false, the provider\n * must declare its `family` explicitly in `providers[<id>]`. */\n modelsRegistry: boolean;\n /** Discover + load skills from disk. */\n skills: boolean;\n /**\n * Enable the prompt library (`/prompt`, `/prompts`, `/prompt-gen`, the WebUI\n * modal and the bundled 168-prompt dataset). Defaults to on; set to false to\n * disable the subsystem entirely (the loader is withheld so every surface\n * reports it unavailable).\n */\n prompts?: boolean | undefined;\n /**\n * Token-saving mode tier. Controls how aggressively the system prompt\n * is compacted to reduce per-request token consumption.\n *\n * - 'off' — Full prompt, all tools, complete guidance\n * - 'minimal' — TIER1 tools only, stripped guidance (~3-4k tokens saved)\n * - 'light' — Core + memory tools, common patterns, minimal guidance\n * - 'medium' — Most development tools, some guidance\n * - 'aggressive' — Maximum savings before tools become unusable (~4-5k tokens)\n *\n * Boolean values are accepted for backward compatibility:\n * - `true` → 'medium'\n * - `false` → 'off'\n *\n * Enable via CLI: `--token-saving-tier <level>` or `--token-saving-mode` (maps to 'medium').\n * Configure via: `features.tokenSavingMode: \"minimal\"` in config.\n */\n tokenSavingMode?: TokenSavingTier | boolean | undefined;\n /**\n * Enable the autonomous-coordination toolkit (AutonomousCoordinator +\n * KnowledgeGraph + ConsensusProtocol + TaskAuctioneer + ChangeManager +\n * TaskDAG). When true (the default), the TUI boot wires the coordinator\n * lazily on the first Director spawn. When false, the coordinator is\n * never constructed and the `/coordinator` slash command reports it\n * unavailable — reducing the coordination domain's runtime surface for\n * users who only use the simpler Director/Fleet path.\n */\n autonomousCoordination?: boolean | undefined;\n /**\n * Allow tools to read/write paths outside the project root directory.\n * When true (default), tools can access any path on the filesystem.\n * When false, tools are restricted to the project root directory.\n */\n allowOutsideProjectRoot?: boolean | undefined;\n /**\n * Auto-bootstrap the mailbox HTTP bridge from any WrongStack surface\n * (REPL/TUI/WebUI/eternal). When 'auto' (the default), the first\n * surface to come up for a given project joins or spawns the bridge\n * so external agents can connect without the user running\n * `wstack mailbox serve` themselves. 'off' disables this — operators\n * must start the bridge explicitly (e.g. via the `/mailbox-serve`\n * slash command or the standalone `wstack mailbox serve` subcommand).\n * The per-project lock + token-persistence model means a second\n * surface on the same project joins the first's bridge rather than\n * spawning a duplicate.\n */\n mailboxBridge?: 'auto' | 'off' | undefined;\n}\n\nexport interface AutonomyConfig {\n /** Default autonomy mode at startup. Default: \"off\". */\n defaultMode?: 'off' | 'suggest' | 'auto' | undefined;\n /** ms to wait before auto-proceeding in 'auto' mode. Default: 45000. */\n autoProceedDelayMs?: number | undefined;\n /** Maximum consecutive auto-proceed turns before pausing. 0 = unlimited. Default: 50. */\n autoProceedMaxIterations?: number | undefined;\n /** Template used for YOLO+auto suggestions. Must include {{suggestion}}. */\n autonomyNextPrompt?: string | undefined;\n /** Animate the terminal/window title while the agent is active. Default: true. */\n terminalTitleAnimation?: boolean | undefined;\n /** Persisted YOLO preference mirrored into top-level config.yolo at runtime. Default: false. */\n yolo?: boolean | undefined;\n /** Stream fleet/subagent output into the main TUI chat. Default: true. */\n streamFleet?: boolean | undefined;\n /** Ring terminal bell when an agent run completes. Default: false. */\n chime?: boolean | undefined;\n /** Ask for confirmation before interrupt/exit. Default: true. */\n confirmExit?: boolean | undefined;\n /** Terminal mouse tracking preference. Default: false. */\n mouseMode?: boolean | undefined;\n /** Enable prompt refinement before sending. Default: true. */\n enhance?: boolean | undefined;\n /** Prompt-refinement preview countdown in ms. Default: 60000. */\n enhanceDelayMs?: number | undefined;\n /** Prompt-refinement language mode. Default: \"original\". */\n enhanceLanguage?: 'original' | 'english' | undefined;\n /** TUI statusline density. Default: \"detailed\". */\n statuslineMode?: 'minimum' | 'detailed' | undefined;\n /** Single short word shown in the TUI rainbow working-state chip. Default: \"thinking\". */\n thinkingWord?: string | undefined;\n}\n\n/**\n * Automatic codebase symbol-index maintenance. Keeps the `codebase-search`\n * index (SQLite, `~/.wrongstack/projects/<hash>/codebase-index/index.db`) fresh\n * without the user having to call `codebase-index` by hand.\n */\nexport interface IndexingConfig {\n /** Run a blocking incremental index at session start (with a visible summary). Default: true. */\n onSessionStart: boolean;\n /** Reindex files the agent writes/edits via tools, in the background. Default: true. */\n onEdit: boolean;\n /** Watch the project root for external editor changes and reindex them. Default: true. */\n watchExternal: boolean;\n /** Debounce window (ms) coalescing rapid edits to the same file. Default: 400. */\n debounceMs: number;\n /**\n * Watchdog timeout (ms) for a full index run. A run exceeding this is\n * aborted (so it can never wedge the indexing mutex or freeze the terminal)\n * and counts toward the indexing circuit breaker. Default: 120000.\n */\n indexTimeoutMs?: number | undefined;\n}\n\n/**\n * Saved launch preferences — restored on next boot so the pre-launch prompt\n * can offer a one-line \"Continue with last settings? [Y/n]\" instead of\n * re-asking every question from scratch.\n */\nexport interface LaunchConfig {\n /** Interactive mode: 'tui' (Ink TUI) or 'repl' (readline REPL). */\n mode?: 'tui' | 'repl' | undefined;\n /** Start with Director mode on (fleet manifest + multi-agent orchestration). */\n director?: boolean | undefined;\n /**\n * Launch-time autonomy mode (binary choice from pre-launch prompt).\n * 'off' = stops after each turn; 'auto' = self-driving.\n * Distinct from `AutonomyConfig.defaultMode` which also supports 'suggest'.\n */\n autonomy?: 'off' | 'auto' | undefined;\n}\n\n/**\n * Controls how much detail is persisted to the per-session JSONL log\n * (`~/.wrongstack/projects/<hash>/sessions/<date>/sess_<ULID>.jsonl`).\n */\nexport interface SessionLoggingConfig {\n /**\n * How much detail to write to the persistent session log.\n *\n * - \"minimal\" → Only events required for resume/rewind/recovery\n * - \"standard\" → (default) + high-value lightweight audit events\n * (compaction, tool timing, retries, errors, etc.)\n * - \"full\" → Also persist full request payloads (very large).\n * Consider enabling a separate replay log instead.\n */\n auditLevel?: 'minimal' | 'standard' | 'full' | undefined;\n\n /**\n * Sampling configuration for high-volume events (especially relevant at\n * `auditLevel: \"full\"`).\n */\n sampling?: {\n /** Controls sampling of `tool_progress` events. */\n toolProgress?: {\n /**\n * Sample rate for noisy progress events (`log`, `partial_output`).\n * - 1 = no sampling (every message is logged)\n * - 8 = default (first message + every 8th)\n */\n sampleRate?: number | undefined;\n };\n };\n}\n\nexport type SyncCategory = 'settings' | 'skills' | 'prompts' | 'memory' | 'history';\n\nexport interface SyncConfig {\n enabled: boolean;\n repo: string;\n /** GitHub token (fine-grained PAT). Encrypted at rest via SecretVault. */\n githubToken: string;\n categories: SyncCategory[];\n lastSyncedAt?: string | undefined;\n}\n\n/**\n * Per-model capability overrides the user can define in their config.\n * Used to add models not in the models.dev catalog, or override catalog\n * facts when the real backend differs (e.g. local Ollama models, proxies).\n */\nexport interface CustomModelDefinition {\n /** Provider this model belongs to. Defaults to the owning ProviderConfig. */\n provider?: string | undefined;\n /** Optional display name. */\n name?: string | undefined;\n /** Capability overrides — only specified fields are overlaid. */\n capabilities?: Partial<Capabilities> | undefined;\n /**\n * Max output tokens. If not specified, the provider family default\n * or catalog entry is used.\n */\n maxOutput?: number | undefined;\n}\n\nexport interface Config {\n version: 1;\n provider: string;\n model: string;\n apiKey?: string | undefined;\n baseUrl?: string | undefined;\n /**\n * Maximum number of subagent tasks the fleet coordinator dispatches\n * simultaneously. Extra tasks queue until a slot frees. Default: 4.\n * Overridden by WRONGSTACK_MAX_CONCURRENT env var and --max-concurrent\n * CLI flag. Change at runtime with /fleet concurrency <n>.\n */\n maxConcurrent?: number | undefined;\n providers?: Record<string, ProviderConfig>;\n /**\n * Top-level custom models (maps modelId → definition). Merged with\n * per-provider `customModels` at resolution time. The key is the\n * model id — not a fully qualified name. When the same model id\n * appears in both places, the top-level one wins.\n */\n models?: Record<string, CustomModelDefinition>;\n /**\n * Per-task model matrix. Keys are catalog roles (e.g. \"security-scanner\"),\n * phase names (e.g. \"review\"), or the `*` default. Resolution precedence at\n * subagent spawn: exact role → the role's phase → `*` → leader model. Set via\n * the `/setmodel` slash command; persisted to ~/.wrongstack/config.json.\n */\n modelMatrix?: Record<string, ModelMatrixEntry>;\n /**\n * User-curated model references shown/prioritized by model commands and used\n * by smart fallback derivation. Entries are `model`, `provider/model`, or\n * `provider model`.\n */\n favoriteModels?: string[] | undefined;\n /**\n * When true, auto-derived fallback chains are restricted to `favoriteModels`.\n * Explicit fallback profiles/chains are always honored as written.\n */\n favoriteModelsOnly?: boolean | undefined;\n context: ContextConfig;\n tools: ToolsConfig;\n mcpServers?: Record<string, MCPServerConfig>;\n /**\n * Per-agent ACP invocation overrides, keyed by catalog agent id\n * (`claude-code`, `codex-cli`, `gemini-cli`, …). Lets a user correct an\n * agent's ACP entry command — e.g. point `claude-code` at the right\n * adapter — without a code change. Consumed by `/acp`, `/ensemble`, and\n * `wstack acp`. SECURITY: this is an arbitrary-command exec surface, so it\n * is in the in-project config DENY list — only honoured from the user's\n * `~/.wrongstack/config.json`, never from a repo-committed config.\n */\n acp?: {\n agents?: Record<\n string,\n { command: string; args?: string[]; env?: Record<string, string> }\n >;\n };\n /**\n * Ordered list of fallback model references tried, in order, when the\n * primary model is overloaded (HTTP 429/529/5xx) and its own retries are\n * exhausted. Each entry is a model reference: a bare model id (same\n * provider), `provider/model`, or `provider model`. The primary is always\n * re-tried first at the start of every user turn. See `createFallbackModelExtension`.\n */\n fallbackModels?: string[] | undefined;\n /**\n * Named fallback chains. A profile's first entry can be used as a primary\n * model by `/setmodel`, while the whole ordered list is used for failover.\n */\n fallbackProfiles?: Record<string, string[]> | undefined;\n /**\n * When `true` (the default) and `fallbackModels` is empty, a fallback chain\n * is derived automatically from the other keyed providers/models so 429s\n * recover out of the box. Set `false` to disable the smart default and only\n * use an explicit `fallbackModels` list. Toggle via `/fallback auto on|off`.\n */\n fallbackAuto?: boolean | undefined;\n /**\n * Lifecycle shell hooks, keyed by event. Each command receives the hook\n * `HookInput` JSON on stdin; a JSON `HookOutcome` on stdout (and exit code 2\n * = block) steers the agent. In-process hooks are registered separately via\n * the plugin API. Disabled entirely under `--bare` / `--no-hooks`.\n */\n hooks?: Partial<Record<HookEvent, ShellHook[]>>;\n plugins?: (string | PluginConfig)[] | undefined;\n log: LogConfig;\n features: FeaturesConfig;\n yolo?: boolean | undefined;\n /** When true, show lightweight LLM-predicted next steps after each turn (/next). */\n nextPrediction?: boolean | undefined;\n cwd?: string | undefined;\n /** Autonomy mode configuration (auto-proceed delay, etc.). */\n autonomy?: AutonomyConfig | undefined;\n /** Show rotating launch hints on startup. Default: true. Set to false to suppress. */\n hints?: boolean | undefined;\n /** Raw SSE stream debugging — hex-dump every byte received from providers to stderr. */\n debugStream?: boolean | undefined;\n /**\n * Where settings are persisted. 'global' → ~/.wrongstack/config.json\n * (default). 'project' → <project>/.wrongstack/config.json.\n * When 'project', safe settings are saved per-project.\n */\n configScope?: 'global' | 'project' | undefined;\n /** Automatic codebase symbol-index maintenance (session-start + live updates). */\n indexing?: IndexingConfig | undefined;\n /**\n * Process circuit-breaker protection (gates `bash`/`exec` on repeated\n * failures). Default off — toggle with `/settings breaker on|off`.\n */\n circuitBreaker?: CircuitBreakerRuntimeConfig | undefined;\n /**\n * Adaptive concurrency controller — automatically adjusts `maxConcurrent` based on\n * rate-limit (429) errors. On 429: decreases concurrency. On sustained success:\n * gradually increases concurrency back up. Default off.\n */\n adaptiveConcurrency?: AdaptiveConcurrencyConfig | undefined;\n /** Saved launch preferences — restored on next boot for one-line confirmation. */\n launch?: LaunchConfig | undefined;\n\n /**\n * Session logging & audit configuration.\n * Controls what gets written to the persistent JSONL transcript.\n */\n session?: SessionLoggingConfig | undefined;\n /**\n * Runtime reasoning / cache controls applied to every provider request\n * (REPL/TUI/WebUI). Mapped into `Request.reasoning` and `Request.cache` by a\n * single request-pipeline middleware, gated by the active model's\n * capabilities. See `ModelRuntimeConfig`.\n */\n modelRuntime?: ModelRuntimeConfig | undefined;\n /** HQ client publishing settings, used by CLI/REPL/TUI/WebUI consistently. */\n hq?: HqClientConfig | undefined;\n /**\n * Cloud sync configuration. Stored separately in sync.json to avoid\n * accidentally committing the GitHub token to project configs.\n */\n sync?: SyncConfig | undefined;\n /**\n * Per-plugin namespaced config sections. Each plugin reads its own\n * subtree via `ConfigStore.getExtension(pluginName)`. Plugins should\n * declare a `configSchema` so the loader validates this section\n * automatically before `setup()` runs.\n *\n * Example:\n * extensions: {\n * 'wstack-auth': { tokenUrl: 'https://...', refreshBefore: 300 },\n * 'wstack-metrics': { sink: 'prometheus', port: 9090 },\n * }\n */\n extensions?: Record<string, Record<string, unknown>>;\n}\n\nexport interface ConfigLoader {\n load(opts?: { cliFlags?: Partial<Config> | undefined; cwd?: string | undefined }): Promise<Config>;\n /** Load and decrypt the sync config from ~/.wrongstack/sync.json. */\n loadSyncConfig(): Promise<SyncConfig | null>;\n /** Persist sync config to ~/.wrongstack/sync.json with encrypted token. */\n persistSyncConfig(cfg: SyncConfig): Promise<void>;\n}\n\n/**\n * Subscribable view over Config. Plugins and CLI subsystems use this instead\n * of holding a frozen Config reference, so they can react to runtime updates\n * (e.g. `/model` switching the active provider, secrets rotation, dynamic\n * extension reload).\n *\n * The store enforces immutability — `get()` always returns a frozen object.\n * Updates happen through `update(partial)`, which produces a new Config\n * (structurally cloned, then frozen) and notifies watchers.\n */\nexport interface ConfigStore {\n get(): Readonly<Config>;\n /**\n * Get a typed top-level section. Convenience for consumers that only\n * care about one slice (e.g. `tools` or `context`).\n */\n getSection<K extends keyof Config>(key: K): Readonly<Config[K]>;\n /**\n * Return the extension namespace for `pluginName`, or an empty record\n * when none is configured. The returned object is frozen.\n */\n getExtension(pluginName: string): Readonly<Record<string, unknown>>;\n /**\n * Apply a partial update. Returns the new Config. Watchers are notified\n * synchronously after the update completes. Throws if the result fails\n * any registered invariants (currently: version must stay 1).\n */\n update(partial: Partial<Config>): Readonly<Config>;\n /** Subscribe to changes. Returns an unsubscribe function. */\n watch(cb: (next: Readonly<Config>, prev: Readonly<Config>) => void): () => void;\n}\n","/**\n * Shared configuration constants used across execution, storage, CLI, and WebUI.\n * Centralized here to avoid cross-domain import cycles.\n */\n\n/** Default tools config — mirrors values baked into BEHAVIOR_DEFAULTS. */\nexport const DEFAULT_TOOLS_CONFIG = Object.freeze({\n defaultExecutionStrategy: 'smart',\n maxIterations: 100,\n iterationTimeoutMs: 300_000,\n sessionTimeoutMs: 1_800_000,\n perIterationOutputCapBytes: 100_000,\n descriptionMode: Object.freeze({}) as Record<string, 'extend' | 'simple' | undefined>,\n disabledTools: Object.freeze([]) as readonly string[],\n autoExtendLimit: true,\n restrictToProjectRoot: false,\n});\n\n/** Default context config — mirrors BEHAVIOR_DEFAULTS.context. */\nexport const DEFAULT_CONTEXT_CONFIG = Object.freeze({\n preserveK: 10,\n eliseThreshold: 2000,\n});\n\n/** Default autonomy config — auto-proceed delay etc. */\nexport const DEFAULT_AUTONOMY_CONFIG = Object.freeze({\n autoProceedDelayMs: 45_000,\n});\n\n/**\n * Default process circuit-breaker config. Protection is OFF by default — the\n * breaker only gates `bash`/`exec` once the user opts in via `/settings breaker on`.\n * The auto kill/reset delay is only consulted when protection is enabled.\n */\nexport const DEFAULT_CIRCUIT_BREAKER_CONFIG = Object.freeze({\n enabled: false,\n autoKillResetMs: 60_000,\n});\n\n/** Default session logging / audit configuration. */\nexport const DEFAULT_SESSION_LOGGING_CONFIG = Object.freeze({\n auditLevel: 'standard' as const,\n sampling: {\n toolProgress: {\n sampleRate: 8,\n },\n },\n});\n\n/** Default retention window for local session pruning. */\nexport const DEFAULT_SESSION_PRUNE_DAYS = 30;\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { decryptConfigSecrets } from '../security/secret-vault.js';\nimport { atomicWrite, withFileLock } from '../utils/atomic-write.js';\nimport { toErrorMessage } from '../utils/error.js';\nimport {\n DEFAULT_CONTEXT_WINDOW_MODE_ID,\n isContextWindowModeId,\n listContextWindowModes,\n} from '../types/context-window.js';\nimport {\n DEFAULT_TUI_THINKING_WORD,\n type Config,\n type ConfigLoader,\n type SyncConfig,\n} from '../types/config.js';\nimport type { SecretVault } from '../types/secret-vault.js';\nimport { ConfigError, ERROR_CODES } from '../types/errors.js';\nimport { safeParse } from '../utils/safe-json.js';\nimport { deepMerge as deepMergeCore, type DeepMergeOptions } from '../utils/deep-merge.js';\nimport type { WstackPaths } from '../utils/wstack-paths.js';\nimport {\n DEFAULT_AUTONOMY_CONFIG,\n DEFAULT_CIRCUIT_BREAKER_CONFIG,\n DEFAULT_TOOLS_CONFIG,\n DEFAULT_CONTEXT_CONFIG,\n DEFAULT_SESSION_LOGGING_CONFIG,\n} from '../types/default-config.js';\nimport type { EventBus } from '../kernel/events.js';\n\n/**\n * Surface the OS error code (EACCES, ENOSPC, …) alongside the message in\n * storage.* event payloads. Codes are stable and locale-independent, so\n * they are what dashboards and alerts key on; the message is supplementary.\n */\nfunction storageErrorString(err: unknown): string {\n if (err instanceof Error) {\n const code = (err as NodeJS.ErrnoException).code;\n return code ? `${code}: ${err.message}` : err.message;\n }\n /* v8 ignore next -- defensive: callers only pass fs Error instances */\n return String(err);\n}\n\n/**\n * Defaults express *behavior*, not identity. Provider and model are NOT\n * hardcoded — they must be resolved at runtime from config + env + the\n * ModelsRegistry. A bare Config returned by this loader will throw when\n * the agent tries to construct a provider, with a message that points\n * users at `wstack init`.\n */\nconst BEHAVIOR_DEFAULTS: Omit<Config, 'provider' | 'model'> = {\n version: 1,\n context: {\n mode: DEFAULT_CONTEXT_WINDOW_MODE_ID,\n warnThreshold: 0.6,\n softThreshold: 0.75,\n hardThreshold: 0.9,\n autoCompact: true,\n preserveK: DEFAULT_CONTEXT_CONFIG.preserveK,\n eliseThreshold: DEFAULT_CONTEXT_CONFIG.eliseThreshold,\n strategy: 'hybrid',\n },\n tools: {\n defaultExecutionStrategy: DEFAULT_TOOLS_CONFIG.defaultExecutionStrategy,\n maxIterations: DEFAULT_TOOLS_CONFIG.maxIterations,\n iterationTimeoutMs: DEFAULT_TOOLS_CONFIG.iterationTimeoutMs,\n sessionTimeoutMs: DEFAULT_TOOLS_CONFIG.sessionTimeoutMs,\n perIterationOutputCapBytes: DEFAULT_TOOLS_CONFIG.perIterationOutputCapBytes,\n descriptionMode: DEFAULT_TOOLS_CONFIG.descriptionMode,\n disabledTools: DEFAULT_TOOLS_CONFIG.disabledTools as string[],\n autoExtendLimit: DEFAULT_TOOLS_CONFIG.autoExtendLimit,\n restrictToProjectRoot: DEFAULT_TOOLS_CONFIG.restrictToProjectRoot,\n },\n log: { level: 'info' },\n features: {\n mcp: true,\n plugins: true,\n memory: true,\n modelsRegistry: true,\n skills: true,\n prompts: true,\n tokenSavingMode: 'off',\n allowOutsideProjectRoot: true,\n },\n mcpServers: {},\n fallbackAuto: true,\n maxConcurrent: 4,\n yolo: false,\n nextPrediction: false,\n hints: true,\n debugStream: false,\n configScope: 'global',\n indexing: {\n onSessionStart: true,\n onEdit: true,\n watchExternal: true,\n debounceMs: 400,\n },\n session: { ...DEFAULT_SESSION_LOGGING_CONFIG },\n autonomy: {\n defaultMode: 'off',\n autoProceedDelayMs: DEFAULT_AUTONOMY_CONFIG.autoProceedDelayMs,\n autoProceedMaxIterations: 50,\n autonomyNextPrompt: 'auto {{suggestion}}',\n terminalTitleAnimation: true,\n yolo: false,\n streamFleet: true,\n chime: false,\n confirmExit: true,\n mouseMode: false,\n enhance: true,\n enhanceDelayMs: 60_000,\n enhanceLanguage: 'original',\n statuslineMode: 'detailed',\n thinkingWord: DEFAULT_TUI_THINKING_WORD,\n },\n circuitBreaker: { ...DEFAULT_CIRCUIT_BREAKER_CONFIG },\n modelRuntime: {\n // `effort` is intentionally undefined by default. Leaving it unset lets\n // each model use its provider-recommended reasoning effort (or none at\n // all) instead of forcing an opinionated value that may be unsupported,\n // silently omitted, and surfaced as a per-request warning. Users who\n // want a specific effort can opt in via `/settings` or the WebUI panel.\n reasoning: { mode: 'auto' },\n cache: {},\n },\n};\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction cloneJsonValue<T>(value: T): T {\n return structuredClone(value);\n}\n\nfunction fillMissingDefaults(\n target: Record<string, unknown>,\n defaults: Record<string, unknown>,\n): { value: Record<string, unknown>; changed: boolean } {\n const value = cloneJsonValue(target);\n const changed = fillMissingDefaultsInPlace(value, defaults);\n return { value, changed };\n}\n\nfunction fillMissingDefaultsInPlace(\n target: Record<string, unknown>,\n defaults: Record<string, unknown>,\n): boolean {\n let changed = false;\n for (const [key, defaultValue] of Object.entries(defaults)) {\n if (!Object.prototype.hasOwnProperty.call(target, key)) {\n target[key] = cloneJsonValue(defaultValue);\n changed = true;\n continue;\n }\n const current = target[key];\n if (isPlainRecord(current) && isPlainRecord(defaultValue)) {\n changed = fillMissingDefaultsInPlace(current, defaultValue) || changed;\n }\n }\n return changed;\n}\n\n/** Parse a boolean-ish env var: \"0\"/\"false\"/\"no\"/\"off\" → false, anything else → true. */\nfunction envBool(v: string): boolean {\n return !/^(0|false|no|off)$/i.test(v.trim());\n}\n\nfunction envBoolOptional(v: string | undefined): boolean {\n return v !== undefined && envBool(v);\n}\n\nconst LOG_LEVELS = new Set<Config['log']['level']>(['error', 'warn', 'info', 'debug', 'trace']);\n\nfunction envLogLevel(v: string): Config['log']['level'] {\n return LOG_LEVELS.has(v as Config['log']['level']) ? (v as Config['log']['level']) : 'info';\n}\n\nconst ENV_MAP: Record<string, (cfg: PartialConfig, val: string) => void> = {\n WRONGSTACK_PROVIDER: (c, v) => {\n c.provider = v;\n if (c._envSource === undefined) c._envSource = new Set();\n c._envSource.add('provider');\n },\n WRONGSTACK_MODEL: (c, v) => {\n c.model = v;\n if (c._envSource === undefined) c._envSource = new Set();\n c._envSource.add('model');\n },\n WRONGSTACK_API_KEY: (c, v) => {\n c.apiKey = v;\n if (c._envSource === undefined) c._envSource = new Set();\n c._envSource.add('apiKey');\n },\n WRONGSTACK_BASE_URL: (c, v) => {\n c.baseUrl = v;\n if (c._envSource === undefined) c._envSource = new Set();\n c._envSource.add('baseUrl');\n },\n WRONGSTACK_LOG_LEVEL: (c, v) => {\n /* v8 ignore next -- defensive: config defaults always seed c.log before env handlers run */\n if (!c.log) c.log = { level: 'info' };\n c.log.level = envLogLevel(v);\n },\n WRONGSTACK_INDEX_ON_START: (c, v) => {\n c.indexing = { ...defaultIndexing, ...c.indexing, onSessionStart: envBool(v) };\n },\n WRONGSTACK_INDEX_ON_EDIT: (c, v) => {\n c.indexing = { ...defaultIndexing, ...c.indexing, onEdit: envBool(v) };\n },\n WRONGSTACK_INDEX_WATCH: (c, v) => {\n c.indexing = { ...defaultIndexing, ...c.indexing, watchExternal: envBool(v) };\n },\n};\n\nconst defaultIndexing = {\n onSessionStart: true,\n onEdit: true,\n watchExternal: true,\n debounceMs: 400,\n} as const;\n\ntype PartialConfig = Partial<Config> & {\n providers?: Record<\n string,\n { apiKey?: string | undefined; baseUrl?: string | undefined; type?: string | undefined }\n >;\n /** Fields that came from environment variables — must not be persisted. */\n _envSource?: Set<string> | undefined;\n};\n\n/**\n * Top-level config keys a REPO-COMMITTED `<project>/.wrongstack/config.json`\n * (the `inProjectConfig` layer) IS permitted to set. The in-project config\n * is attacker-controllable (it ships inside a cloned/pulled repository), so\n * every other field is denied by default. Anything not in this list is\n * stripped by `stripUnsafeInProjectFields()` before the merge.\n *\n * Why an allow-list and not a deny-list? A deny-list of N known-bad keys is\n * structurally incomplete: any new field added to `Config` without a matching\n * edit to the deny list silently becomes attacker-controllable, and the next\n * field that carries an executable string or a credential immediately turns\n * `<project>/.wrongstack/config.json` into an RCE / secret-exfiltration\n * vector the moment someone clones a malicious repo. An allow-list inverts\n * that — new fields are denied by default and must be explicitly added, so a\n * forgotten update is a safe default instead of an unsafe one.\n *\n * Each entry below is a benign user-preference that a project author may\n * legitimately want to pin for everyone who works in the repo:\n *\n * - `version` — schema marker required for any config merge.\n * - `model` — model id (also settable via env / CLI).\n * - `cwd` — working-directory hint (UX, not a permission).\n * - `context` — compaction thresholds, mode, preserveK.\n * - `tools` — iteration / timeouts / restrictToProjectRoot.\n * - `features` — feature toggles (display-only side effects).\n * - `autonomy` — autoProceedDelayMs, thinkingWord.\n * - `indexing` — onSessionStart / onEdit / debounceMs.\n * - `session` — audit level + sampling.\n * - `log` — log level.\n * - `launch` — saved launch prefs.\n * - `nextPrediction` — toggle `/next` after-turn suggestions.\n * - `hints` — toggle startup hints.\n * - `debugStream` — verbose SSE dump (noisy, not security-sensitive).\n * - `configScope` — where settings persist.\n * - `maxConcurrent` — fleet concurrency limit.\n * - `fallbackModels` — model references tried on 429/5xx.\n * - `fallbackProfiles` — named fallback chains.\n * - `favoriteModels` — model references preferred for display/routing.\n * - `favoriteModelsOnly` — restrict auto-derived chains to favorite models.\n * - `fallbackAuto` — derived-fallback toggle.\n * - `models` — custom model definitions (data, not code).\n * - `modelMatrix` — per-task model matrix.\n * - `circuitBreaker` — process circuit-breaker config (process gating).\n * - `adaptiveConcurrency` — adaptive concurrency controller.\n * - `modelRuntime` — runtime reasoning/cache/parameters.\n *\n * Fields deliberately NOT in the allow-list (and therefore always stripped\n * from `<project>/.wrongstack/config.json`) — see `KNOWN_DENIED_IN_PROJECT`\n * below for the reason each is unsafe.\n */\nconst IN_PROJECT_ALLOWED_KEYS: ReadonlySet<string> = new Set([\n 'version',\n 'model',\n 'cwd',\n 'context',\n 'tools',\n 'features',\n 'autonomy',\n 'indexing',\n 'session',\n 'log',\n 'launch',\n 'nextPrediction',\n 'hints',\n 'debugStream',\n 'configScope',\n 'maxConcurrent',\n 'fallbackModels',\n 'fallbackProfiles',\n 'favoriteModels',\n 'favoriteModelsOnly',\n 'fallbackAuto',\n 'models',\n 'modelMatrix',\n 'circuitBreaker',\n 'adaptiveConcurrency',\n 'modelRuntime',\n]);\n\n/**\n * Top-level config keys that exist on `Config` but MUST NEVER be settable\n * from a repo-committed `<project>/.wrongstack/config.json`. Each entry pairs\n * the field name with the specific way a malicious repo would abuse it. This\n * list is documentation + exhaustiveness checking; the runtime enforcement\n * is the *allow-list* above (anything not in the allow-list is stripped).\n *\n * - `provider` — set provider id to a custom / evil implementation →\n * intercepts every prompt and response.\n * - `apiKey` — overrides the user's API key with attacker-controlled\n * value, exfiltrating prompts to the attacker.\n * - `baseUrl` — redirects the provider endpoint so the user's real\n * decrypted API key is sent to the attacker's server.\n * - `providers` — per-provider `apiKey`/`baseUrl`/`oauthConfig` map,\n * same endpoint-redirect + secret-exfiltration vector.\n * - `mcpServers` — arbitrary `command` + `args` + `env` spawned at boot.\n * - `hooks` — shell command arrays attached to lifecycle events.\n * - `plugins` — npm package names dynamically loaded into the agent\n * process at boot.\n * - `sync` — carries `githubToken` (credential) and the repo\n * the user's sync push targets.\n * - `yolo` — flips off every permission confirmation prompt so a\n * malicious agent turn can run `bash` / `write` /\n * `install` without user approval.\n * - `extensions` — per-plugin namespaced config; the LSP plugin's\n * `servers[].command` is spawned on autoStart, and\n * arbitrary plugin configs can carry their own\n * credential / command fields → RCE / secret exposure.\n * - `hq` — carries `token` (HQ client credential) and `url`\n * (HQ endpoint, similar to `baseUrl`).\n */\nconst KNOWN_DENIED_IN_PROJECT: ReadonlyArray<{ key: string; reason: string }> = [\n { key: 'provider', reason: 'Provider id override; can intercept prompts/responses.' },\n { key: 'apiKey', reason: 'Overrides user API key; exfiltrates prompts.' },\n { key: 'baseUrl', reason: 'Redirects provider endpoint; leaks real API key.' },\n { key: 'providers', reason: 'Per-provider apiKey/baseUrl/oauthConfig; same redirect/exfil.' },\n { key: 'mcpServers', reason: 'Arbitrary command/args/env spawned at boot (RCE).' },\n { key: 'hooks', reason: 'Shell command arrays on lifecycle events (RCE).' },\n { key: 'plugins', reason: 'Dynamic npm package load at boot (RCE).' },\n { key: 'sync', reason: 'Carries githubToken credential and target repo.' },\n { key: 'yolo', reason: 'Disables all permission confirmation prompts.' },\n { key: 'extensions', reason: 'Per-plugin config can carry command/credential fields.' },\n { key: 'hq', reason: 'Carries HQ client token credential and endpoint URL.' },\n { key: 'acp', reason: 'Per-agent ACP command/args/env override → arbitrary command exec (RCE).' },\n];\n\n/**\n * Every top-level key that exists on the `Config` interface. This is the\n * *ground truth* used by `assertInProjectAllowListComplete()` to detect when\n * a new field has been added to `Config` without a corresponding decision\n * about whether it is safe for an attacker-controllable source to set it.\n *\n * Each entry must appear in EXACTLY ONE of:\n * - `IN_PROJECT_ALLOWED_KEYS` — explicitly safe for in-project config\n * - `KNOWN_DENIED_IN_PROJECT` — explicitly documented as unsafe\n *\n * The drift-check function below throws at runtime / test time when this\n * invariant is violated, so a forgotten update fails loudly instead of\n * silently widening the attack surface.\n */\nconst KNOWN_CONFIG_TOP_LEVEL_KEYS: ReadonlySet<string> = new Set([\n 'version',\n 'provider',\n 'model',\n 'apiKey',\n 'baseUrl',\n 'maxConcurrent',\n 'providers',\n 'models',\n 'modelMatrix',\n 'context',\n 'tools',\n 'mcpServers',\n 'fallbackModels',\n 'fallbackProfiles',\n 'favoriteModels',\n 'favoriteModelsOnly',\n 'fallbackAuto',\n 'hooks',\n 'plugins',\n 'log',\n 'features',\n 'yolo',\n 'nextPrediction',\n 'cwd',\n 'autonomy',\n 'hints',\n 'debugStream',\n 'configScope',\n 'indexing',\n 'circuitBreaker',\n 'adaptiveConcurrency',\n 'launch',\n 'session',\n 'modelRuntime',\n 'hq',\n 'sync',\n 'extensions',\n 'acp',\n]);\n\n/**\n * Assert that the allow-list and deny-list together cover every top-level\n * field of `Config`. Throws on drift so the failure is loud at test time and\n * at first boot, not a silent widening of the attack surface. Exported so\n * tests (and any consumer building tooling on top of this) can call it\n * explicitly; `stripUnsafeInProjectFields()` also calls it lazily on its\n * first invocation so the guarantee is structural, not test-only.\n *\n * The check is two-sided:\n * 1. Every key in `KNOWN_CONFIG_TOP_LEVEL_KEYS` is either allowed or\n * explicitly documented as denied (catches: \"added a new field but\n * forgot to decide\").\n * 2. Every entry in `KNOWN_DENIED_IN_PROJECT` actually exists on Config\n * (catches: \"left a stale denied-field entry behind after a rename\").\n * 3. The two lists are disjoint (catches: \"put the same field in both\n * lists; allow-list silently wins and the deny docs lie\").\n */\nexport function assertInProjectAllowListComplete(): void {\n const missingFromBoth: string[] = [];\n for (const key of KNOWN_CONFIG_TOP_LEVEL_KEYS) {\n if (IN_PROJECT_ALLOWED_KEYS.has(key)) continue;\n const denied = KNOWN_DENIED_IN_PROJECT.find((d) => d.key === key);\n if (!denied) missingFromBoth.push(key);\n }\n const staleDenials = KNOWN_DENIED_IN_PROJECT\n .filter((d) => !KNOWN_CONFIG_TOP_LEVEL_KEYS.has(d.key))\n .map((d) => d.key);\n const duplicate = KNOWN_DENIED_IN_PROJECT\n .filter((d) => IN_PROJECT_ALLOWED_KEYS.has(d.key))\n .map((d) => d.key);\n\n const problems: string[] = [];\n if (missingFromBoth.length > 0) {\n problems.push(\n `new Config field(s) not classified as allowed or denied for in-project config: ` +\n missingFromBoth.join(', ') +\n '. Add each to IN_PROJECT_ALLOWED_KEYS (if safe) or KNOWN_DENIED_IN_PROJECT (with a reason).',\n );\n }\n if (staleDenials.length > 0) {\n problems.push(\n `KNOWN_DENIED_IN_PROJECT references keys that no longer exist on Config: ` +\n staleDenials.join(', ') +\n '. Remove them or restore the field on Config.',\n );\n }\n if (duplicate.length > 0) {\n problems.push(\n `field(s) appear in BOTH IN_PROJECT_ALLOWED_KEYS and KNOWN_DENIED_IN_PROJECT: ` +\n duplicate.join(', ') +\n '. The allow-list wins at runtime; remove from one of the two.',\n );\n }\n if (problems.length > 0) {\n throw new Error(\n `stripUnsafeInProjectFields drift check failed:\\n - ${problems.join('\\n - ')}`,\n );\n }\n}\n\nlet driftChecked = false;\n\n/**\n * Remove forbidden top-level keys from a repo-committed in-project config\n * before it is merged. Returns a new object; the original is not mutated.\n * Emits a warning (and a `config.read` failure-style event) naming the\n * stripped keys so the behavior is observable rather than silent.\n *\n * On first invocation, runs `assertInProjectAllowListComplete()` to verify\n * the allow-list + deny-list together still cover every top-level field of\n * `Config`. The check is idempotent and the result is memoized so the cost\n * is paid at most once per process. The assertion throws on drift, which\n * surfaces the issue at boot in production and at first test invocation in\n * CI — both observable, never silent.\n */\nexport function stripUnsafeInProjectFields(\n inProject: PartialConfig,\n sourcePath: string,\n warn: (msg: string) => void = (msg) => console.warn(msg),\n): PartialConfig {\n if (!driftChecked) {\n assertInProjectAllowListComplete();\n driftChecked = true;\n }\n const stripped: string[] = [];\n const out: PartialConfig = {};\n for (const [k, v] of Object.entries(inProject)) {\n if (IN_PROJECT_ALLOWED_KEYS.has(k)) {\n (out as Record<string, unknown>)[k] = v;\n continue;\n }\n stripped.push(k);\n }\n\n // Nested strip: `tools` is allow-listed (it carries benign limits), but\n // `tools.exec.allow` EXPANDS what the agent may execute — never honor that\n // from an attacker-controllable repo config. Remove it while preserving\n // `tools.exec.deny` (removing commands only narrows, so it is always safe).\n // Clone the affected objects so the caller's input is not mutated.\n const outTools = (out as Record<string, unknown>)['tools'];\n if (outTools && typeof outTools === 'object') {\n const execCfg = (outTools as Record<string, unknown>)['exec'];\n if (execCfg && typeof execCfg === 'object' && 'allow' in (execCfg as Record<string, unknown>)) {\n const clonedExec = { ...(execCfg as Record<string, unknown>) };\n delete clonedExec['allow'];\n (out as Record<string, unknown>)['tools'] = {\n ...(outTools as Record<string, unknown>),\n exec: clonedExec,\n };\n stripped.push('tools.exec.allow');\n }\n }\n\n if (stripped.length > 0) {\n warn(\n JSON.stringify({\n level: 'warn',\n event: 'config.in_project_unsafe_fields_ignored',\n path: sourcePath,\n ignoredKeys: stripped,\n message:\n `Ignored ${stripped.length} field(s) from the repo-committed config ` +\n `\"${sourcePath}\": ${stripped.join(', ')}. ` +\n `Only a small allow-list of benign preferences (model, context, tools limits, ` +\n `features, …) may be set by <project>/.wrongstack/config.json. ` +\n `Everything else must live in your personal ~/.wrongstack/config.json.`,\n timestamp: new Date().toISOString(),\n }),\n );\n }\n return out;\n}\n\n/**\n * Compare two absolute filesystem paths for identity. Normalizes separators and\n * `.`/`..` segments via `path.resolve`, and folds case on win32 (and darwin,\n * whose default APFS/HFS+ volumes are case-insensitive) so the same file\n * reached through differently-cased drive/dir spellings still compares equal —\n * the same Windows path-casing hazard that bit the core token symbols.\n */\nfunction samePath(a: string, b: string): boolean {\n let ra = path.resolve(a);\n let rb = path.resolve(b);\n if (process.platform === 'win32' || process.platform === 'darwin') {\n ra = ra.toLowerCase();\n rb = rb.toLowerCase();\n }\n return ra === rb;\n}\n\n/**\n * Config-layer deep merge — delegates to the shared utility with\n * `arrayMode: 'concat-primitives'` and optional debug logging for\n * non-primitive array replacements.\n */\nfunction deepMerge<T>(base: T, patch: Partial<T>): T {\n const opts: DeepMergeOptions = { arrayMode: 'concat-primitives' };\n if (envBoolOptional(process.env.WRONGSTACK_DEBUG_CONFIG)) {\n opts.onNonPrimitiveArrayReplace = (key, existingLen, patchLen) => {\n console.warn(\n `[config] Non-primitive array for \"${key}\" replaced (global + local config merge). ` +\n `Global entries: ${existingLen}, local entries: ${patchLen}.`,\n );\n };\n }\n return deepMergeCore(base as Record<string, unknown>, patch as Record<string, unknown>, opts) as T;\n}\n\n/**\n * A single config source. Higher priority wins in merges.\n * Sources are applied in priority order (lowest first), so a source\n * with priority=10 overrides one with priority=1.\n */\nexport interface ConfigSource {\n /** Unique name for debugging and error messages. */\n name: string;\n /** Lower numbers merge first, higher numbers override lower. Default: 50. */\n priority?: number | undefined;\n /**\n * Read the raw config patch. Return an empty object if unavailable.\n * Errors are surfaced but do not abort loading — the source is skipped.\n */\n read(): Promise<Partial<Config>>;\n}\n\nexport interface ConfigLoaderOptions {\n paths: WstackPaths;\n strict?: boolean | undefined;\n vault?: SecretVault | undefined;\n /** Extra sources merged after the built-in layers. */\n sources?: ConfigSource[] | undefined;\n events?: EventBus;\n traceId?: string;\n}\n\ninterface MemoizedConfigSource {\n mtimeMs: number | null;\n value: PartialConfig;\n}\n\nexport class DefaultConfigLoader implements ConfigLoader {\n private readonly paths: WstackPaths;\n private readonly strict: boolean;\n private readonly vault: SecretVault | undefined;\n private readonly extraSources: ConfigSource[];\n private readonly events: EventBus | undefined;\n private readonly traceId: string | undefined;\n private readonly jsonCache = new Map<string, MemoizedConfigSource>();\n\n constructor(opts: ConfigLoaderOptions) {\n this.paths = opts.paths;\n this.strict = opts.strict ?? false;\n this.vault = opts.vault;\n this.extraSources = opts.sources ?? [];\n this.events = opts.events;\n this.traceId = opts.traceId;\n }\n\n async load(\n opts: { cliFlags?: Partial<Config> | undefined; cwd?: string | undefined } = {},\n ): Promise<Config> {\n let cfg: PartialConfig = { ...BEHAVIOR_DEFAULTS } as PartialConfig;\n\n // Materialize behavior/settings defaults into the trusted global config\n // before env vars or CLI flags are applied, so first boot creates a real\n // ~/.wrongstack/config.json without persisting ephemeral overrides.\n await this.ensureGlobalDefaults();\n\n // Layer 2, 3 & 3b: global + project-local + in-project config — read in parallel.\n // inProjectConfig (<project>/.wrongstack/config.json) merges AFTER\n // projectLocalConfig so it takes priority (user-intended > auto-cached).\n //\n // When the project root *is* the user's home (e.g. launching from `~`),\n // `<projectRoot>/.wrongstack/config.json` resolves to the very same file as\n // the trusted global config. Reading it again as the untrusted in-project\n // layer would strip `provider`/`apiKey`/… from the user's *own* file and\n // emit a spurious `config.in_project_unsafe_fields_ignored` warning — even\n // though the trusted global layer already merged those fields. Skip the\n // in-project read entirely on collision so trust isn't applied to a file\n // the user fully controls.\n const inProjectCollides =\n samePath(this.paths.inProjectConfig, this.paths.globalConfig) ||\n samePath(this.paths.inProjectConfig, this.paths.projectLocalConfig);\n const [global, local, inProject] = await Promise.all([\n this.readJson(this.paths.globalConfig),\n this.readJson(this.paths.projectLocalConfig),\n inProjectCollides\n ? Promise.resolve({} as PartialConfig)\n : this.readJson(this.paths.inProjectConfig),\n ]);\n cfg = deepMerge(cfg, global);\n cfg = deepMerge(cfg, local);\n // The in-project config is repo-committed and therefore attacker-\n // controllable. Strip credential/endpoint/code-execution fields before\n // merging so a malicious repo cannot redirect the provider endpoint\n // (API-key exfiltration) or auto-run an MCP server / hook (RCE) on launch.\n cfg = deepMerge(cfg, stripUnsafeInProjectFields(inProject, this.paths.inProjectConfig));\n\n // Layer 4: env vars\n for (const [key, fn] of Object.entries(ENV_MAP)) {\n const v = process.env[key];\n if (v) fn(cfg, v);\n }\n\n // Layer 5: extra sources — sorted by priority (lowest first).\n // When priorities tie, sort by name for deterministic order.\n const sorted = [...this.extraSources].sort((a, b) => {\n const pd = (a.priority ?? 50) - (b.priority ?? 50);\n if (pd !== 0) return pd;\n return a.name.localeCompare(b.name);\n });\n for (const src of sorted) {\n try {\n const patch = await src.read();\n if (patch && Object.keys(patch).length > 0) {\n cfg = deepMerge(cfg, patch);\n }\n } catch (err) {\n // Best-effort: skip failing sources so one bad source doesn't block boot.\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'config.source_load_failed',\n source: src.name,\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n }\n }\n\n // Layer 6: CLI flags\n if (opts.cliFlags) {\n cfg = deepMerge(cfg, opts.cliFlags);\n }\n\n // Decrypt apiKey-like fields if a vault is configured.\n if (this.vault) {\n cfg = decryptConfigSecrets(cfg, this.vault);\n }\n\n // Multi-key resolution: when a provider has `apiKeys[]` configured,\n // mirror the active entry into `apiKey` so downstream construction\n // code (provider registry, wire adapters) needs no changes. Honors\n // `activeKey` (by label), else falls back to the first entry. A\n // pre-existing `apiKey` set by env/CLI flags wins so an explicit\n // override still beats the saved list.\n if (cfg.providers) {\n for (const pcfg of Object.values(cfg.providers)) {\n if (!pcfg || typeof pcfg !== 'object') continue;\n const rawKeys = (pcfg as { apiKeys?: unknown | undefined }).apiKeys;\n if (!Array.isArray(rawKeys) || rawKeys.length === 0) continue;\n // Each apiKeys entry came from arbitrary JSON. Filter to entries\n // that actually have a string apiKey + label so a malformed array\n // (null entry, missing field) doesn't crash the .find / chosen.apiKey\n // path below.\n const keys = rawKeys.filter(\n (k): k is { label: string; apiKey: string } =>\n !!k &&\n typeof k === 'object' &&\n typeof (k as { label?: unknown | undefined }).label === 'string' &&\n typeof (k as { apiKey?: unknown | undefined }).apiKey === 'string',\n );\n if (keys.length === 0) continue;\n const existing = (pcfg as { apiKey?: string | undefined }).apiKey;\n if (existing && existing.length > 0) continue;\n const activeLabel = (pcfg as { activeKey?: string | undefined }).activeKey;\n const chosen = activeLabel\n ? (keys.find((k) => k.label === activeLabel) ?? keys[0])\n : keys[0];\n if (chosen?.apiKey) {\n (pcfg as { apiKey?: string | undefined }).apiKey = chosen.apiKey;\n }\n }\n }\n\n this.validateBehavior(cfg);\n if (this.strict) {\n this.validateIdentity(cfg);\n }\n // In strict mode, validateIdentity has confirmed provider/model are set;\n // it's safe to assert the full Config contract. In non-strict mode the\n // caller (e.g. early-boot wizard) accepts a Partial and constructs the\n // provider later, so we deliberately return without the cast.\n return Object.freeze(cfg) as Config;\n }\n\n private async ensureGlobalDefaults(): Promise<void> {\n const fp = this.paths.globalConfig;\n const t0 = Date.now();\n try {\n await withFileLock(fp, async () => {\n let parsed: Record<string, unknown>;\n try {\n const raw = await fs.readFile(fp, 'utf8');\n const result = safeParse<unknown>(raw);\n if (!result.ok || !isPlainRecord(result.value)) {\n // readJson() below owns the user-visible parse warning. Do not\n // overwrite a malformed config while trying to seed defaults.\n return;\n }\n parsed = result.value;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n this.events?.emit('storage.error', {\n sessionId: '~config~',\n store: 'config',\n filePath: fp,\n operation: 'ensure_defaults',\n outcome: 'failure',\n error: storageErrorString(err),\n recoverable: false,\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'config.defaults_read_failed',\n path: fp,\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n return;\n }\n parsed = {};\n }\n\n const { value, changed } = fillMissingDefaults(\n parsed,\n BEHAVIOR_DEFAULTS as Record<string, unknown>,\n );\n if (!changed) return;\n\n await atomicWrite(fp, JSON.stringify(value, null, 2), { mode: 0o600 });\n this.events?.emit('storage.write', {\n sessionId: '~config~',\n store: 'config',\n filePath: fp,\n operation: 'ensure_defaults',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n });\n } catch (err) {\n this.events?.emit('storage.error', {\n sessionId: '~config~',\n store: 'config',\n filePath: fp,\n operation: 'ensure_defaults',\n outcome: 'failure',\n error: storageErrorString(err),\n recoverable: false,\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'config.defaults_write_failed',\n path: fp,\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n }\n }\n\n /**\n * Persist a sync config to ~/.wrongstack/sync.json, with the token encrypted\n * by the vault (if provided). The file is isolated from the main config\n * hierarchy to prevent accidental commits.\n */\n async persistSyncConfig(cfg: SyncConfig): Promise<void> {\n let toWrite = { ...cfg };\n if (this.vault && toWrite.githubToken && !toWrite.githubToken.startsWith('enc:')) {\n // Re-encrypt if plaintext (e.g. came from in-memory configStore update\n // rather than direct /sync enable call). Idempotent for already-encrypted.\n toWrite = { ...toWrite, githubToken: this.vault.encrypt(toWrite.githubToken) };\n }\n const fp = this.paths.syncConfig;\n const t0 = Date.now();\n try {\n await atomicWrite(fp, JSON.stringify(toWrite, null, 2), { mode: 0o600 });\n this.events?.emit('storage.write', {\n sessionId: '~config~',\n store: 'config',\n filePath: fp,\n operation: 'persist_sync',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n } catch (err) {\n this.events?.emit('storage.error', {\n sessionId: '~config~',\n store: 'config',\n filePath: fp,\n operation: 'persist_sync',\n outcome: 'failure',\n error: storageErrorString(err),\n recoverable: false,\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n throw err;\n }\n }\n\n /**\n * Read ~/.wrongstack/sync.json (encrypted GitHub token storage) and decrypt\n * the token if a vault is available. Returns null if the file doesn't exist.\n * This is separate from main config loading because sync.json is intentionally\n * isolated — it should never be part of project-local or env-driven config.\n */\n async loadSyncConfig(): Promise<SyncConfig | null> {\n const fp = this.paths.syncConfig;\n const t0 = Date.now();\n try {\n const raw = await fs.readFile(fp, 'utf8');\n const parsed = safeParse<SyncConfig>(raw);\n if (!parsed.ok || !parsed.value) {\n this.events?.emit('storage.read', {\n sessionId: '~config~',\n store: 'config',\n filePath: fp,\n operation: 'load_sync',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'parse error or empty file',\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return null;\n }\n\n // Decrypt the token if vault is available (field name matches secret pattern)\n if (this.vault) {\n const decrypted = decryptConfigSecrets({ sync: parsed.value } as PartialConfig, this.vault);\n const result = (decrypted as { sync: SyncConfig }).sync ?? null;\n this.events?.emit('storage.read', {\n sessionId: '~config~',\n store: 'config',\n filePath: fp,\n operation: 'load_sync',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return result;\n }\n this.events?.emit('storage.read', {\n sessionId: '~config~',\n store: 'config',\n filePath: fp,\n operation: 'load_sync',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return parsed.value;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return null;\n // Non-ENOENT failures (EACCES, ENOSPC, etc.) — emit storage.read failure, then return null\n this.events?.emit('storage.read', {\n sessionId: '~config~',\n store: 'config',\n filePath: fp,\n operation: 'load_sync',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: storageErrorString(err),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'config.sync_load_failed',\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n return null;\n }\n }\n\n private async readJson(file: string): Promise<PartialConfig> {\n const t0 = Date.now();\n let mtimeMs: number | null = null;\n try {\n const stat = await fs.stat(file);\n mtimeMs = stat.mtimeMs;\n const cached = this.jsonCache.get(file);\n if (cached && cached.mtimeMs === mtimeMs) {\n return structuredClone(cached.value);\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n this.jsonCache.set(file, { mtimeMs: null, value: {} });\n return {};\n }\n this.events?.emit('storage.read', {\n sessionId: '~config~',\n store: 'config',\n filePath: file,\n operation: 'read_json',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: storageErrorString(err),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'config.read_failed',\n path: file,\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n return {};\n }\n\n let raw: string;\n try {\n raw = await fs.readFile(file, 'utf8');\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n this.events?.emit('storage.read', {\n sessionId: '~config~',\n store: 'config',\n filePath: file,\n operation: 'read_json',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: storageErrorString(err),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'config.read_failed',\n path: file,\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n }\n this.jsonCache.set(file, { mtimeMs: null, value: {} });\n return {};\n }\n const parsed = safeParse<PartialConfig>(raw);\n if (!parsed.ok || !parsed.value) {\n this.events?.emit('storage.read', {\n sessionId: '~config~',\n store: 'config',\n filePath: file,\n operation: 'read_json',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'parse error or empty file',\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'config.parse_failed',\n path: file,\n message: 'invalid JSON — falling back to defaults for this layer',\n timestamp: new Date().toISOString(),\n }));\n return {};\n }\n this.jsonCache.set(file, { mtimeMs, value: structuredClone(parsed.value) });\n return parsed.value;\n }\n\n private validateBehavior(cfg: PartialConfig): void {\n /* v8 ignore start -- defensive: config defaults always seed version:1 before validation */\n if (cfg.version === undefined) throw new ConfigError({\n message: 'Config: missing version field',\n code: ERROR_CODES.CONFIG_INVALID,\n context: { field: 'version' },\n });\n /* v8 ignore stop */\n if (cfg.version !== 1) throw new ConfigError({\n message: `Config: unsupported version ${cfg.version}`,\n code: ERROR_CODES.CONFIG_INVALID,\n context: { field: 'version', actual: cfg.version },\n });\n const c = cfg.context;\n if (!c) throw new ConfigError({\n message: 'Config: missing context section',\n code: ERROR_CODES.CONFIG_INVALID,\n context: { field: 'context' },\n });\n // A user-edited config.json can land strings here (\"0.6\") and slip past\n // truthiness checks; the `>=` comparison then coerces silently and the\n // threshold ordering check passes for nonsense values. Validate types\n // explicitly so misconfigs surface here, not as confusing failures deep\n // in the auto-compaction logic.\n const fields: Array<keyof typeof c> = ['warnThreshold', 'softThreshold', 'hardThreshold'];\n for (const f of fields) {\n const v = c[f];\n if (typeof v !== 'number' || !Number.isFinite(v)) {\n throw new ConfigError({\n message: `Config: context.${String(f)} must be a finite number (got ${typeof v})`,\n code: ERROR_CODES.CONFIG_INVALID,\n context: { field: `context.${String(f)}`, actualType: typeof v },\n });\n }\n }\n if (c.warnThreshold >= c.softThreshold || c.softThreshold >= c.hardThreshold) {\n throw new ConfigError({\n message: 'Config: context thresholds must satisfy warn < soft < hard',\n code: ERROR_CODES.CONFIG_INVALID,\n context: { warn: c.warnThreshold, soft: c.softThreshold, hard: c.hardThreshold },\n });\n }\n if (c.mode !== undefined && !isContextWindowModeId(c.mode)) {\n // An unknown mode (typo or value from an older/renamed scheme) should not\n // brick the CLI — unlike the numeric thresholds above there is a safe\n // default. Warn and fall back rather than throwing.\n const known = listContextWindowModes()\n .map((m) => m.id)\n .join(', ');\n console.warn(\n `[config] Ignoring unknown context.mode \"${c.mode}\" (expected one of: ${known}); ` +\n `falling back to \"${DEFAULT_CONTEXT_WINDOW_MODE_ID}\".`,\n );\n c.mode = DEFAULT_CONTEXT_WINDOW_MODE_ID;\n }\n }\n\n private validateIdentity(cfg: PartialConfig): void {\n if (!cfg.provider) {\n throw new ConfigError({\n message: 'Config: no provider configured. Run `wstack init` or set WRONGSTACK_PROVIDER.',\n code: ERROR_CODES.CONFIG_INVALID,\n context: { field: 'provider' },\n });\n }\n if (!cfg.model) {\n throw new ConfigError({\n message: 'Config: no model configured. Run `wstack init` or set WRONGSTACK_MODEL.',\n code: ERROR_CODES.CONFIG_INVALID,\n context: { field: 'model' },\n });\n }\n }\n}\n","/**\n * L2-D: Config version migration framework. Pure functions, decoupled\n * from disk/CLI — caller passes a parsed JSON object and gets back the\n * up-to-date `Config` shape (or a structured error explaining why\n * migration failed).\n *\n * Migrations are registered as `{ from, to, migrate }` triples and run\n * sequentially. Each migration is independently testable. Adding a new\n * version means appending one migration; existing user configs are\n * upgraded in place at load time.\n */\n\nexport interface MigrationContext {\n /**\n * Original on-disk version of the input. Migrations may use this to\n * decide between in-place patches and rewrites.\n */\n fromVersion: number;\n /**\n * Set when the migration writes back to disk. Callers persist the\n * migrated config when this is true so the user doesn't see the same\n * migration banner on every boot.\n */\n shouldPersist: boolean;\n}\n\nexport interface ConfigMigration {\n /** Version of the input this migration accepts. */\n from: number;\n /** Version of the output it produces. */\n to: number;\n /** Pure transform — no I/O. */\n migrate(input: Record<string, unknown>, ctx: MigrationContext): Record<string, unknown>;\n /** Optional human-readable description for migration logs / banners. */\n describe?: string | undefined;\n}\n\nexport interface MigrationResult {\n /** Final config (still typed as `unknown`-keyed — caller validates). */\n config: Record<string, unknown>;\n /** Ordered list of `from→to` versions that ran. */\n applied: string[];\n /** True when at least one migration produced changes worth persisting. */\n shouldPersist: boolean;\n}\n\nexport class ConfigMigrationError extends Error {\n readonly fromVersion: number;\n readonly targetVersion: number;\n readonly missingStep: number | null;\n\n constructor(opts: {\n message: string;\n fromVersion: number;\n targetVersion: number;\n missingStep: number | null;\n }) {\n super(opts.message);\n this.name = 'ConfigMigrationError';\n this.fromVersion = opts.fromVersion;\n this.targetVersion = opts.targetVersion;\n this.missingStep = opts.missingStep;\n }\n}\n\n/**\n * Run registered migrations until the input reaches `targetVersion`.\n *\n * Resolution rules:\n * 1. If `input.version === targetVersion`, no migrations run; `shouldPersist`\n * is false.\n * 2. Otherwise walk the migration chain from `input.version` upward,\n * picking the migration whose `from` matches the current version.\n * 3. Stop when `current.version === targetVersion`.\n * 4. If no migration matches at some point, throw `ConfigMigrationError`\n * with the missing step recorded for diagnostics.\n *\n * Migrations may be downward (e.g. for staged rollouts), but `targetVersion`\n * must be reachable strictly via the registered chain — there's no implicit\n * \"skip\" or transitive resolution.\n */\nexport function runConfigMigrations(\n input: Record<string, unknown>,\n targetVersion: number,\n migrations: readonly ConfigMigration[],\n): MigrationResult {\n const initial = typeof input['version'] === 'number' ? (input['version'] as number) : 1;\n let current: Record<string, unknown> = { ...input };\n let currentVersion = initial;\n const applied: string[] = [];\n let shouldPersist = false;\n\n let guard = 0;\n while (currentVersion !== targetVersion) {\n if (++guard > 100) {\n throw new ConfigMigrationError({\n message: `Config migration looped past 100 steps (from v${initial} toward v${targetVersion})`,\n fromVersion: initial,\n targetVersion,\n missingStep: currentVersion,\n });\n }\n const step = migrations.find((m) => m.from === currentVersion);\n if (!step) {\n throw new ConfigMigrationError({\n message: `No migration registered from config v${currentVersion} (target v${targetVersion}). Update the framework or revert the config file.`,\n fromVersion: initial,\n targetVersion,\n missingStep: currentVersion,\n });\n }\n const ctx: MigrationContext = { fromVersion: currentVersion, shouldPersist: false };\n const next = step.migrate(current, ctx);\n // Ensure the migration set the new version. Be tolerant: if it didn't,\n // patch it in so the chain doesn't infinite-loop on author oversight.\n if (typeof next['version'] !== 'number' || next['version'] !== step.to) {\n next['version'] = step.to;\n }\n current = next;\n currentVersion = step.to;\n applied.push(`v${step.from}→v${step.to}`);\n shouldPersist = shouldPersist || ctx.shouldPersist || step.from < step.to;\n }\n return { config: current, applied, shouldPersist };\n}\n\n/**\n * Default empty migration registry. Real migrations are appended as new\n * Config versions are introduced. Example (when v2 lands):\n *\n * export const CONFIG_MIGRATIONS: readonly ConfigMigration[] = [\n * {\n * from: 1, to: 2, describe: 'rename `apiKey` → `auth.apiKey`',\n * migrate(cfg) {\n * const apiKey = cfg.apiKey;\n * delete cfg.apiKey;\n * return { ...cfg, auth: { ...(cfg.auth ?? {}), apiKey } };\n * },\n * },\n * ];\n */\nexport const DEFAULT_CONFIG_MIGRATIONS: readonly ConfigMigration[] = [];\n","import * as fsp from 'node:fs/promises';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { SessionStore } from '../types/session.js';\nimport { ensureDir } from '../utils/atomic-write.js';\n\n/**\n * Per-project lockfile used for crash detection. The CLI writes one of\n * these alongside the session JSONLs (`<projectSessions>/active.json`)\n * when an interactive run starts, and deletes it on clean exit. If we\n * find one on the next launch whose owning PID is dead (or whose host\n * doesn't match), we know the previous run was killed mid-flight and\n * the session it was writing to is a recovery candidate.\n *\n * The lockfile is intentionally per-project (already isolated by\n * `wpaths.projectSessions`), so two TUIs in two different repos do not\n * fight each other.\n */\nexport interface RecoveryLockOptions {\n /** Directory the lockfile lives in. Usually `wpaths.projectSessions`. */\n dir: string;\n /** This process's PID. Default: `process.pid`. */\n pid?: number | undefined;\n /** Hostname recorded for the lock. Default: `os.hostname()`. */\n hostname?: string | undefined;\n /** Locks older than this are considered orphaned (disk wiped, etc.). Default 24h. */\n maxAgeMs?: number | undefined;\n /** Used to check whether the abandoned session was actually closed cleanly. */\n sessionStore?: SessionStore | undefined;\n /**\n * Override the PID-liveness probe. Default: `process.kill(pid, 0)` —\n * succeeds (or throws EPERM) when the PID is alive, throws ESRCH when\n * it is gone. Tests inject a deterministic stub.\n */\n isPidAlive?: (((pid: number) => boolean)) | undefined;\n}\n\nexport interface AbandonedSession {\n sessionId: string;\n pid: number;\n startedAt: string;\n /** Lockfile age in ms at the time of the check. */\n ageMs: number;\n /** Number of messages already on disk for this session. */\n messageCount: number;\n}\n\ninterface LockFile {\n v: 1;\n sessionId: string;\n pid: number;\n hostname: string;\n startedAt: string;\n}\n\nconst LOCK_FILE = 'active.json';\nconst DEFAULT_MAX_AGE_MS = 24 * 60 * 60 * 1000;\n\nexport class RecoveryLock {\n private readonly file: string;\n private readonly pid: number;\n private readonly hostname: string;\n private readonly maxAgeMs: number;\n private readonly sessionStore?: SessionStore | undefined;\n private readonly probe: (pid: number) => boolean;\n\n constructor(opts: RecoveryLockOptions) {\n this.file = path.join(opts.dir, LOCK_FILE);\n this.pid = opts.pid ?? process.pid;\n this.hostname = opts.hostname ?? os.hostname();\n this.maxAgeMs = opts.maxAgeMs ?? DEFAULT_MAX_AGE_MS;\n this.sessionStore = opts.sessionStore;\n this.probe = opts.isPidAlive ?? defaultIsPidAlive;\n }\n\n /**\n * Examine the lockfile and decide whether it represents an abandoned\n * session. Returns `null` if the file is missing, points to a live\n * instance, references a clean-closed session, is too old, or is\n * malformed. Otherwise returns enough detail to prompt the user.\n *\n * Important: this is a read-only check. We never delete an active\n * lock from here — if another wstack instance is alive, the caller\n * should bail or run with a fresh session instead.\n */\n async checkAbandoned(): Promise<AbandonedSession | null> {\n const lock = await this.readLock();\n if (!lock) return null;\n\n const ageMs = Date.now() - new Date(lock.startedAt).getTime();\n if (Number.isNaN(ageMs) || ageMs < 0) {\n // Clock skew or corrupted timestamp — treat as orphan.\n return null;\n }\n if (ageMs > this.maxAgeMs) return null;\n\n // PID liveness only meaningful on the same host. Different host\n // means we can't probe — assume abandoned (the other machine's\n // wstack can't be holding *our* sessions dir unless it was\n // shared via network mount, in which case the user is on their\n // own).\n if (lock.hostname === this.hostname && this.probe(lock.pid)) {\n // Another wstack on this box is actively writing here.\n return null;\n }\n\n let messageCount = 0;\n if (this.sessionStore) {\n try {\n const data = await this.sessionStore.load(lock.sessionId);\n // Closed means the LAST session_end is not followed by further\n // conversation activity. Legacy /save wrote mid-stream session_end\n // markers — `some()` would treat a session that crashed AFTER such a\n // marker as cleanly closed and silently skip recovery.\n const lastEnd = data.events.findLastIndex((e) => e.type === 'session_end');\n const closed =\n lastEnd >= 0 &&\n !data.events\n .slice(lastEnd + 1)\n .some(\n (e) =>\n e.type === 'user_input' ||\n e.type === 'llm_response' ||\n e.type === 'in_flight_start',\n );\n if (closed) return null;\n messageCount = data.messages.length;\n } catch {\n // Lock points to a session that doesn't exist on disk (deleted\n // out from under us). Nothing to recover.\n return null;\n }\n }\n\n return {\n sessionId: lock.sessionId,\n pid: lock.pid,\n startedAt: lock.startedAt,\n ageMs,\n messageCount,\n };\n }\n\n /**\n * Claim the lock for the given session. Uses exclusive-create (`O_EXCL`)\n * to detect whether another process acquired the lock between our\n * `checkAbandoned()` call and now. If the file already exists, it means\n * another process won the race and we throw instead of silently\n * overwriting their recovery record.\n *\n * The caller MUST have already called `checkAbandoned()` and handled its\n * null return before calling this.\n */\n async write(sessionId: string): Promise<void> {\n await ensureDir(path.dirname(this.file));\n const lock: LockFile = {\n v: 1,\n sessionId,\n pid: this.pid,\n hostname: this.hostname,\n startedAt: new Date().toISOString(),\n };\n // O_EXCL: atomic create — fails with EEXIST if another process wrote\n // the file between our checkAbandoned() and this write. This prevents\n // two processes that scanned the same stale lock from both believing\n // they hold it. The atomicWrite approach (temp+rename) would silently\n // replace on POSIX, hiding the race.\n try {\n await fsp.writeFile(this.file, JSON.stringify(lock), { flag: 'wx', mode: 0o600 });\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'EEXIST') {\n throw new Error(`Recovery lock already held by another process`);\n }\n /* v8 ignore next -- defensive: an unexpected (non-EEXIST) write failure is rethrown */\n throw err;\n }\n }\n\n /**\n * Release the lock. Idempotent — silently succeeds if the file is\n * already gone (e.g. someone else cleared it, or the directory was\n * wiped).\n */\n async clear(): Promise<void> {\n try {\n await fsp.unlink(this.file);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') return;\n /* v8 ignore next -- defensive: an unexpected (non-ENOENT) unlink failure is rethrown */\n throw err;\n }\n }\n\n private async readLock(): Promise<LockFile | null> {\n let raw: string;\n try {\n raw = await fsp.readFile(this.file, 'utf8');\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') return null;\n return null;\n }\n try {\n const parsed = JSON.parse(raw) as unknown;\n if (!isLockFile(parsed)) return null;\n return parsed;\n } catch {\n return null;\n }\n }\n}\n\nfunction isLockFile(v: unknown): v is LockFile {\n if (typeof v !== 'object' || v === null) return false;\n const o = v as Record<string, unknown>;\n return (\n o['v'] === 1 &&\n typeof o['sessionId'] === 'string' &&\n typeof o['pid'] === 'number' &&\n typeof o['hostname'] === 'string' &&\n typeof o['startedAt'] === 'string'\n );\n}\n\n/**\n * Probe whether a process is alive without sending it a real signal.\n *\n * Unix: `process.kill(pid, 0)` succeeds for our own processes, throws\n * EPERM for others (still alive, just not ours), and throws ESRCH\n * when the PID is gone.\n * Windows (Node 22+): same call returns true if the process exists,\n * throws otherwise.\n */\nfunction defaultIsPidAlive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid <= 0) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n /* v8 ignore next -- platform/permission-specific: EPERM means alive but owned by another user */\n if (code === 'EPERM') return true; // alive, but owned by someone else\n return false;\n }\n}\n","import * as fs from 'node:fs/promises';\nimport { expectDefined } from '../utils/expect-defined.js';\nimport type { ContentBlock } from '../types/blocks.js';\r\nimport type {\r\n DefaultSessionReaderOptions,\r\n SessionExportOptions,\r\n SessionQuery,\r\n SessionReader,\r\n SessionSearchHit,\r\n SessionSearchQuery,\r\n SessionSummaryLite,\r\n} from '../types/session-reader.js';\r\nimport { compileUserRegex } from '../utils/regex-guard.js';\nimport { sessionScopedPath } from '../utils/session-scoped-path.js';\nimport type { SessionData, SessionEvent, SessionMetadata, SessionStore } from '../types/session.js';\n\r\n/**\r\n * L2-A: read-only view over a `SessionStore` with query, replay, search,\r\n * and export helpers. Implemented on top of the public `SessionStore`\r\n * surface so any concrete store can be inspected without re-implementation.\r\n */\r\nexport class DefaultSessionReader implements SessionReader {\r\n private readonly store: SessionStore;\r\n private readonly eventCache = new Map<string, SessionData>();\r\n private readonly eventCacheMtimes = new Map<string, number>();\r\n private static readonly EVENT_CACHE_MAX_ENTRIES = 32;\r\n\r\n constructor(opts: DefaultSessionReaderOptions) {\r\n this.store = opts.store;\r\n }\r\n\r\n private async loadCachedSessionData(sessionId: string): Promise<SessionData> {\r\n const storeWithPath = this.store as SessionStore & {\r\n dir?: string | undefined;\r\n clearLoadCache?: ((sessionId?: string | undefined) => void) | undefined;\r\n };\r\n const rootDir = storeWithPath.dir;\r\n if (!rootDir) {\r\n return await this.store.load(sessionId);\r\n }\r\n const sessionPath = sessionScopedPath(rootDir, sessionId, '.jsonl');\n let mtimeMs: number | null = null;\r\n try {\r\n const stat = await fs.stat(sessionPath);\r\n mtimeMs = stat.mtimeMs;\r\n } catch {\r\n this.eventCache.delete(sessionId);\r\n this.eventCacheMtimes.delete(sessionId);\r\n return await this.store.load(sessionId);\r\n }\r\n\r\n const cachedMtime = this.eventCacheMtimes.get(sessionId);\r\n const cachedData = this.eventCache.get(sessionId);\r\n if (cachedData && cachedMtime === mtimeMs) {\r\n this.eventCache.delete(sessionId);\r\n this.eventCacheMtimes.delete(sessionId);\r\n this.eventCache.set(sessionId, cachedData);\r\n this.eventCacheMtimes.set(sessionId, mtimeMs);\r\n return cachedData;\r\n }\r\n\r\n const data = await this.store.load(sessionId);\r\n this.eventCache.delete(sessionId);\r\n this.eventCacheMtimes.delete(sessionId);\r\n this.eventCache.set(sessionId, data);\r\n this.eventCacheMtimes.set(sessionId, mtimeMs);\r\n while (this.eventCache.size > DefaultSessionReader.EVENT_CACHE_MAX_ENTRIES) {\r\n const oldest = this.eventCache.keys().next().value;\r\n if (oldest === undefined) break;\r\n this.eventCache.delete(oldest);\r\n this.eventCacheMtimes.delete(oldest);\r\n }\r\n\r\n if (data.metadata.endedAt) {\r\n storeWithPath.clearLoadCache?.(sessionId);\r\n }\r\n\r\n return data;\r\n }\r\n\r\n async query(q: SessionQuery = {}): Promise<SessionSummaryLite[]> {\r\n // Prefer the store's filtered list when available — it pushes the\r\n // filter into the cached index instead of fetching 1000 + linear scan.\r\n const storeWithFilter = this.store as SessionStore & {\r\n listFiltered?: ((criteria: {\r\n since?: string | undefined;\r\n until?: string | undefined;\r\n provider?: string | undefined;\r\n model?: string | undefined;\r\n minTokens?: number | undefined;\r\n titleContains?: string | undefined;\r\n limit?: number | undefined;\r\n }) => Promise<import('../types/session.js').SessionSummary[]>) | undefined;\r\n };\r\n let raw: import('../types/session.js').SessionSummary[];\r\n if (typeof storeWithFilter.listFiltered === 'function') {\r\n raw = await storeWithFilter.listFiltered({\r\n since: q.since,\r\n until: q.until,\r\n provider: q.provider,\r\n model: q.model,\r\n minTokens: q.minTokens,\r\n titleContains: q.titleContains,\r\n limit: q.limit,\r\n });\r\n } else {\r\n const fetched = await this.store.list(q.limit ? Math.max(q.limit, 100) : 1000);\r\n const titleNeedle = q.titleContains?.toLowerCase();\r\n raw = fetched.filter((s) => {\r\n if (q.since && s.startedAt < q.since) return false;\r\n if (q.until && s.startedAt > q.until) return false;\r\n if (q.provider && s.provider !== q.provider) return false;\r\n if (q.model && s.model !== q.model) return false;\r\n if (q.minTokens !== undefined && s.tokenTotal < q.minTokens) return false;\r\n if (titleNeedle && !s.title.toLowerCase().includes(titleNeedle)) return false;\r\n return true;\r\n });\r\n }\r\n const out: SessionSummaryLite[] = raw.map((s) => ({\r\n id: s.id,\r\n title: s.title,\r\n startedAt: s.startedAt,\r\n provider: s.provider,\r\n model: s.model,\r\n tokenTotal: s.tokenTotal,\r\n }));\r\n return q.limit ? out.slice(0, q.limit) : out;\r\n }\r\n\r\n async *replay(sessionId: string): AsyncIterable<SessionEvent> {\r\n const data = await this.loadCachedSessionData(sessionId);\r\n for (const e of data.events) yield e;\r\n }\r\n\r\n async search(q: SessionSearchQuery, sessionId?: string | undefined, sessionQuery?: SessionQuery): Promise<SessionSearchHit[]> {\r\n const limit = q.limit ?? 100;\r\n const matcher = buildMatcher(q);\r\n const allowedTypes = q.types ? new Set(q.types) : null;\r\n\r\n // Filter sessions BEFORE scanning events — avoids touching the JSONL\r\n // for sessions that don't match the time/provider/model criteria.\r\n let ids: string[];\r\n if (sessionId) {\r\n ids = [sessionId];\r\n } else {\r\n // Prefer the store's filtered list when available — avoids fetching\r\n // 1000 sessions and linear-filtering in-process.\r\n const storeWithFilter = this.store as SessionStore & {\r\n listFiltered?: ((criteria: {\r\n since?: string | undefined;\r\n until?: string | undefined;\r\n provider?: string | undefined;\r\n model?: string | undefined;\r\n minTokens?: number | undefined;\r\n titleContains?: string | undefined;\r\n limit?: number | undefined;\r\n }) => Promise<import('../types/session.js').SessionSummary[]>) | undefined;\r\n };\r\n let sessions: import('../types/session.js').SessionSummary[];\r\n if (typeof storeWithFilter.listFiltered === 'function') {\r\n sessions = await storeWithFilter.listFiltered({\r\n since: sessionQuery?.since,\r\n until: sessionQuery?.until,\r\n provider: sessionQuery?.provider,\r\n model: sessionQuery?.model,\r\n minTokens: sessionQuery?.minTokens,\r\n titleContains: sessionQuery?.titleContains,\r\n limit: 1000,\r\n });\r\n } else {\r\n sessions = await this.store.list(1000);\r\n const titleNeedle = sessionQuery?.titleContains?.toLowerCase();\r\n sessions = sessions.filter((s) => {\r\n if (sessionQuery?.since && s.startedAt < sessionQuery.since) return false;\r\n if (sessionQuery?.until && s.startedAt > sessionQuery.until) return false;\r\n if (sessionQuery?.provider && s.provider !== sessionQuery.provider) return false;\r\n if (sessionQuery?.model && s.model !== sessionQuery.model) return false;\r\n if (sessionQuery?.minTokens !== undefined && s.tokenTotal < sessionQuery.minTokens) return false;\r\n if (titleNeedle && !s.title.toLowerCase().includes(titleNeedle)) return false;\r\n return true;\r\n });\r\n }\r\n ids = sessions.map((s) => s.id);\r\n }\r\n\r\n const hits: SessionSearchHit[] = [];\r\n\r\n // Fast path: when the underlying store supports streaming search,\r\n // walk each session's JSONL line-by-line and bail out the moment we\r\n // hit `limit`. This avoids reading + parsing the entire file (which\r\n // `load()` does) and never reuses `_loadCache`, so concurrent\r\n // analytics queries don't churn the writer-side cache.\r\n const streaming = this.store.searchEvents?.bind(this.store);\r\n if (streaming) {\r\n for (const id of ids) {\r\n const matched = await streaming(\r\n id,\r\n (ev) => {\r\n if (allowedTypes && !allowedTypes.has(ev.type)) return false;\r\n const text = eventText(ev);\r\n if (text === null) return false;\r\n return matcher(text) !== null;\r\n },\r\n { limit: limit - hits.length },\r\n );\r\n for (const m of matched) {\r\n const text = expectDefined(eventText(m.event));\r\n const hit = expectDefined(matcher(text));\r\n hits.push({\r\n sessionId: id,\r\n eventIndex: m.eventIndex,\r\n ts: m.ts,\r\n type: m.event.type,\r\n snippet: snippetOf(text, hit.start, hit.end),\r\n });\r\n if (hits.length >= limit) return hits;\r\n }\r\n }\r\n return hits;\r\n }\r\n\r\n // Fallback: stores that don't implement streaming. Loads the full\r\n // event stream per session — necessary for in-memory or non-file\r\n // stores that don't expose a streaming surface.\r\n for (const id of ids) {\r\n let data;\r\n try {\r\n data = await this.loadCachedSessionData(id);\r\n } catch {\r\n continue;\r\n }\r\n for (let i = 0; i < data.events.length; i++) {\r\n const ev = expectDefined(data.events[i]);\r\n if (allowedTypes && !allowedTypes.has(ev.type)) continue;\r\n const text = eventText(ev);\r\n if (text === null) continue;\r\n const hit = matcher(text);\r\n if (!hit) continue;\r\n hits.push({\r\n sessionId: id,\r\n eventIndex: i,\r\n ts: ev.ts,\r\n type: ev.type,\r\n snippet: snippetOf(text, hit.start, hit.end),\r\n });\r\n if (hits.length >= limit) return hits;\r\n }\r\n }\r\n return hits;\r\n }\r\n\r\n async export(sessionId: string, opts: SessionExportOptions): Promise<string> {\r\n const data = await this.loadCachedSessionData(sessionId);\r\n const includeTools = opts.includeTools ?? true;\r\n const includeDiagnostics = opts.includeDiagnostics ?? true;\r\n\r\n const filtered = data.events.filter((e) => {\r\n if (\r\n !includeTools &&\r\n (e.type === 'tool_use' ||\r\n e.type === 'tool_result' ||\r\n e.type === 'tool_call_start' ||\r\n e.type === 'tool_call_end')\r\n ) {\r\n return false;\r\n }\r\n if (\r\n !includeDiagnostics &&\r\n (e.type === 'error' || e.type === 'compaction' || e.type === 'message_truncated')\r\n ) {\r\n return false;\r\n }\r\n return true;\r\n });\r\n\r\n if (opts.format === 'json') {\r\n return JSON.stringify({ metadata: data.metadata, events: filtered }, null, 2);\r\n }\r\n if (opts.format === 'text') {\r\n return renderPlainText(data.metadata, filtered);\r\n }\r\n return renderMarkdown(data.metadata, filtered);\r\n }\r\n\r\n async metadata(sessionId: string): Promise<SessionMetadata> {\r\n const data = await this.loadCachedSessionData(sessionId);\r\n return data.metadata;\r\n }\r\n}\r\n\r\nfunction buildMatcher(\r\n q: SessionSearchQuery,\r\n): (text: string) => { start: number; end: number } | null {\r\n const ci = q.caseInsensitive ?? true;\r\n if (q.regex) {\r\n const flags = ci ? 'i' : '';\r\n const compiled = compileUserRegex(q.query, flags);\r\n if (!compiled.ok) {\r\n throw new Error(`Invalid search regex \"${q.query}\": ${compiled.reason}`);\r\n }\r\n const re = compiled.regex;\r\n return (text) => {\r\n const m = re.exec(text);\r\n return m ? { start: m.index, end: m.index + m[0].length } : null;\r\n };\r\n }\r\n const needle = ci ? q.query.toLowerCase() : q.query;\r\n return (text) => {\r\n const hay = ci ? text.toLowerCase() : text;\r\n const idx = hay.indexOf(needle);\r\n return idx === -1 ? null : { start: idx, end: idx + needle.length };\r\n };\r\n}\r\n\r\nfunction eventText(e: SessionEvent): string | null {\r\n switch (e.type) {\r\n case 'user_input':\r\n return contentToString(e.content);\r\n case 'llm_response':\r\n return contentToString(e.content);\r\n case 'tool_use':\r\n return `${e.name} ${JSON.stringify(e.input)}`;\r\n case 'tool_result':\r\n return typeof e.content === 'string' ? e.content : JSON.stringify(e.content);\r\n case 'error':\r\n return `${e.phase}: ${e.message}`;\r\n case 'session_start':\r\n case 'session_resumed':\r\n return `${e.model}/${e.provider}`;\r\n case 'task_created':\r\n case 'task_completed':\r\n return e.title;\r\n case 'task_failed':\r\n return `${e.title}: ${e.error}`;\r\n case 'skill_activated':\r\n case 'skill_deactivated':\r\n return e.skillName;\r\n default:\r\n return null;\r\n }\r\n}\r\n\r\nfunction contentToString(content: string | ContentBlock[]): string {\r\n if (typeof content === 'string') return content;\r\n return content\r\n .map((b) => {\r\n switch (b.type) {\r\n case 'text':\r\n return b.text;\r\n case 'tool_use':\r\n return `[tool_use:${b.name} ${JSON.stringify(b.input)}]`;\r\n case 'tool_result':\r\n return typeof b.content === 'string' ? b.content : JSON.stringify(b.content);\r\n default:\r\n return '';\r\n }\r\n })\r\n .join('\\n');\r\n}\r\n\r\nconst SNIPPET_RADIUS = 60;\r\n\r\nfunction snippetOf(text: string, start: number, end: number): string {\r\n const from = Math.max(0, start - SNIPPET_RADIUS);\r\n const to = Math.min(text.length, end + SNIPPET_RADIUS);\r\n const prefix = from > 0 ? '…' : '';\r\n const suffix = to < text.length ? '…' : '';\r\n return prefix + text.slice(from, to).replace(/\\s+/g, ' ').trim() + suffix;\r\n}\r\n\r\nfunction renderMarkdown(meta: SessionMetadata, events: SessionEvent[]): string {\r\n const lines: string[] = [];\r\n lines.push(`# Session ${meta.id}`);\r\n lines.push('');\r\n if (meta.model || meta.provider) {\r\n lines.push(`- **Model:** ${meta.provider ?? '?'}/${meta.model ?? '?'}`);\r\n }\r\n lines.push(`- **Started:** ${meta.startedAt}`);\r\n if (meta.endedAt) lines.push(`- **Ended:** ${meta.endedAt}`);\r\n lines.push('');\r\n lines.push('---');\r\n lines.push('');\r\n for (const e of events) {\r\n switch (e.type) {\r\n case 'user_input': {\r\n lines.push(`## User — ${e.ts}`);\r\n lines.push('');\r\n lines.push(contentToString(e.content));\r\n lines.push('');\r\n break;\r\n }\r\n case 'llm_response': {\r\n lines.push(`## Assistant — ${e.ts}`);\r\n lines.push('');\r\n lines.push(contentToString(e.content));\r\n if (e.stopReason && e.stopReason !== 'end_turn') {\r\n lines.push('');\r\n lines.push(`*stop: ${e.stopReason}*`);\r\n }\r\n lines.push('');\r\n break;\r\n }\r\n case 'tool_use': {\r\n lines.push(`### Tool call: \\`${e.name}\\``);\r\n lines.push('');\r\n lines.push('```json');\r\n lines.push(JSON.stringify(e.input, null, 2));\r\n lines.push('```');\r\n lines.push('');\r\n break;\r\n }\r\n case 'tool_result': {\r\n const body = typeof e.content === 'string' ? e.content : JSON.stringify(e.content, null, 2);\r\n lines.push(`### Tool result${e.isError ? ' (error)' : ''}`);\r\n lines.push('');\r\n lines.push('```');\r\n lines.push(body);\r\n lines.push('```');\r\n lines.push('');\r\n break;\r\n }\r\n case 'error': {\r\n lines.push(`> **Error** (${e.phase}): ${e.message}`);\r\n lines.push('');\r\n break;\r\n }\r\n case 'compaction': {\r\n lines.push(`> **Compaction**: ${e.before} → ${e.after} tokens`);\r\n lines.push('');\r\n break;\r\n }\r\n default:\r\n break;\r\n }\r\n }\r\n return lines.join('\\n');\r\n}\r\n\r\nfunction renderPlainText(meta: SessionMetadata, events: SessionEvent[]): string {\r\n const lines: string[] = [];\r\n lines.push(\r\n `Session ${meta.id} — ${meta.provider ?? '?'}/${meta.model ?? '?'} — started ${meta.startedAt}`,\r\n );\r\n lines.push(''.padEnd(72, '-'));\r\n for (const e of events) {\r\n switch (e.type) {\r\n case 'user_input':\r\n lines.push(`[${e.ts}] USER`);\r\n lines.push(contentToString(e.content));\r\n lines.push('');\r\n break;\r\n case 'llm_response':\r\n lines.push(`[${e.ts}] ASSISTANT`);\r\n lines.push(contentToString(e.content));\r\n lines.push('');\r\n break;\r\n case 'tool_use':\r\n lines.push(`[${e.ts}] TOOL_USE ${e.name} ${JSON.stringify(e.input)}`);\r\n break;\r\n case 'tool_result':\r\n lines.push(\r\n `[${e.ts}] TOOL_RESULT${e.isError ? ' (error)' : ''} ${\r\n typeof e.content === 'string' ? e.content : JSON.stringify(e.content)\r\n }`,\r\n );\r\n break;\r\n case 'error':\r\n lines.push(`[${e.ts}] ERROR (${e.phase}): ${e.message}`);\r\n break;\r\n default:\r\n break;\r\n }\r\n }\r\n return lines.join('\\n');\r\n}\r\n","import { expectDefined } from '../utils/expect-defined.js';\nimport { toErrorMessage } from '../utils/error.js';\nimport { randomUUID } from 'node:crypto';\nimport * as fs from 'node:fs/promises';\nimport { sessionScopedPath } from '../utils/session-scoped-path.js';\nimport { atomicWrite, withFileLock } from '../utils/atomic-write.js';\nimport { WrongStackError, ERROR_CODES } from '../types/errors.js';\nimport type { EventBus } from '../kernel/events.js';\n/**\n * L2-B: AnnotationsStore — sidecar storage for collaboration annotations\n * (Phase 2 of idea #13 from IDEAS.md).\n *\n * Why a sidecar file, not the session JSONL?\n *\n * The session log is an event-sourced append-only journal\n * (`packages/core/src/types/session.ts` invariant: events are\n * append-only, with `truncateToCheckpoint` only as an explicit\n * rewind). Mixing in human-typed annotations would break that\n * invariant — the user's note about \"this rm looks dangerous\"\n * is not part of the agent's event history; it is meta-commentary\n * on the history.\n *\n * So we keep annotations in a sibling file: one JSON document per\n * session, resolved with `sessionScopedPath(sessionDir, sessionId,\n * '.annotations.json')`. The shape is a simple versioned array,\n * written atomically.\n *\n * Concurrency model:\n *\n * The store uses a per-session Promise chain to serialize writes.\n * Multiple annotators adding notes at the same time will queue,\n * not race. The atomic write itself is the second line of\n * defense (in case the chain is bypassed — e.g. two processes\n * pointing at the same dir).\n */\n\n/** Wire/storage shape for one annotation. */\nexport interface Annotation {\n /** Stable id (UUIDv4-ish). Referenced by resolve/delete. */\n id: string;\n /** Session this annotation belongs to. */\n sessionId: string;\n /** Index into the session event log the annotation refers to. */\n atEventIndex: number;\n /** Participant id of the annotator (matches WSCollabParticipantJoined.participantId). */\n authorId: string;\n /** Human-readable role label snapshot for display (e.g. \"annotator\"). */\n authorRole: 'annotator';\n /** The note itself. Trimmed, capped at `MAX_TEXT_LENGTH` on add. */\n text: string;\n /** ISO timestamp of creation. */\n createdAt: string;\n /** Resolved state. Annotations start unresolved. */\n resolved: boolean;\n /** ISO timestamp when resolved (if resolved). */\n resolvedAt?: string | undefined;\n /** Participant id of the resolver (if resolved). */\n resolvedBy?: string | undefined;\n}\n\ninterface AnnotationsFile {\n /** Bumped when the on-disk shape changes. v1 = initial release. */\n version: 1;\n annotations: Annotation[];\n}\n\n/** Bumped when the on-disk shape changes. Bump + migration on change. */\nconst FILE_VERSION = 1;\n/** Hard cap to keep a runaway annotator from writing megabytes. */\nconst MAX_TEXT_LENGTH = 2000;\n/** Hard cap on total annotations per session (oldest are evicted beyond this). */\nconst MAX_ANNOTATIONS = 1000;\n\nexport interface AnnotationsStoreOptions {\n /** Root sessions directory used with `sessionScopedPath(..., '.annotations.json')`. */\n dir: string;\n events?: EventBus;\n traceId?: string;\n}\n\nexport class AnnotationsStore {\n private readonly dir: string;\n private readonly events: EventBus | undefined;\n private readonly traceId: string | undefined;\n /** Per-session write queue. Created lazily on first add. */\n private readonly writeChains = new Map<string, Promise<void>>();\n\n constructor(opts: AnnotationsStoreOptions) {\n this.dir = opts.dir;\n this.events = opts.events;\n this.traceId = opts.traceId;\n }\n\n // ── Reads ──────────────────────────────────────────────────────────────\n\n /**\n * Return all annotations for `sessionId` in insertion order\n * (oldest first). Returns an empty array when no file exists\n * yet (the normal case for a fresh session) and also degrades\n * gracefully to `[]` on a read error (permissions, corruption) —\n * the failure is still surfaced via a `storage.read` event so it\n * never silently hides I/O problems from observers.\n */\n async list(sessionId: string): Promise<Annotation[]> {\n const t0 = Date.now();\n const fp = this.filePath(sessionId);\n try {\n const file = await this.readFile(sessionId);\n const durationMs = Date.now() - t0;\n this.events?.emit('storage.read', {\n sessionId,\n store: 'annotations',\n filePath: fp,\n operation: 'list',\n outcome: 'success',\n durationMs,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return file ? file.annotations : [];\n } catch (err) {\n this.events?.emit('storage.read', {\n sessionId,\n store: 'annotations',\n filePath: fp,\n operation: 'list',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: toErrorMessage(err),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return [];\n }\n }\n\n /**\n * Convenience: only unresolved annotations, newest first — the\n * common UI rendering for \"what still needs attention?\".\n */\n async listOpen(sessionId: string): Promise<Annotation[]> {\n const all = await this.list(sessionId);\n return all.filter((a) => !a.resolved).reverse();\n }\n\n // ── Writes ─────────────────────────────────────────────────────────────\n\n /**\n * Add a new annotation. Returns the persisted record (with id\n * and timestamps filled in). Throws when `text` is empty or\n * exceeds `MAX_TEXT_LENGTH`.\n */\n async add(input: {\n sessionId: string;\n atEventIndex: number;\n authorId: string;\n text: string;\n }): Promise<Annotation> {\n const text = input.text.trim();\n if (text.length === 0) {\n throw new WrongStackError({\n message: 'Annotation text must be non-empty',\n code: ERROR_CODES.VALIDATION_ERROR,\n subsystem: 'general',\n context: { field: 'text', sessionId: input.sessionId },\n });\n }\n if (text.length > MAX_TEXT_LENGTH) {\n throw new WrongStackError({\n message: `Annotation text exceeds ${MAX_TEXT_LENGTH} chars (got ${text.length})`,\n code: ERROR_CODES.VALIDATION_ERROR,\n subsystem: 'general',\n context: { field: 'text', maxLength: MAX_TEXT_LENGTH, actualLength: text.length },\n });\n }\n if (!Number.isInteger(input.atEventIndex) || input.atEventIndex < 0) {\n throw new WrongStackError({\n message: 'atEventIndex must be a non-negative integer',\n code: ERROR_CODES.VALIDATION_ERROR,\n subsystem: 'general',\n context: { field: 'atEventIndex', value: input.atEventIndex },\n });\n }\n const annotation: Annotation = {\n id: randomUUID(),\n sessionId: input.sessionId,\n atEventIndex: input.atEventIndex,\n authorId: input.authorId,\n authorRole: 'annotator',\n text,\n createdAt: new Date().toISOString(),\n resolved: false,\n };\n const fp = this.filePath(input.sessionId);\n const t0 = Date.now();\n try {\n await this.enqueue(input.sessionId, async () => {\n await withFileLock(fp, async () => {\n const all = await this.list(input.sessionId);\n all.push(annotation);\n // Evict oldest if we crossed the cap. Resolved first, then oldest.\n if (all.length > MAX_ANNOTATIONS) {\n const sorted = all\n .map((a, i) => ({ a, i }))\n .sort((x, y) => {\n // resolved=false wins (keep unresolved); among same resolved state, oldest first.\n /* v8 ignore next -- scale+tiebreak: needs >1000 annotations with mixed resolved states */\n if (x.a.resolved !== y.a.resolved) return x.a.resolved ? 1 : -1;\n return x.a.createdAt.localeCompare(y.a.createdAt);\n });\n const evictCount = all.length - MAX_ANNOTATIONS;\n const toEvict = new Set(sorted.slice(0, evictCount).map((s) => s.a.id));\n const kept = all.filter((a) => !toEvict.has(a.id));\n await this.writeFile(input.sessionId, { version: FILE_VERSION, annotations: kept });\n const durationMs = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: input.sessionId,\n store: 'annotations',\n filePath: fp,\n operation: 'evict',\n outcome: 'success',\n durationMs,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n } else {\n await this.writeFile(input.sessionId, { version: FILE_VERSION, annotations: all });\n const durationMs = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: input.sessionId,\n store: 'annotations',\n filePath: fp,\n operation: 'add',\n outcome: 'success',\n durationMs,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n }\n });\n });\n return annotation;\n } catch (err) {\n this.events?.emit('storage.error', {\n sessionId: input.sessionId,\n store: 'annotations',\n filePath: fp,\n operation: 'add',\n outcome: 'failure',\n error: toErrorMessage(err),\n recoverable: false,\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n throw err;\n }\n }\n\n /**\n * Mark an annotation as resolved. Returns the updated record, or\n * `null` if no annotation with that id exists in this session.\n * Idempotent: resolving an already-resolved annotation refreshes\n * `resolvedAt` / `resolvedBy` to the latest call.\n */\n async resolve(input: {\n sessionId: string;\n annotationId: string;\n resolvedBy: string;\n }): Promise<Annotation | null> {\n let updated: Annotation | null = null;\n const fp = this.filePath(input.sessionId);\n const t0 = Date.now();\n try {\n await this.enqueue(input.sessionId, async () => {\n await withFileLock(fp, async () => {\n const all = await this.list(input.sessionId);\n const idx = all.findIndex((a) => a.id === input.annotationId);\n if (idx === -1) {\n updated = null;\n return;\n }\n const next: Annotation = {\n ...expectDefined(all[idx]),\n resolved: true,\n resolvedAt: new Date().toISOString(),\n resolvedBy: input.resolvedBy,\n };\n all[idx] = next;\n await this.writeFile(input.sessionId, { version: FILE_VERSION, annotations: all });\n updated = next;\n const durationMs = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: input.sessionId,\n store: 'annotations',\n filePath: fp,\n operation: 'resolve',\n outcome: 'success',\n durationMs,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n });\n });\n return updated;\n } catch (err) {\n this.events?.emit('storage.error', {\n sessionId: input.sessionId,\n store: 'annotations',\n filePath: fp,\n operation: 'resolve',\n outcome: 'failure',\n error: toErrorMessage(err),\n recoverable: false,\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n throw err;\n }\n }\n\n // ── Internals ──────────────────────────────────────────────────────────\n\n private filePath(sessionId: string): string {\n // Containment-checked: date-sharded ids (\"2026-06-11/<base>\") are\n // legitimate; traversal is rejected. A plain slash ban here used to\n // throw for every modern session id, breaking annotations entirely.\n return sessionScopedPath(this.dir, sessionId, '.annotations.json');\n }\n\n private async readFile(sessionId: string): Promise<AnnotationsFile | null> {\n const fp = this.filePath(sessionId);\n let raw: string;\n try {\n raw = await fs.readFile(fp, 'utf8');\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return null;\n // Non-ENOENT I/O errors (EACCES, ENOSPC): re-throw so callers emit\n // storage.error.\n throw err;\n }\n try {\n const parsed = JSON.parse(raw) as AnnotationsFile;\n if (parsed.version !== FILE_VERSION) {\n return { version: FILE_VERSION, annotations: [] };\n }\n return parsed;\n } catch {\n // JSON parse error (SyntaxError): treat as empty store — not an I/O failure.\n return null;\n }\n }\n\n private async writeFile(sessionId: string, file: AnnotationsFile): Promise<void> {\n const fp = this.filePath(sessionId);\n await atomicWrite(fp, JSON.stringify(file, null, 2));\n }\n\n /**\n * Serialize writes per-sessionId. We chain promises instead of\n * using a Mutex class so the contract is obvious from the\n * call-site: `enqueue(sid, fn)` runs `fn` after every prior\n * enqueue for `sid` has settled.\n */\n private enqueue(sessionId: string, fn: () => Promise<void>): Promise<void> {\n const prev = this.writeChains.get(sessionId) ?? Promise.resolve();\n const next = prev.then(fn, fn);\n // Keep the chain intact even when `fn` throws; failures\n // shouldn't break subsequent writes.\n this.writeChains.set(\n sessionId,\n next.catch(() => undefined),\n );\n return next;\n }\n}\n","import { createHash } from 'node:crypto';\nimport type { Request } from '../types/provider.js';\n\n/**\n * Idea #2 from IDEAS.md — Deterministic Replay.\n *\n * The hash function is the foundation of replay: given a `Request`,\n * produce a stable identifier so a recorded `Response` can be looked\n * up later when we want to \"re-run\" the same agent loop without\n * burning API credits.\n *\n * Stability rules:\n *\n * - All object keys are sorted recursively before stringification.\n * Without this, two semantically identical requests that differ\n * only in key insertion order would produce different hashes.\n * - We hash ONLY the fields that affect the response: `model`,\n * `system`, `messages`, `tools`, `maxTokens`, and the four\n * sampling knobs (`temperature`, `topP`, `stopSequences`,\n * `toolChoice`). Anything else on the `Request` (metadata,\n * future extensions) is ignored so replay stays forward-compat.\n * - We serialize to JSON. The `ContentBlock` and `Message` shapes\n * are pure data; this works as long as no `undefined` values\n * sneak in (those get dropped by `JSON.stringify`, which is\n * fine — the structural diff is what matters).\n *\n * The SHA-256 output is hex-encoded and prefixed with the algorithm\n * tag so a future migration to a different hash (e.g. blake3) is\n * trivial to detect.\n */\nexport function stableStringify(value: unknown): string {\n return JSON.stringify(sortKeys(value));\n}\n\nfunction sortKeys(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortKeys);\n if (value && typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(obj).sort()) {\n sorted[key] = sortKeys(obj[key]);\n }\n return sorted;\n }\n return value;\n}\n\nexport function hashRequest(request: Request): string {\n // Pick only the fields that affect the response. See stability rules.\n const payload = {\n model: request.model,\n system: request.system,\n messages: request.messages,\n tools: request.tools,\n maxTokens: request.maxTokens,\n temperature: request.temperature,\n topP: request.topP,\n stopSequences: request.stopSequences,\n toolChoice: request.toolChoice,\n };\n const json = stableStringify(payload);\n const digest = createHash('sha256').update(json, 'utf8').digest('hex');\n return `sha256:${digest}`;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { atomicWrite, withFileLock } from '../utils/atomic-write.js';\nimport { toErrorMessage } from '../utils/error.js';\nimport { sessionScopedPath } from '../utils/session-scoped-path.js';\nimport { hashRequest } from '../replay/hash.js';\nimport type { Request, Response } from '../types/provider.js';\nimport { safeParse } from '../utils/safe-json.js';\nimport type { EventBus } from '../kernel/events.js';\n\n/**\n * Surface the OS error code (EACCES, ENOSPC, …) alongside the message in\n * storage.* event payloads. Codes are stable and locale-independent, so\n * they are what dashboards and alerts key on; the message is supplementary.\n */\nfunction storageErrorString(err: unknown): string {\n if (err instanceof Error) {\n const code = (err as NodeJS.ErrnoException).code;\n return code ? `${code}: ${err.message}` : err.message;\n }\n /* v8 ignore next -- defensive: fs/lock failures are always Error instances */\n return String(err);\n}\n\n/**\n * ReplayLogStore — sidecar store for deterministic-replay support\n * (idea #2 from IDEAS.md). One JSONL file per session, recording\n * every provider request/response pair so the same agent loop can\n * be re-run later with frozen API responses.\n *\n * Why a sidecar (not the session JSONL)?\n *\n * Same reason as `AnnotationsStore` — the session log is\n * event-sourced and append-only; a provider request payload can be\n * tens of kilobytes (especially with long conversation history),\n * and we want replay to be opt-in (recorded only when the user\n * runs with `--replay` or a future equivalent). Mixing it into\n * the event log would inflate every read for replay-irrelevant\n * paths.\n *\n * File layout: `sessionScopedPath(dir, sessionId, '.replay.jsonl')`,\n * one entry per line.\n * Each entry: `{ hash, ts, request, response }`. The `hash` is\n * computed via `hashRequest` so lookups are O(1) by hash.\n *\n * Concurrency: per-session write queue (same pattern as\n * `AnnotationsStore`). Reads are lock-free; the write chain makes\n * the append + rehash sequence atomic.\n */\nexport interface ReplayEntry {\n hash: string;\n ts: string;\n request: Request;\n response: Response;\n}\n\nconst FILE_VERSION = 1;\n\n/** Default cap on the number of entries per session. */\nconst DEFAULT_MAX_ENTRIES = 1000;\n\nexport interface ReplayLogStoreOptions {\n /** Root sessions directory used with `sessionScopedPath(..., '.replay.jsonl')`. */\n dir: string;\n /**\n * Cap on the number of entries per session. When a `record` would\n * push the file beyond this, the oldest entries are evicted (LRU\n * by insertion order). Set to `Infinity` to disable rotation.\n * Defaults to 1000 — a single LLM call averages ~5KB serialized\n * (messages + tools + response), so 1000 entries is ~5MB per\n * session which is a reasonable upper bound.\n */\n maxEntries?: number | undefined;\n events?: EventBus;\n traceId?: string;\n}\n\ninterface ReplayEntryLocation {\n entry?: ReplayEntry;\n offset: number;\n length: number;\n}\n\nexport class ReplayLogStore {\n private readonly dir: string;\n private readonly events: EventBus | undefined;\n private readonly traceId: string | undefined;\n private readonly writeChains = new Map<string, Promise<void>>();\n /** Per-session hash → on-disk location, with lazy entry hydration. */\n private readonly cache = new Map<string, Map<string, ReplayEntryLocation>>();\n /** Per-session entry count on disk, to detect when compaction is needed. */\n private readonly diskCount = new Map<string, number>();\n private readonly maxEntries: number;\n\n constructor(opts: ReplayLogStoreOptions) {\n this.dir = opts.dir;\n this.events = opts.events;\n this.traceId = opts.traceId;\n this.maxEntries = opts.maxEntries ?? DEFAULT_MAX_ENTRIES;\n }\n\n // ── Writes ──────────────────────────────────────────────────────────────\n\n /**\n * Record a request/response pair. Idempotent on hash: a second\n * `record` for the same hash is a no-op (the existing entry wins).\n * Returns the hash.\n */\n async record(input: {\n sessionId: string;\n request: Request;\n response: Response;\n }): Promise<string> {\n const hash = hashRequest(input.request);\n const fp = this.filePath(input.sessionId);\n const t0 = Date.now();\n try {\n await this.enqueue(input.sessionId, async () => {\n await withFileLock(fp, async () => {\n // Dedup via the in-memory hash map — O(1) instead of re-reading\n // and re-parsing the whole JSONL just to run `entries.some(...)`.\n // `ensureCache` populates both the cache and `diskCount` from a\n // single read on first contact; subsequent records reuse it.\n const cache = await this.ensureCache(input.sessionId);\n if (cache.has(hash)) return; // already recorded\n\n const entry: ReplayEntry = {\n hash,\n ts: new Date().toISOString(),\n request: input.request,\n response: input.response,\n };\n\n const currentCount = this.diskCount.get(input.sessionId) ?? 0;\n const willEvict = currentCount + 1 > this.maxEntries;\n\n if (!willEvict) {\n // Common path (the first `maxEntries` writes per session, plus\n // any session that never hits the cap): a single O(1) append.\n // The previous implementation did a full readAll + full rewrite\n // (atomicWrite of the entire file) on every single record, which\n // was quadratic in session length — a 1000-call session rewrote\n // a multi-MB file 1000 times.\n const line = JSON.stringify(entry) + '\\n';\n let offset = 0;\n try {\n const stat = await fs.stat(fp);\n offset = stat.size;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;\n }\n await fs.appendFile(fp, line, 'utf8');\n cache.set(hash, { entry, offset, length: Buffer.byteLength(line, 'utf8') });\n this.diskCount.set(input.sessionId, currentCount + 1);\n this.events?.emit('storage.write', {\n sessionId: input.sessionId,\n store: 'replay',\n filePath: fp,\n operation: 'record',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return;\n }\n\n // Eviction path: we're at capacity, drop the oldest entry to make\n // room. This does require a full read + rewrite, but it fires at\n // most once per `maxEntries` writes (default 1000), not per write.\n const all = await this.readAll(input.sessionId);\n all.push(entry);\n const keep = all.slice(-this.maxEntries);\n const refreshed = new Map<string, ReplayEntryLocation>();\n let offset = 0;\n for (const e of keep) {\n const line = JSON.stringify(e) + '\\n';\n refreshed.set(e.hash, { entry: e, offset, length: Buffer.byteLength(line, 'utf8') });\n offset += Buffer.byteLength(line, 'utf8');\n }\n this.cache.set(input.sessionId, refreshed);\n this.diskCount.set(input.sessionId, keep.length);\n await this.writeAll(input.sessionId, keep, 'compact');\n });\n });\n return hash;\n } catch (err) {\n this.events?.emit('storage.error', {\n sessionId: input.sessionId,\n store: 'replay',\n filePath: fp,\n operation: 'record',\n outcome: 'failure',\n error: storageErrorString(err),\n recoverable: false,\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n throw err;\n }\n }\n\n // ── Reads ───────────────────────────────────────────────────────────────\n\n /**\n * Look up an entry by hash. Returns `null` when the request has\n * not been recorded for this session. O(1) after the first call\n * per session (in-memory cache).\n */\n async lookup(sessionId: string, hash: string): Promise<ReplayEntry | null> {\n const fp = this.filePath(sessionId);\n const t0 = Date.now();\n try {\n const cache = await this.ensureCache(sessionId);\n const location = cache.get(hash);\n const entry = location ? await this.hydrateEntry(sessionId, hash, location) : null;\n this.events?.emit('storage.read', {\n sessionId,\n store: 'replay',\n filePath: fp,\n operation: 'lookup',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return entry;\n } catch (err) {\n this.events?.emit('storage.read', {\n sessionId,\n store: 'replay',\n filePath: fp,\n operation: 'lookup',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: storageErrorString(err),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n throw err;\n }\n }\n\n /** All recorded entries for a session, in insertion order. */\n async load(sessionId: string): Promise<ReplayEntry[]> {\n const fp = this.filePath(sessionId);\n const t0 = Date.now();\n try {\n const cache = await this.ensureCache(sessionId);\n const entries: ReplayEntry[] = [];\n for (const [hash, location] of cache) {\n entries.push(await this.hydrateEntry(sessionId, hash, location));\n }\n const durationMs = Date.now() - t0;\n this.events?.emit('storage.read', {\n sessionId,\n store: 'replay',\n filePath: fp,\n operation: 'load',\n outcome: 'success',\n durationMs,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return entries;\n } catch (err) {\n const durationMs = Date.now() - t0;\n this.events?.emit('storage.read', {\n sessionId,\n store: 'replay',\n filePath: fp,\n operation: 'load',\n outcome: 'failure',\n durationMs,\n error: storageErrorString(err),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n throw err;\n }\n }\n\n /**\n * List every session id that has a replay log in the store dir.\n * Returns an array of `{ sessionId, entryCount, path }` sorted\n * by sessionId for stable output. Used by `wstack replay --list`.\n */\n async list(): Promise<Array<{ sessionId: string; entryCount: number; path: string }>> {\n const out: Array<{ sessionId: string; entryCount: number; path: string }> = [];\n // Replay logs sit next to their session JSONL — flat at the root for\n // legacy/`record-<ts>` ids, inside a date-shard dir for modern ids.\n // Scan both levels; a root-only scan misses every sharded session.\n const scan = async (dir: string, prefix: string, depth: number): Promise<void> => {\n let entries: import('node:fs').Dirent[];\n try {\n entries = await fs.readdir(dir, { withFileTypes: true });\n } catch (err) {\n if (depth === 0 && (err as NodeJS.ErrnoException).code !== 'ENOENT') {\n // EACCES, ENOTDIR, etc. — log the real error so the operator can\n // diagnose a misconfiguration, but still return empty list so the\n // caller (slash command display) doesn't crash.\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'replay_log_store.list_readdir_failed',\n dir,\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n }\n return;\n }\n for (const entry of entries) {\n if (entry.name.startsWith('.')) continue;\n if (entry.isDirectory()) {\n if (depth === 0) await scan(path.join(dir, entry.name), entry.name, depth + 1);\n continue;\n }\n if (!entry.isFile() || !entry.name.endsWith('.replay.jsonl')) continue;\n const base = entry.name.slice(0, -'.replay.jsonl'.length);\n const sessionId = prefix ? `${prefix}/${base}` : base;\n const fp = path.join(dir, entry.name);\n out.push({\n sessionId,\n entryCount: await this.countEntries(fp),\n path: fp,\n });\n }\n };\n await scan(this.dir, '', 0);\n return out.sort((a, b) => a.sessionId.localeCompare(b.sessionId));\n }\n\n // ── Internals ───────────────────────────────────────────────────────────\n\n private filePath(sessionId: string): string {\n // Containment-checked: date-sharded ids (\"2026-06-11/<base>\") are\n // legitimate; traversal is rejected. A plain slash ban would throw\n // the moment a real (sharded) session id is used for --replay.\n return sessionScopedPath(this.dir, sessionId, '.replay.jsonl');\n }\n\n private async countEntries(filePath: string): Promise<number> {\n // list() only needs a count, not provider request/response payloads. Count\n // non-empty JSONL rows in fixed-size chunks so large replay logs are not\n // parsed or materialized just to render `wstack replay --list`.\n const handle = await fs.open(filePath, 'r');\n const buffer = Buffer.allocUnsafe(64 * 1024);\n let count = 0;\n let hasNonWhitespace = false;\n try {\n while (true) {\n const { bytesRead } = await handle.read(buffer, 0, buffer.length, null);\n if (bytesRead === 0) break;\n for (let i = 0; i < bytesRead; i++) {\n const ch = buffer[i]!;\n if (ch === 10) {\n if (hasNonWhitespace) count++;\n hasNonWhitespace = false;\n continue;\n }\n if (ch !== 13 && ch !== 32 && ch !== 9) {\n hasNonWhitespace = true;\n }\n }\n }\n } finally {\n await handle.close();\n }\n if (hasNonWhitespace) count++;\n return count;\n }\n\n private parseReplayLine(line: string): ReplayEntry | null {\n try {\n const parsed = safeParse<\n { version?: number | undefined; entry?: ReplayEntry | undefined } & ReplayEntry\n >(line);\n if (!parsed.ok || !parsed.value) return null;\n if ('entry' in parsed.value && parsed.value.entry) {\n return parsed.value.entry;\n }\n return parsed.value;\n } catch {\n return null;\n }\n }\n\n private async readAll(sessionId: string): Promise<ReplayEntry[]> {\n const fp = this.filePath(sessionId);\n try {\n const raw = await fs.readFile(fp, 'utf8');\n const out: ReplayEntry[] = [];\n for (const line of raw.split('\\n')) {\n if (!line.trim()) continue;\n const parsed = this.parseReplayLine(line);\n if (parsed) out.push(parsed);\n }\n return out;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return [];\n throw err;\n }\n }\n\n private async writeAll(\n sessionId: string,\n entries: ReplayEntry[],\n operation: 'record' | 'compact' = 'record',\n ): Promise<void> {\n const fp = this.filePath(sessionId);\n const t0 = Date.now();\n const body = entries.map((e) => JSON.stringify(e)).join('\\n') + (entries.length ? '\\n' : '');\n await atomicWrite(fp, body);\n const durationMs = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId,\n store: 'replay',\n filePath: fp,\n operation,\n outcome: 'success',\n durationMs,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n // Drop the version-stamp comment at the top — v1 has no envelope,\n // but we keep a one-line marker for human readers / future tooling.\n // (The atomicWrite just wrote pure JSONL; that's correct for v1.)\n void FILE_VERSION;\n }\n\n private async ensureCache(sessionId: string): Promise<Map<string, ReplayEntryLocation>> {\n let cache = this.cache.get(sessionId);\n if (cache) return cache;\n\n const fp = this.filePath(sessionId);\n cache = new Map();\n try {\n const handle = await fs.open(fp, 'r');\n const CHUNK = 64 * 1024;\n const buffer = Buffer.alloc(CHUNK);\n let leftover = '';\n let leftoverOffset = 0;\n let fileOffset = 0;\n try {\n while (true) {\n const { bytesRead } = await handle.read(buffer, 0, CHUNK, fileOffset);\n if (bytesRead === 0) break;\n const chunk = buffer.subarray(0, bytesRead).toString('utf8');\n const text = leftover + chunk;\n let lineStart = leftoverOffset;\n let searchFrom = 0;\n while (true) {\n const newlineIndex = text.indexOf('\\n', searchFrom);\n if (newlineIndex === -1) break;\n const line = text.slice(searchFrom, newlineIndex);\n const lineLength = Buffer.byteLength(text.slice(searchFrom, newlineIndex + 1), 'utf8');\n if (line.trim()) {\n const entry = this.parseReplayLine(line);\n if (entry) {\n cache.set(entry.hash, { offset: lineStart, length: lineLength });\n }\n }\n lineStart += lineLength;\n searchFrom = newlineIndex + 1;\n }\n leftover = text.slice(searchFrom);\n leftoverOffset = lineStart;\n fileOffset += bytesRead;\n }\n if (leftover.trim()) {\n const entry = this.parseReplayLine(leftover);\n if (entry) {\n cache.set(entry.hash, { offset: leftoverOffset, length: Buffer.byteLength(leftover, 'utf8') });\n }\n }\n } finally {\n await handle.close();\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;\n }\n\n this.cache.set(sessionId, cache);\n this.diskCount.set(sessionId, cache.size);\n return cache;\n }\n\n private async hydrateEntry(\n sessionId: string,\n hash: string,\n location: ReplayEntryLocation,\n ): Promise<ReplayEntry> {\n if (location.entry) return location.entry;\n\n const fp = this.filePath(sessionId);\n const handle = await fs.open(fp, 'r');\n try {\n const buffer = Buffer.alloc(location.length);\n const { bytesRead } = await handle.read(buffer, 0, location.length, location.offset);\n const line = buffer.subarray(0, bytesRead).toString('utf8').trimEnd();\n const entry = this.parseReplayLine(line);\n if (!entry) {\n throw new Error(`Replay entry ${hash} is unreadable`);\n }\n location.entry = entry;\n return entry;\n } finally {\n await handle.close();\n }\n }\n\n private enqueue(sessionId: string, fn: () => Promise<void>): Promise<void> {\n const prev = this.writeChains.get(sessionId) ?? Promise.resolve();\n const next = prev.then(fn, fn);\n this.writeChains.set(\n sessionId,\n next.catch(() => undefined),\n );\n return next;\n }\n}\n","import { expectDefined } from '../utils/expect-defined.js';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { SessionEvent } from '../types/session.js';\nimport { sessionScopedPath } from '../utils/session-scoped-path.js';\n/**\n * Idea #1 from IDEAS.md — Stateful Session Recovery.\n *\n * `SessionRecovery` is the read-side companion to the in-flight\n * marker mechanism. When the agent loop is running, it writes an\n * `in_flight_start` event at the current point in the log. On\n * clean shutdown, a matching `in_flight_end` follows. If the\n * process dies (crash, OOM, machine sleep, SIGKILL) the marker\n * is the last event in the file — and `detectStale` flags the\n * session as \"incomplete, can be resumed\".\n *\n * Phase 1 of this feature is **detection only**. The actual\n * re-execution of incomplete work is a follow-up: it requires\n * tracking pending tool calls, mid-stream LLM responses, and\n * uncommitted file changes — and re-running the agent loop from\n * the last `checkpoint` event. The detection layer is independent\n * and ships first because (a) it gives the user immediate\n * visibility into what died, and (b) it's the foundation for the\n * resume command and the CLI's \"Incomplete sessions\" surface.\n *\n * Concurrency: pure read; no writes. Safe to call from multiple\n * processes simultaneously.\n */\nexport interface StaleSession {\n sessionId: string;\n /** Path to the JSONL log. */\n path: string;\n /** Last event ts (the in_flight_start timestamp). */\n lastEventTs: string;\n /** Context the agent was working on when it died. */\n context: string;\n /** Total events in the log. */\n eventCount: number;\n}\n\nexport interface RecoveryPlan {\n sessionId: string;\n /** True if the session is stale (has a dangling in_flight_start). */\n stale: boolean;\n /** The last `checkpoint` event before the un-replayed work, or null. */\n lastCheckpoint: SessionEvent | null;\n /** All events after the last checkpoint (i.e. the work that needs re-execution). */\n pendingEvents: SessionEvent[];\n /** The dangling in_flight_start event, if any. */\n inFlightStart: SessionEvent | null;\n /** Free-form context the agent was working on, if any. */\n context: string | null;\n}\n\n/**\n * Result of `SessionRecovery.recover(sessionId)`. Distinct from\n * `StaleSession`: a session is \"stale\" if the last event is an\n * open marker, but a \"recovery plan\" can also be generated for\n * clean sessions whose last checkpoint is older than the\n * conversation history (e.g. a user-initiated \"rewind to last\n * good state\" flow). Phase 2 of idea #1: this returns the plan;\n * the actual kernel re-execution is a follow-up.\n */\nexport class SessionRecovery {\n /**\n * Scan a session log and return a `StaleSession` if and only\n * if the last event is an `in_flight_start` without a matching\n * `in_flight_end`. Returns `null` when:\n * - the log does not exist;\n * - the log is empty;\n * - the last event is `in_flight_end` (clean shutdown);\n * - the last event is something else (e.g. an unannotated\n * legacy log without in-flight markers).\n */\n async detectStale(sessionId: string): Promise<StaleSession | null> {\n const fp = this.filePath(sessionId);\n // Only read the last ~8KB — enough for several large events.\n // This is O(1) I/O vs O(n) of reading the entire file.\n const TAIL_SIZE = 8192;\n let stat;\n try {\n stat = await fs.stat(fp);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return null;\n /* v8 ignore next -- defensive: any other stat failure is also non-recoverable */\n return null;\n }\n if (stat.size === 0) return null;\n const position = Math.max(0, stat.size - TAIL_SIZE);\n const buf = Buffer.alloc(TAIL_SIZE);\n let fh;\n try {\n fh = await fs.open(fp, 'r');\n const { bytesRead } = await fh.read(buf, 0, TAIL_SIZE, position);\n // Count total events for StaleSession.eventCount — requires full scan.\n // For very large files this is a trade-off; count is informational.\n let eventCount = 0;\n const raw = buf.subarray(0, bytesRead).toString('utf8');\n for (const line of raw.split('\\n')) {\n if (line.trim()) eventCount++;\n }\n // Find the last complete JSON line in the tail.\n const lines = raw.split('\\n').filter((l) => l.trim());\n for (let i = lines.length - 1; i >= 0; i--) {\n try {\n const ev = JSON.parse(expectDefined(lines[i])) as SessionEvent;\n if (ev.type === 'in_flight_start') {\n return {\n sessionId,\n path: fp,\n lastEventTs: ev.ts,\n context: ev.context,\n eventCount,\n };\n }\n // Found a different last event — clean shutdown or legacy\n return null;\n } catch {\n // Incomplete line (spans the read boundary) — skip\n }\n }\n return null;\n /* v8 ignore start -- defensive: tail open/read failure after a successful stat is rare */\n } catch {\n return null;\n } finally {\n if (fh) await fh.close();\n }\n /* v8 ignore stop */\n }\n\n /**\n * Generate a recovery plan for a session. The plan describes\n * \"what would be re-executed\" if the user chose to resume —\n * everything after the last `checkpoint` event, plus the\n * dangling in-flight marker if present.\n *\n * Returns a non-null plan for ANY session that has at least\n * one event after a checkpoint (or, for legacy sessions, at\n * least one event). Pure read; no mutation.\n */\n async recover(sessionId: string): Promise<RecoveryPlan | null> {\n const fp = this.filePath(sessionId);\n let raw: string;\n try {\n raw = await fs.readFile(fp, 'utf8');\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return null;\n /* v8 ignore next -- defensive: any other read failure is also non-recoverable */\n return null;\n }\n const events: SessionEvent[] = [];\n for (const line of raw.split('\\n')) {\n if (!line.trim()) continue;\n try {\n events.push(JSON.parse(line) as SessionEvent);\n } catch {\n // skip corrupt lines\n }\n }\n if (events.length === 0) return null;\n // Find the last checkpoint.\n let lastCheckpoint: SessionEvent | null = null;\n let lastCheckpointIdx = -1;\n for (let i = 0; i < events.length; i++) {\n if (events[i]?.type === 'checkpoint') {\n lastCheckpoint = expectDefined(events[i]);\n lastCheckpointIdx = i;\n }\n }\n // Events after the last checkpoint = the work that needs re-execution.\n const pendingEvents =\n lastCheckpointIdx >= 0 ? events.slice(lastCheckpointIdx + 1) : events;\n // The dangling in_flight_start, if the last event is one.\n const lastEv = expectDefined(events[events.length - 1]);\n const inFlightStart =\n lastEv.type === 'in_flight_start' ? lastEv : null;\n const context = inFlightStart && inFlightStart.type === 'in_flight_start'\n ? inFlightStart.context\n : null;\n return {\n sessionId,\n stale: inFlightStart !== null,\n lastCheckpoint,\n pendingEvents,\n inFlightStart,\n context,\n };\n }\n\n /**\n * List every stale session in a directory. Returns an array\n * (possibly empty) sorted by `lastEventTs` descending — most\n * recent crash first.\n */\n async listResumable(): Promise<StaleSession[]> {\n const out: StaleSession[] = [];\n // Modern sessions live inside date-shard subdirectories\n // (\"2026-06-11/<base>.jsonl\"); legacy/flat sessions sit at the root.\n // Scan both — a root-only scan silently misses every modern crash.\n const collect = async (dir: string, prefix: string, depth: number): Promise<void> => {\n let entries: import('node:fs').Dirent[];\n try {\n entries = await fs.readdir(dir, { withFileTypes: true });\n /* v8 ignore start -- defensive: the sessions dir (and its shards) are readable during a scan */\n } catch {\n return;\n }\n /* v8 ignore stop */\n for (const entry of entries) {\n if (entry.name.startsWith('.')) continue;\n if (\n entry.name === 'shared' ||\n entry.name === 'subagents' ||\n entry.name === 'attachments'\n )\n continue;\n if (entry.isDirectory()) {\n if (depth === 0) {\n await collect(path.join(dir, entry.name), entry.name, depth + 1);\n }\n continue;\n }\n if (!entry.isFile() || !entry.name.endsWith('.jsonl')) continue;\n if (entry.name === '_index.jsonl' || entry.name === '_mailbox.jsonl') continue;\n const base = entry.name.slice(0, -'.jsonl'.length);\n if (base.includes('.replay') || base.includes('.annotations') || base.includes('.audit'))\n continue;\n const sessionId = prefix ? `${prefix}/${base}` : base;\n const stale = await this.detectStale(sessionId);\n if (stale) out.push(stale);\n }\n };\n await collect(this.dir, '', 0);\n return out.sort((a, b) => b.lastEventTs.localeCompare(a.lastEventTs));\n }\n\n // ── Internals ──────────────────────────────────────────────────────────\n\n private filePath(sessionId: string): string {\n // Containment-checked: date-sharded ids (\"2026-06-11/<base>\") are\n // legitimate; traversal is rejected. Shared with the other per-session\n // sidecar stores so the contract can't drift.\n return sessionScopedPath(this.dir, sessionId, '.jsonl');\n }\n\n constructor(private readonly dir: string) {}\n}\n","import { expectDefined } from '../utils/expect-defined.js';\nimport { toErrorMessage } from '../utils/error.js';\nimport { createHash, randomUUID } from 'node:crypto';\nimport * as fs from 'node:fs/promises';\nimport { withFileLock } from '../utils/atomic-write.js';\nimport { safeParse } from '../utils/safe-json.js';\nimport { sessionScopedPath } from '../utils/session-scoped-path.js';\nimport type { EventBus } from '../kernel/events.js';\n/**\n * ToolAuditLog — idea #9 from IDEAS.md.\n *\n * Tamper-evident audit trail for tool calls. Every tool_use /\n * tool_result pair is appended to a sidecar JSONL with a chained\n * SHA-256 — each entry's `prevHash` is the prior entry's `hash`,\n * so any post-hoc modification of a single line breaks the chain\n * from that point forward.\n *\n * Why a sidecar (not the session JSONL)?\n * Same reason as `AnnotationsStore` and `ReplayLogStore`: the\n * session log is an event-sourced journal. Mixing in a hash\n * chain would inflate every read and tightly couple the\n * integrity check to the event format. Sidecar keeps both\n * concerns orthogonal.\n *\n * What \"tamper-evident\" means here:\n * - The hash covers the full serialized entry: tool name, id,\n * input, output, timestamp, author. Changing any byte\n * changes the hash.\n * - The chain is sequential — a verifier walks the file in\n * order, recomputing each hash, and checks `prevHash`\n * matches the previous entry's `hash`.\n * - Any insertion, deletion, or modification of a single\n * entry surfaces as a \"chain broken at entry N\" verdict.\n *\n * What it does NOT defend against:\n * - An attacker who rewrites the whole file consistently.\n * For that you'd need an external anchor (signing key,\n * transparency log, etc.) — out of scope for Phase 1.\n * - The agent itself misbehaving; this is post-hoc audit, not\n * real-time enforcement. Use `PermissionPolicy` for that.\n *\n * File layout: `sessionScopedPath(dir, sessionId, '.audit.jsonl')`,\n * one entry per line. The chain starts with a `genesis` entry whose\n * `prevHash` is all zeros.\n */\nexport interface AuditEntry {\n /** Monotonic index (0-based). */\n index: number;\n /** UUID for cross-referencing with logs. */\n id: string;\n /** ISO timestamp. */\n ts: string;\n /** Hash of the previous entry (or all-zeros for the genesis entry). */\n prevHash: string;\n /** Hash of this entry's content (sha256 over the canonical JSON). */\n hash: string;\n toolName: string;\n toolUseId: string;\n input: unknown;\n output: unknown;\n isError: boolean;\n}\n\nconst GENESIS_PREV = '0'.repeat(64);\n\nexport type VerifyResult =\n | { ok: true; entries: number }\n | { ok: false; brokenAt: number; reason: string };\n\nexport interface ToolAuditLogOptions {\n /** Root sessions directory used with `sessionScopedPath(..., '.audit.jsonl')`. */\n dir: string;\n /**\n * Flush the file system cache to disk every N writes per session.\n * Default 100. Lower values = better crash durability, more I/O overhead.\n * Set to `Infinity` to disable periodic fsync (fastest, but highest data-loss risk).\n */\n fsyncEvery?: number | undefined;\n events?: EventBus;\n traceId?: string;\n}\n\n/** Default number of writes between fsync calls. */\nconst DEFAULT_FSYNC_EVERY = 100;\n\nexport class ToolAuditLog {\n private readonly dir: string;\n private readonly events: EventBus | undefined;\n private readonly traceId: string | undefined;\n /** In-memory cache of the last entry's hash (per session), to compute chains efficiently. */\n private readonly tailHash = new Map<string, string>();\n /** In-memory counter for entry indices — avoids re-reading the file on every write. */\n private readonly tailIndex = new Map<string, number>();\n /**\n * File mtime+size recorded after our last write, per session. Used to\n * detect cross-process writes (session handoff, recovery) that would\n * invalidate the in-memory tail cache: if the stat no longer matches\n * we re-read the file to re-establish the chain tip before appending.\n */\n private readonly tailStat = new Map<string, { mtimeMs: number; size: number }>();\n /** Tracks writes since last fsync, per session. */\n private readonly unSyncedWrites = new Map<string, number>();\n private readonly writeChains = new Map<string, Promise<void>>();\n private readonly fsyncEvery: number;\n\n constructor(opts: ToolAuditLogOptions) {\n this.dir = opts.dir;\n this.events = opts.events;\n this.traceId = opts.traceId;\n this.fsyncEvery = opts.fsyncEvery ?? DEFAULT_FSYNC_EVERY;\n }\n\n /**\n * Append a tool call/result pair to the chain. Returns the\n * resulting entry. Idempotency is not guaranteed — if you\n * record the same tool_use twice you get two entries. That's\n * intentional: the audit log is a record, not a cache.\n */\n async record(input: {\n sessionId: string;\n toolName: string;\n toolUseId: string;\n input: unknown;\n output: unknown;\n isError: boolean;\n }): Promise<AuditEntry> {\n let entry!: AuditEntry; // assigned inside the enqueue callback\n const fp = this.filePath(input.sessionId);\n const t0 = Date.now();\n try {\n await this.enqueue(input.sessionId, async () => {\n await withFileLock(fp, async () => {\n // Resolve the chain tip from the in-memory cache when possible,\n // re-reading the file only on first contact or when an external\n // writer (cross-process session handoff) changed it under us.\n // The previous implementation did `readAll` on every single\n // record just to find `entries.at(-1)` — a full parse of the\n // audit file per tool call.\n const tip = await this._resolveChainTip(input.sessionId, fp);\n const prevHash = tip.prevHash;\n const index = tip.nextIndex;\n\n const id = randomUUID();\n const ts = new Date().toISOString();\n const content = {\n id,\n ts,\n prevHash,\n toolName: input.toolName,\n toolUseId: input.toolUseId,\n input: input.input,\n output: input.output,\n isError: input.isError,\n index,\n };\n const hash = createHash('sha256').update(stableStringify(content), 'utf8').digest('hex');\n entry = {\n id,\n ts,\n prevHash,\n hash,\n toolName: input.toolName,\n toolUseId: input.toolUseId,\n input: input.input,\n output: input.output,\n isError: input.isError,\n index,\n };\n\n // True O(1) append — one line, no full-file rewrite. The previous\n // `writeAll(entries)` path re-serialized every entry on every\n // record; a 1000-call session rewrote a multi-MB audit file 1000\n // times (quadratic in session length). `withFileLock` above\n // guarantees no concurrent writer interleaves with our append.\n await fs.appendFile(fp, JSON.stringify(entry) + '\\n', 'utf8');\n\n // Refresh caches + fsync bookkeeping. We stat post-write so the\n // mtime+size tracker reflects the just-appended line — the next\n // record can trust the cache without re-reading.\n try {\n const st = await fs.stat(fp);\n this.tailStat.set(input.sessionId, { mtimeMs: st.mtimeMs, size: st.size });\n } catch {\n /* best-effort; next record will just re-read */\n }\n this.tailHash.set(input.sessionId, hash);\n this.tailIndex.set(input.sessionId, index + 1);\n await this._trackUnsynced(input.sessionId, fp);\n\n const durationMs = Date.now() - t0;\n this.events?.emit('storage.write', {\n sessionId: input.sessionId,\n store: 'audit',\n filePath: fp,\n operation: 'record',\n outcome: 'success',\n durationMs,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n });\n });\n return entry;\n } catch (err) {\n this.events?.emit('storage.error', {\n sessionId: input.sessionId,\n store: 'audit',\n filePath: fp,\n operation: 'record',\n outcome: 'failure',\n error: toErrorMessage(err),\n recoverable: false,\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n throw err;\n }\n }\n\n /**\n * Resolve the chain tip (previous hash + next index) for an append.\n * Uses the in-memory `tailHash`/`tailIndex` cache when the file's\n * stat matches our last known write; falls back to a full read on\n * cache miss or when an external writer has extended the file.\n */\n private async _resolveChainTip(\n sessionId: string,\n fp: string,\n ): Promise<{ prevHash: string; nextIndex: number }> {\n const cachedHash = this.tailHash.get(sessionId);\n const cachedIndex = this.tailIndex.get(sessionId);\n const cachedStat = this.tailStat.get(sessionId);\n\n if (cachedHash !== undefined && cachedIndex !== undefined && cachedStat) {\n // Verify no other process appended since our last write. Stat is a\n // single inode lookup; the common case (same-process sequential\n // writes) returns immediately and we skip the full read.\n try {\n const st = await fs.stat(fp);\n if (st.mtimeMs === cachedStat.mtimeMs && st.size === cachedStat.size) {\n return { prevHash: cachedHash, nextIndex: cachedIndex };\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n // File was removed out from under us — reset and start a new chain.\n this.tailHash.delete(sessionId);\n this.tailIndex.delete(sessionId);\n this.tailStat.delete(sessionId);\n return { prevHash: GENESIS_PREV, nextIndex: 0 };\n }\n /* v8 ignore next -- defensive: a non-ENOENT stat failure during cache-hit is rare */\n throw err;\n }\n }\n\n // Cache miss or external write detected — read the true tail.\n const entries = await this.readAll(sessionId);\n const prev = entries.at(-1);\n const prevHash = prev?.hash ?? GENESIS_PREV;\n const nextIndex = prev ? prev.index + 1 : 0;\n this.tailHash.set(sessionId, prevHash);\n this.tailIndex.set(sessionId, nextIndex);\n try {\n const st = await fs.stat(fp);\n this.tailStat.set(sessionId, { mtimeMs: st.mtimeMs, size: st.size });\n } catch {\n /* leave cache empty; next record re-reads */\n }\n return { prevHash, nextIndex };\n }\n\n /**\n * Walk the chain and verify every entry's hash and prevHash.\n * Returns a structured verdict — never throws.\n */\n async verify(sessionId: string): Promise<VerifyResult> {\n const fp = this.filePath(sessionId);\n const t0 = Date.now();\n let entries: AuditEntry[];\n try {\n entries = await this.readAll(sessionId);\n } catch (err) {\n // The file exists but can't be read (permissions, corruption). We\n // can't verify it, so emit a read failure for observability and\n // degrade gracefully — this method's contract is \"never throws\".\n this.events?.emit('storage.read', {\n sessionId,\n store: 'audit',\n filePath: fp,\n operation: 'verify',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: toErrorMessage(err),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return { ok: true, entries: 0 };\n }\n\n // Walk the chain into a verdict, then emit a single storage.read whose\n // outcome reflects the verification result (a broken chain is a failure).\n const verdict = ((): VerifyResult => {\n if (entries.length === 0) return { ok: true, entries: 0 };\n // The first entry's prevHash must be the all-zeros genesis marker.\n if (entries[0]?.prevHash !== GENESIS_PREV) {\n return {\n ok: false,\n brokenAt: 0,\n reason: 'first entry is not the genesis (prevHash != 0…0)',\n };\n }\n let prevHash = GENESIS_PREV;\n for (let i = 0; i < entries.length; i++) {\n const e = expectDefined(entries[i]);\n if (e.prevHash !== prevHash) {\n return {\n ok: false,\n brokenAt: i,\n reason: `prevHash mismatch at entry ${i} (expected ${prevHash.slice(0, 8)}…, got ${e.prevHash.slice(0, 8)}…)`,\n };\n }\n // Recompute the hash from the entry's content (without the\n // `hash` field itself, which is what we are verifying).\n const content = {\n id: e.id,\n ts: e.ts,\n prevHash: e.prevHash,\n toolName: e.toolName,\n toolUseId: e.toolUseId,\n input: e.input,\n output: e.output,\n isError: e.isError,\n index: e.index,\n };\n const expectedHash = createHash('sha256')\n .update(stableStringify(content), 'utf8')\n .digest('hex');\n if (expectedHash !== e.hash) {\n return {\n ok: false,\n brokenAt: i,\n reason: `hash mismatch at entry ${i} (entry content was modified)`,\n };\n }\n prevHash = e.hash;\n }\n return { ok: true, entries: entries.length };\n })();\n\n this.events?.emit('storage.read', {\n sessionId,\n store: 'audit',\n filePath: fp,\n operation: 'verify',\n outcome: verdict.ok ? 'success' : 'failure',\n durationMs: Date.now() - t0,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return verdict;\n }\n\n /** All entries for a session, in insertion order. */\n async load(sessionId: string): Promise<AuditEntry[]> {\n const fp = this.filePath(sessionId);\n const t0 = Date.now();\n try {\n const entries = await this.readAll(sessionId);\n const durationMs = Date.now() - t0;\n this.events?.emit('storage.read', {\n sessionId,\n store: 'audit',\n filePath: fp,\n operation: 'load',\n outcome: 'success',\n durationMs,\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n return entries;\n } catch (err) {\n const durationMs = Date.now() - t0;\n this.events?.emit('storage.read', {\n sessionId,\n store: 'audit',\n filePath: fp,\n operation: 'load',\n outcome: 'failure',\n durationMs,\n error: toErrorMessage(err),\n ...(this.traceId !== undefined ? { traceId: this.traceId } : {}),\n });\n throw err;\n }\n }\n\n // ── Internals ────────────────────────────────────────────────────────────\n\n private filePath(sessionId: string): string {\n // Containment-checked: date-sharded ids (\"2026-06-11/<base>\") are\n // legitimate; traversal is rejected. A plain slash ban would throw\n // for every modern session id the moment record() gets wired in.\n return sessionScopedPath(this.dir, sessionId, '.audit.jsonl');\n }\n\n private async readAll(sessionId: string): Promise<AuditEntry[]> {\n const fp = this.filePath(sessionId);\n try {\n const raw = await fs.readFile(fp, 'utf8');\n const out: AuditEntry[] = [];\n for (const line of raw.split('\\n')) {\n if (!line.trim()) continue;\n try {\n const parsed = safeParse<AuditEntry>(line);\n if (parsed.ok && parsed.value) out.push(parsed.value);\n } catch {\n // Skip corrupt lines — audit data is meta, not fatal.\n }\n }\n return out;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return [];\n // Non-ENOENT errors (EACCES, ENOSPC, etc.) are real I/O failures —\n // re-throw so callers (verify, load) can emit storage.error.\n throw err;\n }\n }\n\n /**\n * Tracks writes since last fsync and triggers periodic fsync.\n * Called after each O(1) append to maintain the same durability\n * guarantees as the old writeAll approach.\n */\n private async _trackUnsynced(sessionId: string, fp: string): Promise<void> {\n const count = (this.unSyncedWrites.get(sessionId) ?? 0) + 1;\n this.unSyncedWrites.set(sessionId, count);\n if (this.fsyncEvery !== Number.POSITIVE_INFINITY && count % this.fsyncEvery === 0) {\n await this.sync(sessionId, fp);\n }\n }\n\n /**\n * Explicitly sync the file to disk. Called automatically every\n * `fsyncEvery` writes, and available for callers who want to\n * force a sync before closing or during graceful shutdown.\n */\n async flush(sessionId: string): Promise<void> {\n await this.sync(sessionId, this.filePath(sessionId));\n }\n\n private async sync(sessionId: string, fp: string): Promise<void> {\n try {\n const fh = await fs.open(fp, 'r+');\n try {\n await fh.sync();\n } finally {\n await fh.close();\n }\n } catch {\n // fsync is best-effort; a failure here does not corrupt the chain.\n } finally {\n this.unSyncedWrites.set(sessionId, 0);\n }\n }\n\n private enqueue(sessionId: string, fn: () => Promise<void>): Promise<void> {\n const prev = this.writeChains.get(sessionId) ?? Promise.resolve();\n const next = prev.then(fn, fn);\n this.writeChains.set(\n sessionId,\n next.catch(() => undefined),\n );\n return next;\n }\n}\n\nfunction stableStringify(value: unknown): string {\n return JSON.stringify(sortKeys(value));\n}\n\nfunction sortKeys(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortKeys);\n if (value && typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(obj).sort()) {\n sorted[key] = sortKeys(obj[key]);\n }\n return sorted;\n }\n return value;\n}\n","import type { SessionEvent } from '../types/session.js';\n\nexport interface QueryFilter {\n eventTypes?: string[] | undefined;\n toolNames?: string[] | undefined;\n timeRange?: { start: string; end: string } | undefined;\n}\n\nexport interface ToolInvocation {\n ts: string;\n name: string;\n input: unknown;\n output?: unknown | undefined;\n error?: string | undefined;\n durationMs: number;\n}\n\nexport interface SessionError {\n ts: string;\n phase: string;\n message: string;\n}\n\nexport interface ModeChange {\n ts: string;\n from: string;\n to: string;\n}\n\nexport interface TaskSummary {\n taskId: string;\n title: string;\n status: string;\n createdAt: string;\n completedAt?: string | undefined;\n}\n\nexport interface SessionAnalysis {\n sessionId: string;\n totalDuration: number;\n toolUsageCount: Record<string, number>;\n errorCount: number;\n modeChanges: ModeChange[];\n tasks: TaskSummary[];\n}\n\nexport class SessionAnalyzer {\n analyze(events: SessionEvent[]): SessionAnalysis {\n const toolUsageCount: Record<string, number> = {};\n const errors: SessionError[] = [];\n const modeChanges: ModeChange[] = [];\n const tasksById = new Map<string, TaskSummary>();\n let sessionId = '';\n\n for (const event of events) {\n // sessionId comes from session_start / session_resumed.\n if (event.type === 'session_start' || event.type === 'session_resumed') {\n if (!sessionId) sessionId = event.id;\n }\n if (event.type === 'tool_use') {\n toolUsageCount[event.name] = (toolUsageCount[event.name] ?? 0) + 1;\n }\n if (event.type === 'error') {\n errors.push({ ts: event.ts, phase: event.phase, message: event.message });\n }\n if (event.type === 'mode_changed') {\n modeChanges.push({ ts: event.ts, from: event.from, to: event.to });\n }\n if (event.type === 'task_created') {\n tasksById.set(event.taskId, {\n taskId: event.taskId,\n title: event.title,\n status: 'created',\n createdAt: event.ts,\n });\n }\n if (event.type === 'task_updated') {\n const t = tasksById.get(event.taskId);\n if (t) t.status = event.status;\n }\n if (event.type === 'task_completed') {\n const t = tasksById.get(event.taskId);\n if (t) {\n t.status = 'completed';\n t.completedAt = event.ts;\n } else {\n tasksById.set(event.taskId, {\n taskId: event.taskId,\n title: event.title,\n status: 'completed',\n createdAt: event.ts,\n completedAt: event.ts,\n });\n }\n }\n if (event.type === 'task_failed') {\n const t = tasksById.get(event.taskId);\n if (t) {\n t.status = 'failed';\n t.completedAt = event.ts;\n } else {\n tasksById.set(event.taskId, {\n taskId: event.taskId,\n title: event.title,\n status: 'failed',\n createdAt: event.ts,\n completedAt: event.ts,\n });\n }\n }\n }\n\n return {\n sessionId,\n totalDuration: this.calcDuration(events),\n toolUsageCount,\n errorCount: errors.length,\n modeChanges,\n tasks: Array.from(tasksById.values()),\n };\n }\n\n query(events: SessionEvent[], filter: QueryFilter): SessionEvent[] {\n return events.filter((e) => {\n if (filter.eventTypes?.length && !filter.eventTypes.includes(e.type)) return false;\n if (filter.toolNames?.length && e.type === 'tool_use') {\n const toolEvent = e as { type: 'tool_use'; name: string };\n if (!filter.toolNames.includes(toolEvent.name)) return false;\n }\n if (filter.timeRange) {\n const ts = new Date(e.ts).getTime();\n const start = new Date(filter.timeRange.start).getTime();\n const end = new Date(filter.timeRange.end).getTime();\n if (ts < start || ts > end) return false;\n }\n return true;\n });\n }\n\n private calcDuration(events: SessionEvent[]): number {\n if (events.length < 2) return 0;\n const firstEvent = events[0];\n const lastEvent = events[events.length - 1];\n /* v8 ignore next -- defensive: length>=2 guard above guarantees both ends exist */\n if (!firstEvent || !lastEvent) return 0;\n const first = new Date(firstEvent.ts).getTime();\n const last = new Date(lastEvent.ts).getTime();\n return last - first;\n }\n}\n","/**\n * SessionRegistry — cross-process session and agent tracker.\n *\n * Each WrongStack process registers its session on start and updates its\n * status periodically. The registry is a single JSON file at\n * `~/.wrongstack/session-registry.json`. Entries are keyed by session ID.\n *\n * Because multiple processes may write concurrently, every write is an\n * atomic read-modify-write protected by a per-file advisory lock (flock on\n * Unix, exclusive open on Windows). Stale entries (process no longer alive)\n * are pruned on every read.\n *\n * @module session-registry\n */\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { randomUUID } from 'node:crypto';\n\n// ── Types ─────────────────────────────────────────────────────────────────\n\n/** Live status of a single agent within a session. */\nexport type AgentLiveStatus =\n | 'idle'\n | 'running'\n | 'streaming'\n | 'waiting_user' // brain.ask_human, confirm prompt\n | 'error';\n\nexport interface AgentEntry {\n /** Unique agent id (ULID or UUID). */\n id: string;\n /** Human-readable label (e.g. \"leader\", \"bug-hunter #1\"). */\n name: string;\n /** UTC ISO timestamp when this agent/run started, when known. */\n startedAt?: string | undefined;\n status: AgentLiveStatus;\n /** Current tool name if running, undefined otherwise. */\n currentTool?: string | undefined;\n /** Iteration count so far. */\n iterations: number;\n /** Tool calls so far. */\n toolCalls: number;\n /** Cumulative cost in USD for this agent, when known. */\n costUsd?: number | undefined;\n /** Cumulative input tokens, when known. */\n tokensIn?: number | undefined;\n /** Cumulative output tokens, when known. */\n tokensOut?: number | undefined;\n /** Context window fill 0–100 (may exceed 100 when over limit), when known. */\n ctxPct?: number | undefined;\n /** Model id this agent is running on, when known. */\n model?: string | undefined;\n /**\n * Tail of the assistant text currently being streamed (capped, throttled).\n * Lets a cross-process watcher see the response form in near-real-time\n * instead of waiting for the completed turn to land in the session log.\n */\n partialText?: string | undefined;\n /** UTC ISO timestamp of last activity. */\n lastActivityAt: string;\n}\n\nexport type SessionLiveStatus =\n | 'active' // process running, agents may be idle or busy\n | 'idle' // process running, no agent activity\n | 'closing' // session_end written, process shutting down\n | 'stale'; // process no longer alive (pruned on next read)\n\nexport interface SessionRegistryEntry {\n sessionId: string;\n projectSlug: string;\n projectRoot: string;\n projectName: string;\n workingDir: string;\n /**\n * Which surface owns this session — `'tui'` / `'webui'` / `'cli'` (one-shot or\n * REPL). Lets cross-process consumers (e.g. the WebUI Fleet HQ office map) label\n * each live session by client kind. Optional for back-compat with older entries.\n */\n clientType?: 'tui' | 'webui' | 'cli' | 'repl' | string | undefined;\n /** Current git branch, if the project is a git repo. Detected at registration. */\n gitBranch?: string | undefined;\n status: SessionLiveStatus;\n pid: number;\n /** UTC ISO */\n startedAt: string;\n /** UTC ISO — updated on every heartbeat */\n lastHeartbeatAt: string;\n /** Count of tracked agents */\n agentCount: number;\n agents: AgentEntry[];\n}\n\n// ── Constants ─────────────────────────────────────────────────────────────\n\nconst REGISTRY_FILE = 'session-registry.json';\nconst HEARTBEAT_INTERVAL_MS = 5_000;\nconst STALE_TIMEOUT_MS = 30_000; // entry considered stale after 30s without heartbeat\n// A session that announced `closing` (heartbeat stopped) is dropped this long\n// after its last heartbeat, so the fleet view doesn't keep a dead client around.\nconst CLOSING_GRACE_MS = 15_000;\n// A held lock is released within milliseconds; anything older is a crashed\n// owner's leftover and is safe to break so writes never wedge permanently.\nconst STALE_LOCK_MS = 10_000;\nconst STALE_TMP_MS = 60_000;\nconst MAX_STALE_TMP_FILES = 20;\n\n// ── Helpers ───────────────────────────────────────────────────────────────\n\nfunction pidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n// ── Registry class ────────────────────────────────────────────────────────\n\nexport class SessionRegistry {\n private readonly filePath: string;\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private currentSessionId: string | null = null;\n /**\n * Last full entry this process registered. Kept so the heartbeat can\n * re-create our entry if it ever goes missing — e.g. our initial register()\n * write was dropped (a wedged lock), the file was reset, or we were pruned.\n */\n private lastEntry: SessionRegistryEntry | null = null;\n\n constructor(globalRoot: string) {\n this.filePath = path.join(globalRoot, REGISTRY_FILE);\n }\n\n // ── Public API ──────────────────────────────────────────────────────────\n\n /**\n * Register the current session. Call once on session start.\n * Starts the heartbeat timer.\n */\n async register(\n entry: Omit<SessionRegistryEntry, 'status' | 'lastHeartbeatAt' | 'agentCount' | 'agents'> & {\n agents?: AgentEntry[] | undefined;\n },\n ): Promise<void> {\n // Safe to call again on a project switch: the WebUI re-roots in place and\n // creates a fresh session id pointing at the new project. Clear the prior\n // heartbeat timer (otherwise each switch leaks a timer that keeps writing).\n // A process owns exactly one entry, so the same-pid dedup below drops our\n // own previous entry — the registry never carries a phantom session still\n // pointing at the old project's root/workingDir.\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n this.currentSessionId = entry.sessionId;\n const full: SessionRegistryEntry = {\n ...entry,\n status: 'active',\n lastHeartbeatAt: new Date().toISOString(),\n agentCount: entry.agents?.length ?? 0,\n agents: entry.agents ?? [],\n };\n this.lastEntry = full;\n await this.atomicUpdate((registry) => {\n // Prune dead entries that haven't heartbeated recently.\n // A just-created entry has no heartbeat yet — don't prune it.\n const now = Date.now();\n for (const [id, existing] of Object.entries(registry)) {\n if (existing.pid === entry.pid) {\n // Our own process owns exactly one entry. When re-registering under\n // a new session id (project switch re-roots in place), drop the\n // stale same-pid entry so it doesn't linger pointing at the old\n // project's root/workingDir.\n if (id !== entry.sessionId) delete registry[id];\n continue;\n }\n const heartbeatAge = now - new Date(existing.lastHeartbeatAt).getTime();\n if (heartbeatAge > STALE_TIMEOUT_MS && !pidAlive(existing.pid)) {\n delete registry[id];\n }\n }\n registry[entry.sessionId] = full;\n });\n\n // Start heartbeat\n this.heartbeatTimer = setInterval(() => {\n void this.heartbeat();\n }, HEARTBEAT_INTERVAL_MS);\n if (this.heartbeatTimer.unref) this.heartbeatTimer.unref();\n }\n\n /**\n * Update agent status for the current session. Call on every\n * significant status change (agent start, tool start, user wait, error).\n */\n async updateAgents(agents: AgentEntry[]): Promise<void> {\n if (!this.currentSessionId) return;\n // Derive session status from the agent collective.\n const hasRunning = agents.some((a) => a.status === 'running' || a.status === 'streaming');\n const hasWaiting = agents.some((a) => a.status === 'waiting_user');\n const hasError = agents.some((a) => a.status === 'error');\n const status: SessionLiveStatus = hasRunning || hasWaiting || hasError ? 'active' : 'idle';\n const nowIso = new Date().toISOString();\n\n // Keep the cached entry current so a heartbeat re-insert carries live agents.\n if (this.lastEntry) {\n this.lastEntry.agents = agents;\n this.lastEntry.agentCount = agents.length;\n this.lastEntry.status = status;\n this.lastEntry.lastHeartbeatAt = nowIso;\n }\n\n await this.atomicUpdate((registry) => {\n let entry = registry[this.currentSessionId!];\n if (!entry) {\n // Our entry vanished (dropped write / reset / pruned) — re-create it.\n if (!this.lastEntry) return;\n entry = { ...this.lastEntry };\n registry[this.currentSessionId!] = entry;\n }\n entry.agents = agents;\n entry.agentCount = agents.length;\n entry.status = status;\n entry.lastHeartbeatAt = nowIso;\n });\n }\n\n /**\n * Mark the session as closing. Called during shutdown.\n * Stops the heartbeat timer.\n */\n async markClosing(): Promise<void> {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n if (!this.currentSessionId) return;\n await this.atomicUpdate((registry) => {\n const entry = registry[this.currentSessionId!];\n if (!entry) return;\n entry.status = 'closing';\n entry.lastHeartbeatAt = new Date().toISOString();\n });\n }\n\n /**\n * Remove the current session from the registry. Call on clean exit.\n */\n async unregister(): Promise<void> {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n if (!this.currentSessionId) return;\n const sid = this.currentSessionId;\n this.currentSessionId = null;\n await this.atomicUpdate((registry) => {\n delete registry[sid];\n });\n }\n\n /**\n * List all non-stale sessions. Prunes stale entries automatically.\n */\n async list(): Promise<SessionRegistryEntry[]> {\n const registry = await this.readAndPrune();\n return Object.values(registry);\n }\n\n /**\n * Get a single session entry by ID. Returns undefined if not found or stale.\n */\n async get(sessionId: string): Promise<SessionRegistryEntry | undefined> {\n const registry = await this.readAndPrune();\n return registry[sessionId];\n }\n\n /**\n * List all sessions for a specific project (by slug).\n */\n async listByProject(projectSlug: string): Promise<SessionRegistryEntry[]> {\n const all = await this.list();\n return all.filter((e) => e.projectSlug === projectSlug);\n }\n\n /**\n * Return the registry file path. Useful for WebUI to watch/read.\n */\n get registryPath(): string {\n return this.filePath;\n }\n\n // ── Internal ────────────────────────────────────────────────────────────\n\n private async heartbeat(): Promise<void> {\n if (!this.currentSessionId) return;\n try {\n const sessionId = this.currentSessionId;\n const nowIso = new Date().toISOString();\n await this.atomicUpdate((registry) => {\n const entry = registry[sessionId];\n if (entry) {\n entry.lastHeartbeatAt = nowIso;\n // Status bound: if closing, don't revert\n if (entry.status !== 'closing') {\n const hasRunning = (entry.agents ?? []).some(\n (a) => a.status === 'running' || a.status === 'streaming',\n );\n entry.status = hasRunning ? 'active' : 'idle';\n }\n return;\n }\n if (this.lastEntry) {\n // Our entry is gone (initial register() dropped on a wedged lock, file\n // reset, or pruned). Re-create it through the locked path so a process\n // that booted into a broken registry still shows up once it heals.\n registry[sessionId] = { ...this.lastEntry, lastHeartbeatAt: nowIso };\n }\n });\n } catch {\n // Best-effort heartbeat — never throw\n }\n }\n\n private async readAndPrune(): Promise<Record<string, SessionRegistryEntry>> {\n try {\n const raw = await fs.readFile(this.filePath, 'utf8');\n const registry = JSON.parse(raw) as Record<string, SessionRegistryEntry>;\n const now = Date.now();\n let pruned = false;\n\n for (const [id, entry] of Object.entries(registry)) {\n const heartbeatAge = now - new Date(entry.lastHeartbeatAt).getTime();\n // Cleanly-closed session: drop after a short grace (handles both a fully\n // exited process and one still alive but done) so no dead client lingers.\n if (entry.status === 'closing' && heartbeatAge > CLOSING_GRACE_MS) {\n delete registry[id];\n pruned = true;\n continue;\n }\n if (heartbeatAge > STALE_TIMEOUT_MS && !pidAlive(entry.pid)) {\n entry.status = 'stale';\n // Keep stale entries for 5 minutes so UIs can show \"recently closed\"\n const startedAge = now - new Date(entry.startedAt).getTime();\n if (startedAge > 5 * 60_000) {\n delete registry[id];\n pruned = true;\n }\n }\n }\n\n if (pruned) {\n await this.writeAtomic(registry).catch(() => undefined);\n }\n\n return registry;\n } catch {\n return {};\n }\n }\n\n private async atomicUpdate(\n fn: (registry: Record<string, SessionRegistryEntry>) => void,\n ): Promise<void> {\n const lockPath = `${this.filePath}.lock`;\n const maxRetries = 8;\n const retryDelayMs = 20;\n\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n // Ensure directory exists\n await fs.mkdir(path.dirname(this.filePath), { recursive: true });\n\n // Acquire exclusive lock via O_CREAT | O_EXCL\n let lockHandle = await fs.open(lockPath, 'wx').catch(() => null);\n if (!lockHandle) {\n // Lock contended. A crashed process can leave its lock file behind\n // forever (the `finally` unlink never ran), which would wedge EVERY\n // future write — the registry silently stops updating. Break the lock\n // when its owner pid is dead or it has been held implausibly long\n // (legit holds are sub-millisecond), then retry the open once.\n if (await this.breakStaleLock(lockPath)) {\n lockHandle = await fs.open(lockPath, 'wx').catch(() => null);\n }\n if (!lockHandle) {\n await new Promise((r) => setTimeout(r, retryDelayMs * (attempt + 1)));\n continue;\n }\n }\n\n try {\n // Stamp the owner pid so other processes can detect a stale lock.\n await lockHandle.writeFile(String(process.pid)).catch(() => undefined);\n const raw = await fs.readFile(this.filePath, 'utf8').catch(() => '{}');\n const registry = JSON.parse(raw) as Record<string, SessionRegistryEntry>;\n fn(registry);\n await this.writeAtomicLocked(registry);\n return; // success\n } finally {\n await lockHandle.close();\n await fs.unlink(lockPath).catch(() => undefined);\n }\n } catch {\n // Best-effort — never throw from registry writes\n return;\n }\n }\n // All retries exhausted — registry update dropped (non-critical)\n }\n\n /**\n * Break a contended lock if it is stale: the recorded owner pid is no longer\n * alive, or the lock is older than {@link STALE_LOCK_MS}. Returns true when the\n * lock was removed (caller should retry acquisition). Best-effort and\n * race-tolerant — a fresh lock (age ~0, live owner) is never broken, so the\n * common concurrent case self-heals on the next heartbeat.\n */\n private async breakStaleLock(lockPath: string): Promise<boolean> {\n try {\n const [stat, content] = await Promise.all([\n fs.stat(lockPath),\n fs.readFile(lockPath, 'utf8').catch(() => ''),\n ]);\n const ageMs = Date.now() - stat.mtimeMs;\n const ownerPid = Number.parseInt(content.trim(), 10);\n const ownerDead =\n Number.isInteger(ownerPid) && ownerPid > 0 && ownerPid !== process.pid && !pidAlive(ownerPid);\n if (ownerDead || ageMs > STALE_LOCK_MS) {\n await fs.unlink(lockPath).catch(() => undefined);\n return true;\n }\n return false;\n } catch {\n // stat failed → the lock vanished underneath us; let the caller retry.\n return true;\n }\n }\n\n private async writeAtomicLocked(registry: Record<string, SessionRegistryEntry>): Promise<void> {\n await this.pruneStaleTempFiles();\n await this.writeAtomicFile(registry);\n }\n\n /** Legacy write without lock — used by heartbeat for performance. */\n private async writeAtomic(registry: Record<string, SessionRegistryEntry>): Promise<void> {\n await this.pruneStaleTempFiles();\n await this.writeAtomicFile(registry);\n }\n\n private async writeAtomicFile(registry: Record<string, SessionRegistryEntry>): Promise<void> {\n const tmp = path.join(\n path.dirname(this.filePath),\n `.${path.basename(this.filePath)}.${randomUUID().slice(0, 8)}.tmp`,\n );\n try {\n await fs.writeFile(tmp, JSON.stringify(registry, null, 2), 'utf8');\n await fs.rename(tmp, this.filePath);\n } catch (err) {\n await fs.unlink(tmp).catch(() => undefined);\n throw err;\n }\n }\n\n private async pruneStaleTempFiles(): Promise<void> {\n try {\n const dir = path.dirname(this.filePath);\n const base = path.basename(this.filePath);\n const now = Date.now();\n const stale: Array<{ name: string; mtimeMs: number }> = [];\n\n for (const name of await fs.readdir(dir)) {\n const isTemp =\n (name.startsWith(`${base}.`) || name.startsWith(`.${base}.`)) && name.endsWith('.tmp');\n if (!isTemp) continue;\n const stat = await fs.stat(path.join(dir, name)).catch(() => null);\n if (!stat) continue;\n if (now - stat.mtimeMs > STALE_TMP_MS) stale.push({ name, mtimeMs: stat.mtimeMs });\n }\n\n stale.sort((a, b) => b.mtimeMs - a.mtimeMs);\n await Promise.all(\n stale.slice(MAX_STALE_TMP_FILES).map(async ({ name }) => {\n await fs.unlink(path.join(dir, name)).catch(() => undefined);\n }),\n );\n } catch {\n // best-effort cleanup must not block registry heartbeats\n }\n }\n}\n\n/** Singleton — created once per process. */\nlet _instance: SessionRegistry | null = null;\n\nexport function getSessionRegistry(globalRoot?: string): SessionRegistry {\n if (!_instance && globalRoot) {\n _instance = new SessionRegistry(globalRoot);\n }\n if (!_instance) {\n throw new Error('SessionRegistry not initialized. Call getSessionRegistry(globalRoot) first.');\n }\n return _instance;\n}\n\nexport function hasSessionRegistry(): boolean {\n return _instance !== null;\n}\n","/**\n * AgentStatusTracker — subscribes to EventBus events and keeps the\n * SessionRegistry updated with live agent status.\n *\n * Created once per process during boot. Listens for:\n * - agent.run.started / agent.run.completed → agent status changes\n * - tool.started / tool.executed → current tool tracking\n * - brain.ask_human → waiting_user status\n * - fleet events (subagent spawn/start/done) → agent entries\n *\n * @module agent-status-tracker\n */\nimport type { EventBus } from './kernel/events.js';\nimport type {\n AgentEntry,\n AgentLiveStatus,\n SessionRegistry,\n} from './session-registry.js';\n\n/** A finished (idle/error) subagent older than this is reaped from the fleet view. */\nconst AGENT_REAP_MS = 30_000;\n/** How often the reaper sweeps for finished subagents. */\nconst AGENT_SWEEP_INTERVAL_MS = 10_000;\n/** Max chars of streamed assistant text kept in the registry (the live tail). */\nconst PARTIAL_TEXT_CAP = 1200;\n/** Min gap between registry flushes triggered purely by streamed text. */\nconst PARTIAL_FLUSH_THROTTLE_MS = 300;\n\nfunction clampPct(pct: number): number {\n if (!Number.isFinite(pct)) return 0;\n return Math.max(0, Math.min(100, pct));\n}\n\nexport interface AgentStatusTrackerOptions {\n events: EventBus;\n registry: SessionRegistry;\n /** Session id whose live agent state is mirrored by this tracker. */\n sessionId?: string | (() => string | undefined) | undefined;\n /** Leader agent name shown in the registry. Default: \"leader\". */\n leaderName?: string | undefined;\n /**\n * Best-effort callback fired after each registry write settles. Used to nudge\n * local WebUI servers (FleetNotifier) so cross-process status reaches the map\n * without waiting on their file-watch/poll. Never block or throw.\n */\n onUpdate?: (() => void) | undefined;\n}\n\nexport class AgentStatusTracker {\n private readonly events: EventBus;\n private readonly registry: SessionRegistry;\n private readonly sessionId: string | (() => string | undefined) | undefined;\n private readonly leaderName: string;\n\n // Live agent map: agentId → AgentEntry\n private agents = new Map<string, AgentEntry>();\n // Last full agent list flushed (leader + subagents). Lets external consumers\n // read the current state synchronously without re-deriving it.\n private lastAgents: AgentEntry[] = [];\n\n // Leader tracking\n private leaderStatus: AgentLiveStatus = 'idle';\n private leaderCurrentTool: string | undefined;\n private leaderIterations = 0;\n private leaderToolCalls = 0;\n private leaderCostUsd = 0;\n private leaderTokensIn = 0;\n private leaderTokensOut = 0;\n private leaderCtxPct: number | undefined;\n private leaderModel: string | undefined;\n private leaderPartialText = '';\n private leaderStartedAt: string | undefined;\n\n private unsubscribers: Array<() => void> = [];\n private readonly onUpdate: (() => void) | undefined;\n private sweepTimer: ReturnType<typeof setInterval> | null = null;\n private partialTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(opts: AgentStatusTrackerOptions) {\n this.events = opts.events;\n this.registry = opts.registry;\n this.sessionId = opts.sessionId;\n this.leaderName = opts.leaderName ?? 'leader';\n this.onUpdate = opts.onUpdate;\n }\n\n /** Current full agent list (leader + subagents) as of the last flush. */\n getAgents(): AgentEntry[] {\n return this.lastAgents.length > 0 ? [...this.lastAgents] : [];\n }\n\n start(): void {\n const on = (\n pattern: string,\n fn: (event: string, payload: unknown) => void,\n ): (() => void) =>\n this.events.onPattern(pattern, (event, payload) => {\n if (!this.acceptsSession(payload)) return;\n fn(event, payload);\n });\n\n // Leader events\n this.unsubscribers.push(\n on('agent.run.started', (_event, payload) => {\n const p = payload as { at?: string; model?: string; ctx?: unknown } | undefined;\n this.markLeaderStarted(p?.at);\n this.captureLeaderContext(p?.ctx);\n if (p?.model) this.leaderModel = p.model;\n this.leaderStatus = 'running';\n this.leaderIterations++;\n this.flush();\n }),\n );\n\n // Capture the leader's model + context fill from each iteration's context.\n this.unsubscribers.push(\n on('iteration.started', (_e, payload) => {\n const p = payload as { ctx?: unknown; index?: number } | undefined;\n const ctx = p?.ctx;\n this.markLeaderStarted();\n this.leaderStatus = 'running';\n if (typeof p?.index === 'number') {\n this.leaderIterations = Math.max(this.leaderIterations, p.index + 1);\n }\n if (!ctx) {\n this.flush();\n return;\n }\n this.captureLeaderContext(ctx);\n this.flush();\n }),\n );\n\n this.unsubscribers.push(\n on('agent.run.completed', (_event, payload) => {\n const p = payload as { status?: string; ctx?: unknown } | undefined;\n this.captureLeaderContext(p?.ctx);\n this.leaderStatus = p?.status === 'failed' ? 'error' : 'idle';\n this.leaderCurrentTool = undefined;\n this.leaderPartialText = '';\n if (this.leaderStatus === 'idle') this.leaderStartedAt = undefined;\n this.flush();\n }),\n );\n\n this.unsubscribers.push(\n on('agent.run.error', (_event, payload) => {\n const p = payload as { ctx?: unknown } | undefined;\n this.captureLeaderContext(p?.ctx);\n this.leaderStatus = 'error';\n this.leaderCurrentTool = undefined;\n this.leaderPartialText = '';\n this.flush();\n }),\n );\n\n // Tool events — track current tool\n this.unsubscribers.push(\n on('tool.started', (_event, payload) => {\n const p = payload as { name?: string } | undefined;\n if (p?.name) {\n this.markLeaderStarted();\n this.leaderCurrentTool = p.name;\n this.leaderToolCalls++;\n }\n this.leaderStatus = 'running';\n this.flush();\n }),\n );\n\n this.unsubscribers.push(\n on('tool.executed', () => {\n this.leaderCurrentTool = undefined;\n this.flush();\n }),\n );\n\n // Brain ask_human → waiting for user input\n this.unsubscribers.push(\n on('brain.ask_human', () => {\n this.markLeaderStarted();\n this.leaderStatus = 'waiting_user';\n this.flush();\n }),\n );\n\n // Streaming events\n this.unsubscribers.push(\n on('llm.stream_started', () => {\n this.markLeaderStarted();\n this.leaderStatus = 'streaming';\n // A new response is starting — drop the previous turn's live tail.\n this.leaderPartialText = '';\n this.flush();\n }),\n );\n\n // Live assistant text — accumulate the streamed tail so a cross-process\n // watcher sees the response form. Flushed on a throttle, NOT per token\n // (text_delta fires once per chunk → would thrash the shared registry).\n this.unsubscribers.push(\n on('provider.text_delta', (_e, payload) => {\n const p = payload as { text?: string; ctx?: unknown } | undefined;\n const text = p?.text;\n if (!text) return;\n this.markLeaderStarted();\n this.captureLeaderContext(p?.ctx);\n this.leaderStatus = 'streaming';\n const next = this.leaderPartialText + text;\n this.leaderPartialText =\n next.length > PARTIAL_TEXT_CAP ? next.slice(next.length - PARTIAL_TEXT_CAP) : next;\n this.schedulePartialFlush();\n }),\n );\n\n this.unsubscribers.push(\n on('provider.response', (_e, payload) => {\n const p = payload as { ctx?: unknown } | undefined;\n this.captureLeaderContext(p?.ctx);\n this.flush();\n }),\n );\n\n this.unsubscribers.push(\n on('provider.fallback', (_e, payload) => {\n const p = payload as { to?: { providerId?: string; model?: string } } | undefined;\n if (p?.to?.model) {\n this.leaderModel = p.to.providerId\n ? `${p.to.providerId}/${p.to.model}`\n : p.to.model;\n this.flush();\n }\n }),\n );\n\n this.unsubscribers.push(\n on('ctx.pct', (_e, payload) => {\n const p = payload as { load?: number } | undefined;\n if (typeof p?.load === 'number' && Number.isFinite(p.load)) {\n this.leaderCtxPct = clampPct(Math.round(p.load * 100));\n this.flush();\n }\n }),\n );\n\n // Leader token + cost accounting (per provider call — accumulate).\n this.unsubscribers.push(\n on('token.accounted', (_e, payload) => {\n const p = payload as\n | { usage?: { input?: number; output?: number }; cost?: { total?: number } }\n | undefined;\n if (!p) return;\n this.leaderTokensIn += p.usage?.input ?? 0;\n this.leaderTokensOut += p.usage?.output ?? 0;\n this.leaderCostUsd += p.cost?.total ?? 0;\n this.flush();\n }),\n );\n\n // ── Subagent tracking ──────────────────────────────────────────────\n // These are the real fleet lifecycle events (emitted by MultiAgentHost /\n // the subagent runner / director). The previous code listened to a\n // `fleet.subagent.*` namespace that nothing emits, so subagents never\n // reached the registry — only the leader showed up.\n const touch = (id: string): AgentEntry => {\n let entry = this.agents.get(id);\n if (!entry) {\n const now = new Date().toISOString();\n entry = { id, name: id, status: 'idle', iterations: 0, toolCalls: 0, startedAt: now, lastActivityAt: now };\n this.agents.set(id, entry);\n }\n entry.lastActivityAt = new Date().toISOString();\n return entry;\n };\n\n this.unsubscribers.push(\n on('subagent.spawned', (_e, payload) => {\n const p = payload as { subagentId?: string; name?: string; model?: string } | undefined;\n if (!p?.subagentId) return;\n const entry = touch(p.subagentId);\n entry.name = p.name?.trim() || entry.name;\n if (p.model) entry.model = p.model;\n if (!entry.startedAt) entry.startedAt = new Date().toISOString();\n entry.status = 'running';\n this.flush();\n }),\n );\n\n this.unsubscribers.push(\n on('subagent.ctx_pct', (_e, payload) => {\n const p = payload as { subagentId?: string; load?: number } | undefined;\n if (!p?.subagentId) return;\n const entry = touch(p.subagentId);\n if (typeof p.load === 'number') entry.ctxPct = clampPct(Math.round(p.load * 100));\n this.flush();\n }),\n );\n\n this.unsubscribers.push(\n on('subagent.task_started', (_e, payload) => {\n const p = payload as { subagentId?: string } | undefined;\n if (!p?.subagentId) return;\n const entry = touch(p.subagentId);\n entry.status = 'running';\n if (!entry.startedAt) entry.startedAt = new Date().toISOString();\n entry.iterations++;\n this.flush();\n }),\n );\n\n this.unsubscribers.push(\n on('subagent.tool_executed', (_e, payload) => {\n const p = payload as { subagentId?: string; name?: string } | undefined;\n if (!p?.subagentId) return;\n const entry = touch(p.subagentId);\n entry.status = 'running';\n if (!entry.startedAt) entry.startedAt = new Date().toISOString();\n entry.currentTool = p.name;\n entry.toolCalls++;\n this.flush();\n }),\n );\n\n this.unsubscribers.push(\n on('subagent.iteration_summary', (_e, payload) => {\n const p = payload as\n | {\n subagentId?: string;\n iteration?: number;\n toolCalls?: number;\n currentTool?: string;\n costUsd?: number;\n partialText?: string;\n }\n | undefined;\n if (!p?.subagentId) return;\n const entry = touch(p.subagentId);\n entry.status = 'running';\n if (!entry.startedAt) entry.startedAt = new Date().toISOString();\n if (typeof p.iteration === 'number') entry.iterations = p.iteration;\n if (typeof p.toolCalls === 'number') entry.toolCalls = p.toolCalls;\n if (typeof p.costUsd === 'number') entry.costUsd = p.costUsd;\n if (p.currentTool) entry.currentTool = p.currentTool;\n // Live streamed tail of THIS subagent's current response (the runner\n // already accumulates it) — capped to the same budget as the leader.\n if (typeof p.partialText === 'string') {\n entry.partialText =\n p.partialText.length > PARTIAL_TEXT_CAP\n ? p.partialText.slice(p.partialText.length - PARTIAL_TEXT_CAP)\n : p.partialText;\n }\n this.flush();\n }),\n );\n\n this.unsubscribers.push(\n on('subagent.task_completed', (_e, payload) => {\n const p = payload as\n | { subagentId?: string; status?: string; iterations?: number; toolCalls?: number }\n | undefined;\n if (!p?.subagentId) return;\n // Only update an agent we already know — a completion for an unseen\n // agent isn't worth materialising.\n const entry = this.agents.get(p.subagentId);\n if (!entry) return;\n entry.status = p.status === 'failed' || p.status === 'timeout' ? 'error' : 'idle';\n entry.currentTool = undefined;\n entry.partialText = undefined;\n if (typeof p.iterations === 'number') entry.iterations = p.iterations;\n if (typeof p.toolCalls === 'number') entry.toolCalls = p.toolCalls;\n entry.lastActivityAt = new Date().toISOString();\n this.flush();\n }),\n );\n\n this.unsubscribers.push(\n on('subagent.stopped', (_e, payload) => {\n const p = payload as { subagentId?: string } | undefined;\n if (!p?.subagentId) return;\n if (this.agents.delete(p.subagentId)) this.flush();\n }),\n );\n\n // Reap finished subagents so the fleet view doesn't fill with dead/idle\n // desks. The leader is synthesised in flush() (never in `this.agents`), so\n // it is never reaped — it represents the live session.\n this.sweepTimer = setInterval(() => this.sweep(), AGENT_SWEEP_INTERVAL_MS);\n if (typeof this.sweepTimer.unref === 'function') this.sweepTimer.unref();\n }\n\n stop(): void {\n for (const unsub of this.unsubscribers) {\n try { unsub(); } catch { /* ignore */ }\n }\n this.unsubscribers = [];\n if (this.sweepTimer) {\n clearInterval(this.sweepTimer);\n this.sweepTimer = null;\n }\n if (this.partialTimer) {\n clearTimeout(this.partialTimer);\n this.partialTimer = null;\n }\n }\n\n /**\n * Coalesce streamed-text flushes: at most one registry write per\n * {@link PARTIAL_FLUSH_THROTTLE_MS} while text streams in, so per-token\n * deltas never thrash the cross-process registry file.\n */\n private schedulePartialFlush(): void {\n if (this.partialTimer) return;\n this.partialTimer = setTimeout(() => {\n this.partialTimer = null;\n this.flush();\n }, PARTIAL_FLUSH_THROTTLE_MS);\n if (typeof this.partialTimer.unref === 'function') this.partialTimer.unref();\n }\n\n /**\n * Remove subagents that have been finished (idle/error) for longer than\n * {@link AGENT_REAP_MS}. Running / streaming / waiting_user agents are kept\n * regardless of age — only *not-working* agents are reaped.\n */\n private sweep(): void {\n const now = Date.now();\n let removed = false;\n for (const [id, a] of this.agents) {\n const finished = a.status !== 'running' && a.status !== 'streaming' && a.status !== 'waiting_user';\n const age = now - Date.parse(a.lastActivityAt);\n if (finished && Number.isFinite(age) && age > AGENT_REAP_MS) {\n this.agents.delete(id);\n removed = true;\n }\n }\n if (removed) this.flush();\n }\n\n private flush(): void {\n const leaderEntry: AgentEntry = {\n id: 'leader',\n name: this.leaderName,\n startedAt: this.leaderStartedAt,\n status: this.leaderStatus,\n currentTool: this.leaderCurrentTool,\n iterations: this.leaderIterations,\n toolCalls: this.leaderToolCalls,\n costUsd: this.leaderCostUsd,\n tokensIn: this.leaderTokensIn,\n tokensOut: this.leaderTokensOut,\n ctxPct: this.leaderCtxPct,\n model: this.leaderModel,\n partialText: this.leaderPartialText || undefined,\n lastActivityAt: new Date().toISOString(),\n };\n\n const allAgents = [leaderEntry, ...this.agents.values()];\n this.lastAgents = allAgents;\n // Broadcast the fresh agent list on the local bus so in-process consumers\n // (e.g. the HQ session-telemetry bridge) can build snapshots without\n // re-reading the shared registry file. Best-effort, never throws here.\n try {\n this.events.emit('session.agents_updated', {\n sessionId: this.currentSessionId(),\n agents: allAgents,\n });\n } catch {\n /* best-effort */\n }\n // Nudge local WebUIs only AFTER the write settles, so they re-read fresh\n // data. Best-effort — never let a notifier failure surface here.\n this.registry\n .updateAgents(allAgents)\n .then(() => {\n try {\n this.onUpdate?.();\n } catch {\n /* best-effort */\n }\n })\n .catch(() => undefined);\n }\n\n private currentSessionId(): string | undefined {\n return typeof this.sessionId === 'function' ? this.sessionId() : this.sessionId;\n }\n\n private acceptsSession(payload: unknown): boolean {\n const expected = this.currentSessionId();\n if (!expected) return true;\n if (typeof payload !== 'object' || payload === null) return true;\n const actual = (payload as { sessionId?: unknown }).sessionId;\n return typeof actual !== 'string' || actual.length === 0 || actual === expected;\n }\n\n private markLeaderStarted(startedAt?: string): void {\n if (\n this.leaderStartedAt &&\n (this.leaderStatus === 'running' ||\n this.leaderStatus === 'streaming' ||\n this.leaderStatus === 'waiting_user')\n ) {\n return;\n }\n this.leaderStartedAt = startedAt ?? new Date().toISOString();\n }\n\n private captureLeaderContext(ctx: unknown): void {\n if (typeof ctx !== 'object' || ctx === null) return;\n const c = ctx as {\n model?: unknown;\n lastRequestTokens?: unknown;\n meta?: Record<string, unknown> | undefined;\n provider?: { capabilities?: { maxContext?: unknown } | undefined } | undefined;\n };\n if (typeof c.model === 'string' && c.model.length > 0) this.leaderModel = c.model;\n\n const metaLimit = c.meta?.['effectiveMaxContext'];\n const providerMax = c.provider?.capabilities?.maxContext;\n const maxContext =\n typeof metaLimit === 'number' && metaLimit > 0\n ? metaLimit\n : typeof providerMax === 'number' && providerMax > 0\n ? providerMax\n : undefined;\n if (\n typeof c.lastRequestTokens === 'number' &&\n c.lastRequestTokens > 0 &&\n maxContext !== undefined\n ) {\n this.leaderCtxPct = clampPct(Math.round((c.lastRequestTokens / maxContext) * 100));\n }\n }\n}\n","/**\n * FleetNotifier — push-on-write nudge to local WebUI servers.\n *\n * The cross-process source of truth is the file-based SessionRegistry, which\n * every WebUI server already watches (`fs.watch`, ~150ms) and polls (5s). This\n * notifier is a best-effort *latency* optimisation on top: after a process\n * writes its session/agent status to the registry, it sends a tiny\n * fire-and-forget `POST /api/fleet/ping` to every WebUI running against the\n * same project (discovered from `~/.wrongstack/webui-instances.json`). The\n * WebUI responds by re-broadcasting the (already-fresh) registry immediately —\n * so a TUI/REPL agent's activity reaches the Fleet HQ map in ~milliseconds\n * instead of waiting on the watch/poll.\n *\n * Design notes:\n * - **Never the source of truth.** If no WebUI is running, the file system +\n * watch/poll still carry everything. Every failure here is swallowed.\n * - **Coalesced.** Bursts of events (tool calls, deltas) collapse into one POST\n * per ~50ms so we never hammer the WebUI per token.\n * - **Discovery cached** for a couple seconds to avoid a disk read per event.\n * - **Loopback only / self-excluded.** Targets the local instances file; a\n * `0.0.0.0`/`::` bind is dialled on `127.0.0.1`, and the caller's own pid is\n * skipped so a WebUI never pings itself.\n *\n * @module fleet-notifier\n */\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\nconst INSTANCES_FILE = 'webui-instances.json';\nconst DISCOVERY_TTL_MS = 2_500;\nconst COALESCE_MS = 50;\nconst POST_TIMEOUT_MS = 500;\n\ninterface InstanceRecordLike {\n pid: number;\n httpPort: number;\n host: string;\n projectRoot: string;\n}\n\nfunction pidAlive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid <= 0) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch (err) {\n return (err as NodeJS.ErrnoException).code !== 'ESRCH';\n }\n}\n\n/** Normalise a project root for cross-process comparison (case-insensitive on Windows). */\nfunction normRoot(root: string): string {\n const resolved = path.resolve(root);\n return process.platform === 'win32' ? resolved.toLowerCase() : resolved;\n}\n\nexport interface FleetNotifierOptions {\n /** WrongStack global dir (`~/.wrongstack`) holding `webui-instances.json`. */\n baseDir: string;\n /** This process's project root — only WebUIs on the same project are pinged. */\n projectRoot: string;\n /** This process's pid, so a WebUI never pings itself. */\n selfPid?: number | undefined;\n /** Injectable POST for tests. Defaults to a timed `fetch`. */\n post?: ((url: string) => Promise<void>) | undefined;\n}\n\nexport class FleetNotifier {\n private readonly baseDir: string;\n private readonly projectRoot: string;\n private readonly selfPid: number;\n private readonly doPost: (url: string) => Promise<void>;\n\n private cache: { at: number; urls: string[] } | null = null;\n private timer: ReturnType<typeof setTimeout> | null = null;\n private disposed = false;\n\n constructor(opts: FleetNotifierOptions) {\n this.baseDir = opts.baseDir;\n this.projectRoot = normRoot(opts.projectRoot);\n this.selfPid = opts.selfPid ?? process.pid;\n this.doPost = opts.post ?? defaultPost;\n }\n\n /** Coalesced, best-effort nudge. Safe to call on every status change. */\n notify(): void {\n if (this.disposed || this.timer) return;\n this.timer = setTimeout(() => {\n this.timer = null;\n void this.flush();\n }, COALESCE_MS);\n if (typeof this.timer.unref === 'function') this.timer.unref();\n }\n\n /** Resolve same-project WebUI ping URLs (cached briefly). Exposed for tests. */\n async endpoints(): Promise<string[]> {\n const now = Date.now();\n if (this.cache && now - this.cache.at < DISCOVERY_TTL_MS) return this.cache.urls;\n const urls = await this.discover();\n this.cache = { at: now, urls };\n return urls;\n }\n\n dispose(): void {\n this.disposed = true;\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n }\n\n private async flush(): Promise<void> {\n const urls = await this.endpoints();\n await Promise.all(urls.map((u) => this.doPost(u).catch(() => undefined)));\n }\n\n private async discover(): Promise<string[]> {\n try {\n const raw = await fs.readFile(path.join(this.baseDir, INSTANCES_FILE), 'utf8');\n const data = JSON.parse(raw) as { instances?: InstanceRecordLike[] };\n const list = Array.isArray(data?.instances) ? data.instances : [];\n return list\n .filter((i) => i && typeof i.httpPort === 'number')\n .filter((i) => i.pid !== this.selfPid)\n .filter((i) => normRoot(i.projectRoot) === this.projectRoot)\n .filter((i) => pidAlive(i.pid))\n .map((i) => {\n const host = i.host === '0.0.0.0' || i.host === '::' || !i.host ? '127.0.0.1' : i.host;\n return `http://${host}:${i.httpPort}/api/fleet/ping`;\n });\n } catch {\n // Missing/corrupt instances file → no WebUIs to notify.\n return [];\n }\n }\n}\n\nasync function defaultPost(url: string): Promise<void> {\n await fetch(url, {\n method: 'POST',\n signal: AbortSignal.timeout(POST_TIMEOUT_MS),\n });\n}\n","import { expectDefined } from '../utils/expect-defined.js';\r\nimport { toErrorMessage } from '../utils/error.js';\nimport * as fsp from 'node:fs/promises';\r\nimport * as path from 'node:path';\r\nimport type { CheckpointInfo, RewindResult, RewindResultExtended, SessionRewinder } from '../types/session-rewinder.js';\r\nimport type { SessionEvent, FileSnapshot } from '../types/session.js';\r\nimport { atomicWrite } from '../utils/atomic-write.js';\nimport { SessionError, ERROR_CODES } from '../types/errors.js';\nimport { sessionScopedPath } from '../utils/session-scoped-path.js';\n\r\nexport interface SessionRewinderOptions {\r\n sessionsDir: string;\r\n /** The project root directory; used to validate rewind targets stay inside it. */\r\n projectRoot: string;\r\n}\r\n\r\n/**\r\n * Rewind engine that reads session JSONL files and reverts file system\r\n * changes to any previous checkpoint.\r\n */\r\nexport class DefaultSessionRewinder implements SessionRewinder {\n constructor(private readonly sessionsDir: string, private readonly projectRoot: string) {}\n\n private sessionFile(sessionId: string): string {\n return sessionScopedPath(this.sessionsDir, sessionId, '.jsonl');\n }\n\n async listCheckpoints(sessionId: string): Promise<CheckpointInfo[]> {\n const file = this.sessionFile(sessionId);\n const raw = await fsp.readFile(file, 'utf8');\r\n const events = parseEvents(raw);\r\n\r\n // Build a map of promptIndex -> file snapshot count\r\n const fileCountMap = new Map<number, number>();\r\n for (const event of events) {\r\n if (event.type === 'file_snapshot') {\r\n const e = event as { promptIndex: number; files: FileSnapshot[] };\r\n fileCountMap.set(e.promptIndex, (fileCountMap.get(e.promptIndex) ?? 0) + e.files.length);\r\n }\r\n }\r\n\r\n const checkpoints: CheckpointInfo[] = [];\r\n for (const event of events) {\r\n if (event.type === 'checkpoint') {\r\n const e = event as { promptIndex: number; promptPreview: string; ts: string };\r\n checkpoints.push({\r\n promptIndex: e.promptIndex,\r\n promptPreview: e.promptPreview,\r\n ts: e.ts,\r\n fileCount: fileCountMap.get(e.promptIndex) ?? 0,\r\n });\r\n }\r\n }\r\n\r\n return checkpoints;\r\n }\r\n\r\n async rewindToCheckpoint(\r\n sessionId: string,\r\n checkpointIndex: number,\r\n ): Promise<RewindResultExtended> {\n const file = this.sessionFile(sessionId);\n const raw = await fsp.readFile(file, 'utf8');\r\n const events = parseEvents(raw);\r\n\r\n let targetIdx = -1;\r\n for (let i = 0; i < events.length; i++) {\r\n const event = expectDefined(events[i]);\r\n if (event.type === 'checkpoint') {\r\n const checkpointEvent = event as { promptIndex: number };\r\n if (checkpointEvent.promptIndex === checkpointIndex) {\r\n targetIdx = i;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (targetIdx === -1) {\r\n throw new SessionError({\r\n message: `Checkpoint ${checkpointIndex} not found`,\r\n code: ERROR_CODES.SESSION_NOT_FOUND,\r\n context: { checkpointIndex },\r\n });\r\n }\r\n\r\n const snapshotsToRevert: Array<{ promptIndex: number; files: FileSnapshot[] }> = [];\r\n for (let i = targetIdx + 1; i < events.length; i++) {\r\n const event = expectDefined(events[i]);\r\n if (event.type === 'checkpoint') {\r\n break;\r\n }\r\n if (event.type === 'file_snapshot') {\r\n const snapshotEvent = event as { promptIndex: number; files: FileSnapshot[] };\r\n if (snapshotEvent.promptIndex >= checkpointIndex) {\r\n snapshotsToRevert.push({ promptIndex: snapshotEvent.promptIndex, files: snapshotEvent.files });\r\n }\r\n }\r\n }\r\n\r\n const result = await revertSnapshots(snapshotsToRevert, this.projectRoot);\r\n const removedEvents = events.length - targetIdx - 1;\r\n return { ...result, toPromptIndex: checkpointIndex, removedEvents };\r\n }\r\n\r\n async rewindLastN(sessionId: string, n: number): Promise<RewindResultExtended> {\n const file = this.sessionFile(sessionId);\n const raw = await fsp.readFile(file, 'utf8');\r\n const events = parseEvents(raw);\r\n\r\n const checkpoints: Array<{ promptIndex: number; ts: string }> = [];\r\n for (const event of events) {\r\n if (event.type === 'checkpoint') {\r\n checkpoints.push({ promptIndex: event.promptIndex, ts: event.ts });\r\n }\r\n }\r\n\r\n if (checkpoints.length === 0) {\r\n return { revertedFiles: [], errors: [], toPromptIndex: 0, removedEvents: 0 };\r\n }\r\n\r\n checkpoints.sort((a, b) => b.promptIndex - a.promptIndex);\r\n const targetIndex = checkpoints[n]?.promptIndex ?? 0;\r\n\r\n const snapshotsToRevert: Array<{ promptIndex: number; files: FileSnapshot[] }> = [];\r\n let shouldRevert = false;\r\n\r\n for (const event of events) {\r\n if (event.type === 'checkpoint' && event.promptIndex === targetIndex) {\r\n shouldRevert = true;\r\n continue;\r\n }\r\n if (shouldRevert && event.type === 'file_snapshot') {\r\n snapshotsToRevert.push({ promptIndex: event.promptIndex, files: event.files });\r\n }\r\n }\r\n\r\n const result = await revertSnapshots(snapshotsToRevert.reverse(), this.projectRoot);\r\n return { ...result, toPromptIndex: targetIndex, removedEvents: snapshotsToRevert.length };\r\n }\r\n\r\n async rewindToStart(sessionId: string): Promise<RewindResultExtended> {\n const file = this.sessionFile(sessionId);\n const raw = await fsp.readFile(file, 'utf8');\r\n const events = parseEvents(raw);\r\n\r\n const allSnapshots: Array<{ promptIndex: number; files: FileSnapshot[] }> = [];\r\n for (const event of events) {\r\n if (event.type === 'file_snapshot') {\r\n allSnapshots.push({ promptIndex: event.promptIndex, files: event.files });\r\n }\r\n }\r\n\r\n if (allSnapshots.length === 0) {\r\n return { revertedFiles: [], errors: [], toPromptIndex: 0, removedEvents: 0 };\r\n }\r\n\r\n const result = await revertSnapshots(allSnapshots.reverse(), this.projectRoot);\r\n return { ...result, toPromptIndex: 0, removedEvents: allSnapshots.length };\r\n }\r\n}\r\n\r\nfunction parseEvents(raw: string): SessionEvent[] {\r\n const lines = raw.split('\\n').filter((l) => l.trim());\r\n const events: SessionEvent[] = [];\r\n\r\n for (const line of lines) {\r\n try {\r\n const parsed = JSON.parse(line);\r\n if (\r\n parsed !== null &&\r\n typeof parsed === 'object' &&\r\n typeof (parsed as { type?: unknown | undefined }).type === 'string' &&\r\n typeof (parsed as { ts?: unknown | undefined }).ts === 'string'\r\n ) {\r\n events.push(parsed as SessionEvent);\r\n }\r\n } catch {\r\n // skip malformed\r\n }\r\n }\r\n\r\n return events;\r\n}\r\n\r\nasync function revertSnapshots(\r\n snapshots: Array<{ promptIndex: number; files: FileSnapshot[] }>,\r\n projectRoot: string,\r\n): Promise<RewindResult> {\r\n const revertedFiles: string[] = [];\r\n const errors: string[] = [];\r\n\r\n for (const snapshot of snapshots) {\r\n for (const file of snapshot.files) {\r\n try {\r\n // Guard: ensure the target path resolves inside the project root.\r\n // Without this, a maliciously recorded path (e.g., via path traversal\r\n // in a tool call that wasn't caught) could cause rewind to write\r\n // to arbitrary locations.\r\n const absPath = path.resolve(file.path);\r\n const root = path.resolve(projectRoot);\r\n const rel = path.relative(root, absPath);\r\n if (rel.startsWith('..') || path.isAbsolute(rel)) {\r\n errors.push(`${file.path}: path resolves outside project root — skipping`);\r\n continue;\r\n }\r\n\r\n if (file.action === 'deleted') {\r\n // File was deleted — restore it from before\r\n if (file.before !== null) {\r\n // atomicWrite: torn restore would leave the user with a frankenstein file.\r\n await atomicWrite(file.path, file.before, { mode: 0o644 });\r\n revertedFiles.push(file.path);\r\n }\r\n } else if (file.action === 'created') {\r\n // File was created — delete it\r\n await fsp.unlink(file.path);\r\n revertedFiles.push(file.path);\r\n } else if (file.action === 'modified') {\r\n // File was modified — restore before content\r\n if (file.before !== null) {\r\n // atomicWrite: torn restore would leave the user with a frankenstein file.\r\n await atomicWrite(file.path, file.before, { mode: 0o644 });\r\n revertedFiles.push(file.path);\r\n }\r\n }\r\n } catch (err) {\r\n errors.push(`${file.path}: ${toErrorMessage(err)}`);\r\n }\r\n }\r\n }\r\n\r\n return { revertedFiles, errors };\r\n}\n","import * as fsp from 'node:fs/promises';\nimport type { EventBus } from '../kernel/events.js';\nimport type { TodoItem } from '../core/context.js';\nimport type { ConversationState } from '../core/conversation-state.js';\nimport { atomicWrite } from '../utils/atomic-write.js';\nimport { toErrorMessage } from '../utils/error.js';\n\n/**\n * On-disk checkpoint for `ctx.todos`. Written atomically every time the\n * todo list changes, read once on session resume. This is the missing\n * piece that lets `wstack resume <id>` rehydrate where the previous run\n * stopped instead of starting with an empty board.\n *\n * Schema is intentionally small — a single JSON object so a future\n * format bump is easy. The `version` field is the only contract; the\n * shape under `todos` mirrors `TodoItem` so reading is a straight assign.\n */\nexport interface TodosCheckpointFile {\n version: 1;\n sessionId: string;\n updatedAt: string;\n todos: TodoItem[];\n}\n\nexport type TodosCheckpointDetach = () => Promise<void>;\n\n/** Read a checkpoint from disk. Returns null when the file doesn't\n * exist or is corrupt — callers treat both cases as \"no prior state\".\n */\nexport async function loadTodosCheckpoint(\n filePath: string,\n events?: EventBus,\n traceId?: string,\n): Promise<TodoItem[] | null> {\n const t0 = Date.now();\n let raw: string;\n try {\n raw = await fsp.readFile(filePath, 'utf8');\n } catch (err) {\n events?.emit('storage.error', {\n sessionId: traceId ?? '~boot~',\n store: 'todos',\n filePath,\n operation: 'load',\n outcome: 'failure',\n error: toErrorMessage(err),\n recoverable: true,\n });\n return null;\n }\n try {\n const parsed = JSON.parse(raw) as TodosCheckpointFile;\n if (parsed?.version !== 1 || !Array.isArray(parsed.todos)) {\n events?.emit('storage.read', {\n sessionId: traceId ?? '~boot~',\n store: 'todos',\n filePath,\n operation: 'load',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'invalid_schema',\n ...(traceId !== undefined && { traceId }),\n });\n return null;\n }\n events?.emit('storage.read', {\n sessionId: traceId ?? '~boot~',\n store: 'todos',\n filePath,\n operation: 'load',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(traceId !== undefined && { traceId }),\n });\n return parsed.todos.filter(\n (t): t is TodoItem =>\n !!t &&\n typeof t.id === 'string' &&\n typeof t.content === 'string' &&\n typeof t.status === 'string' &&\n (t.activeForm === undefined || typeof t.activeForm === 'string'),\n );\n } catch {\n events?.emit('storage.read', {\n sessionId: traceId ?? '~boot~',\n store: 'todos',\n filePath,\n operation: 'load',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'parse_failed',\n ...(traceId !== undefined && { traceId }),\n });\n return null;\n }\n}\n\n/** Write the checkpoint atomically. Best-effort: a write failure is\n * logged but does not throw — losing one checkpoint shouldn't bring\n * down the agent run.\n */\nexport async function saveTodosCheckpoint(\n filePath: string,\n sessionId: string,\n todos: readonly TodoItem[],\n events?: EventBus,\n traceId?: string,\n): Promise<void> {\n const t0 = Date.now();\n const payload: TodosCheckpointFile = {\n version: 1,\n sessionId,\n updatedAt: new Date().toISOString(),\n todos: [...todos],\n };\n try {\n await atomicWrite(filePath, JSON.stringify(payload, null, 2), { mode: 0o600 });\n events?.emit('storage.write', {\n sessionId: traceId ?? sessionId,\n store: 'todos',\n filePath,\n operation: 'save',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(traceId !== undefined && { traceId }),\n });\n } catch (err) {\n events?.emit('storage.error', {\n sessionId: traceId ?? sessionId,\n store: 'todos',\n filePath,\n operation: 'save',\n outcome: 'failure',\n error: toErrorMessage(err),\n recoverable: false,\n });\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'todos_checkpoint.save_failed',\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n }\n}\n\n/**\n * Subscribe a `ConversationState` so every `todos_replaced` mutation\n * triggers an atomic write to disk. Returns the unsubscribe function.\n *\n * Writes are debounced by 150ms so a flurry of edits (e.g. the LLM\n * marking three items done in the same tool call) coalesces into one\n * disk hit.\n */\nexport function attachTodosCheckpoint(\n state: ConversationState,\n filePath: string,\n sessionId: string,\n events?: EventBus,\n traceId?: string,\n): TodosCheckpointDetach {\n let timer: NodeJS.Timeout | null = null;\n let pending: readonly TodoItem[] | null = null;\n let writeChain: Promise<void> = Promise.resolve();\n\n const enqueueWrite = (todos: readonly TodoItem[]) => {\n writeChain = writeChain\n .then(() => saveTodosCheckpoint(filePath, sessionId, todos, events, traceId))\n /* v8 ignore start -- defensive: saveTodosCheckpoint swallows its own errors and never rejects */\n .catch((err) => {\n // Log and keep the chain alive — a failed write must not\n // poison the chain and silently stop all subsequent writes.\n const msg = toErrorMessage(err);\n console.error(JSON.stringify({\n level: 'error',\n event: 'todos_checkpoint.write_chain_failed',\n sessionId,\n message: msg,\n timestamp: new Date().toISOString(),\n }));\n });\n /* v8 ignore stop */\n return writeChain;\n };\n\n const flush = () => {\n timer = null;\n if (pending) {\n const todos = pending;\n pending = null;\n return enqueueWrite(todos);\n }\n /* v8 ignore next -- defensive: flush is only invoked when a change is pending */\n return writeChain;\n };\n\n const unsubscribe = state.onChange((change) => {\n if (change.kind !== 'todos_replaced') return;\n pending = change.todos;\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n void flush();\n }, 150);\n });\n return async () => {\n unsubscribe();\n if (timer) {\n clearTimeout(timer);\n // Flush any pending write before detach so callers can safely\n // unsubscribe at shutdown without losing the last update.\n await flush();\n } else {\n await writeChain;\n }\n };\n}\n","import * as fsp from 'node:fs/promises';\nimport { randomUUID } from 'node:crypto';\nimport type { EventBus } from '../kernel/events.js';\nimport type { ConversationState } from '../core/conversation-state.js';\nimport { atomicWrite, withFileLock } from '../utils/atomic-write.js';\nimport { toErrorMessage } from '../utils/error.js';\nimport { SessionError } from '../types/errors.js';\n\n/**\n * Plan items are the strategic counterpart to todos. Where `ctx.todos`\n * is the moment-to-moment task board the LLM mutates per-turn, a plan\n * captures the higher-level approach — the steps the user (or LLM)\n * laid out before any work began.\n *\n * Plans persist by default (per session) so a resumed session can show\n * \"you were on step 3 of 5\". Todos are derived/transient. Both can\n * coexist: think roadmap (plan) vs. sprint board (todos).\n */\nexport interface PlanItem {\n id: string;\n title: string;\n /** Optional longer-form context or rationale. */\n details?: string | undefined;\n status: 'open' | 'in_progress' | 'done';\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface PlanFile {\n version: 1;\n sessionId: string;\n title?: string | undefined;\n updatedAt: string;\n items: PlanItem[];\n}\n\nexport async function loadPlan(filePath: string, events?: EventBus): Promise<PlanFile | null> {\n const t0 = Date.now();\n let raw: string;\n try {\n raw = await fsp.readFile(filePath, 'utf8');\n } catch (err) {\n events?.emit('storage.error', {\n sessionId: '~boot~',\n store: 'plan',\n filePath,\n operation: 'load',\n error: toErrorMessage(err),\n recoverable: true,\n });\n return null;\n }\n try {\n const parsed = JSON.parse(raw) as PlanFile;\n if (parsed?.version !== 1 || !Array.isArray(parsed.items)) {\n events?.emit('storage.read', {\n sessionId: '~boot~',\n store: 'plan',\n filePath,\n operation: 'load',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'invalid_schema',\n });\n return null;\n }\n events?.emit('storage.read', {\n sessionId: '~boot~',\n store: 'plan',\n filePath,\n operation: 'load',\n outcome: 'success',\n durationMs: Date.now() - t0,\n });\n return parsed;\n } catch {\n events?.emit('storage.read', {\n sessionId: '~boot~',\n store: 'plan',\n filePath,\n operation: 'load',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'parse_failed',\n });\n return null;\n }\n}\n\n/**\n * Persist a plan. Returns `true` on success, `false` if the write failed\n * (still emits `storage.error` + warns — it does NOT throw, so callers that\n * treat a lost plan-save as non-fatal keep working). `mutatePlan` inspects the\n * result and throws so the plan TOOL can report `ok:false` instead of falsely\n * claiming the plan was persisted.\n */\nexport async function savePlan(filePath: string, plan: PlanFile, events?: EventBus): Promise<boolean> {\n const t0 = Date.now();\n try {\n await atomicWrite(filePath, JSON.stringify(plan, null, 2), { mode: 0o600 });\n events?.emit('storage.write', {\n sessionId: '~boot~',\n store: 'plan',\n filePath,\n operation: 'save',\n outcome: 'success',\n durationMs: Date.now() - t0,\n });\n return true;\n } catch (err) {\n events?.emit('storage.error', {\n sessionId: '~boot~',\n store: 'plan',\n filePath,\n operation: 'save',\n error: toErrorMessage(err),\n recoverable: false,\n });\n console.warn(\n '[plan-store] save failed:',\n toErrorMessage(err),\n );\n return false;\n }\n}\n\n/** Create a new PlanFile when none exists on disk. */\nexport function emptyPlan(sessionId: string, title?: string): PlanFile {\n return {\n version: 1,\n sessionId,\n title,\n updatedAt: new Date().toISOString(),\n items: [],\n };\n}\n\nexport function addPlanItem(\n plan: PlanFile,\n title: string,\n details?: string | undefined,\n): { plan: PlanFile; item: PlanItem } {\n const now = new Date().toISOString();\n const item: PlanItem = {\n id: `plan_${Date.now()}_${randomUUID().slice(0, 6)}`,\n title,\n details,\n status: 'open',\n createdAt: now,\n updatedAt: now,\n };\n return {\n plan: { ...plan, items: [...plan.items, item], updatedAt: now },\n item,\n };\n}\n\nexport function removePlanItem(plan: PlanFile, idOrIndex: string): PlanFile {\n const idx = matchIndex(plan, idOrIndex);\n if (idx === -1) return plan;\n return {\n ...plan,\n items: plan.items.filter((_, i) => i !== idx),\n updatedAt: new Date().toISOString(),\n };\n}\n\nexport function setPlanItemStatus(\n plan: PlanFile,\n idOrIndex: string,\n status: PlanItem['status'],\n): PlanFile {\n const idx = matchIndex(plan, idOrIndex);\n if (idx === -1) return plan;\n const now = new Date().toISOString();\n const items = plan.items.map((it, i) =>\n i === idx ? { ...it, status, updatedAt: now } : it,\n );\n return { ...plan, items, updatedAt: now };\n}\n\nexport function clearPlan(plan: PlanFile): PlanFile {\n return { ...plan, items: [], updatedAt: new Date().toISOString() };\n}\n\n/** Render the plan as a short markdown-ish string suitable for slash output. */\nexport function formatPlan(plan: PlanFile): string {\n if (plan.items.length === 0) return 'Plan is empty.';\n const lines: string[] = [];\n if (plan.title) lines.push(`# ${plan.title}`);\n plan.items.forEach((it, i) => {\n const mark = it.status === 'done' ? '[x]' : it.status === 'in_progress' ? '[~]' : '[ ]';\n lines.push(`${i + 1}. ${mark} ${it.title}`);\n if (it.details) {\n for (const line of it.details.split('\\n')) lines.push(` ${line}`);\n }\n });\n return lines.join('\\n');\n}\n\nfunction matchIndex(plan: PlanFile, idOrIndex: string): number {\n const asNum = Number.parseInt(idOrIndex, 10);\n if (!Number.isNaN(asNum) && asNum >= 1 && asNum <= plan.items.length) return asNum - 1;\n const byId = plan.items.findIndex((it) => it.id === idOrIndex);\n if (byId !== -1) return byId;\n const lower = idOrIndex.toLowerCase();\n return plan.items.findIndex((it) => it.title.toLowerCase().includes(lower));\n}\n\n/**\n * Promote a plan item to a set of todo items.\n * The plan item is marked 'in_progress' (if not already done) and its\n * title + details become the first todo; additional subtasks are appended.\n * Returns the derived todo list so the caller can pass it to `todoTool`\n * or `ctx.state.replaceTodos()`.\n */\nexport function deriveTodosFromPlanItem(\n plan: PlanFile,\n idOrIndex: string,\n subtasks?: string[] | undefined,\n): { plan: PlanFile; todos: Array<{ id: string; content: string; status: 'pending' | 'in_progress' | 'completed'; activeForm?: string | undefined; promotedFromPlan?: string | undefined }> } | null {\n const idx = matchIndex(plan, idOrIndex);\n if (idx === -1) return null;\n\n const item = plan.items[idx];\n /* v8 ignore next -- defensive: matchIndex returns a valid in-range index or -1 (handled above) */\n if (!item) return null;\n\n // Mark the plan item in_progress if it wasn't already done\n let updatedPlan = plan;\n if (item.status !== 'done') {\n updatedPlan = setPlanItemStatus(plan, idOrIndex, 'in_progress');\n }\n\n const todos: Array<{ id: string; content: string; status: 'pending' | 'in_progress' | 'completed'; activeForm?: string | undefined; promotedFromPlan?: string | undefined }> = [];\n\n // First todo from the plan item itself\n todos.push({\n id: `todo_${Date.now()}_plan`,\n content: item.title,\n status: 'in_progress',\n activeForm: item.title,\n promotedFromPlan: item.id,\n });\n\n // Optional subtasks\n if (subtasks && subtasks.length > 0) {\n for (const st of subtasks) {\n todos.push({\n id: `todo_${Date.now()}_${randomUUID().slice(0, 6)}`,\n content: st,\n status: 'pending',\n promotedFromPlan: item.id,\n });\n }\n }\n\n return { plan: updatedPlan, todos };\n}\n\n/**\n * Load, modify, and save the plan file under a file-level lock.\n * Prevents races from parallel tool invocations (e.g. batch_tool_use).\n */\nexport async function mutatePlan(\n filePath: string,\n sessionId: string,\n fn: (plan: PlanFile) => PlanFile | Promise<PlanFile>,\n): Promise<PlanFile> {\n return withFileLock(filePath, async () => {\n const plan = (await loadPlan(filePath)) ?? emptyPlan(sessionId);\n const updated = await fn(plan);\n const persisted = await savePlan(filePath, updated);\n if (!persisted) {\n throw new SessionError({\n message: `Failed to persist plan to ${filePath} — the change was NOT saved.`,\n code: 'SESSION_WRITE_FAILED',\n sessionId,\n context: { filePath, operation: 'mutatePlan' },\n });\n }\n return updated;\n });\n}\n\n/**\n * Optional: attach a state-listener so meta operations (storing a plan\n * id on ctx.meta) trigger a save. Currently a stub — plans don't live\n * on Context, but this keeps the API surface symmetric with the todos\n * checkpoint so future refactors can flip plans into Context if needed.\n */\nexport function attachPlanCheckpoint(\n _state: ConversationState,\n _filePath: string,\n _sessionId: string,\n): () => void {\n return () => undefined;\n}\n","/**\n * Plan templates — pre-defined plan skeletons for common workflows.\n *\n * Templates are stored in-memory (no disk I/O). Users instantiate them\n * via `/plan template use <name>` or `planTool(action: 'template_use')`.\n * Each template is a function that returns an array of item titles, so\n * dynamic content (dates, project names) can be injected later.\n */\n\nexport interface PlanTemplate {\n name: string;\n description: string;\n category: 'development' | 'release' | 'maintenance' | 'infrastructure';\n items: Array<{\n title: string;\n details?: string | undefined;\n }>;\n}\n\nconst templates: Record<string, PlanTemplate> = {\n 'new-feature': {\n name: 'new-feature',\n description: 'Standard workflow for adding a new feature',\n category: 'development',\n items: [\n { title: 'Write specification / design doc', details: 'Define scope, acceptance criteria, edge cases' },\n { title: 'Set up feature branch', details: 'git checkout -b feature/...' },\n { title: 'Implement core logic', details: 'TDD preferred — write tests first' },\n { title: 'Add unit tests', details: '>= 80% coverage for new code' },\n { title: 'Add integration tests', details: 'End-to-end happy path + error paths' },\n { title: 'Update documentation', details: 'README, API docs, changelog' },\n { title: 'Code review', details: 'Self-review before requesting review' },\n { title: 'Merge and deploy', details: 'CI green, tag release' },\n ],\n },\n 'bug-fix': {\n name: 'bug-fix',\n description: 'Systematic approach to fixing bugs',\n category: 'maintenance',\n items: [\n { title: 'Reproduce the bug', details: 'Minimal reproduction case' },\n { title: 'Root cause analysis', details: 'Trace through logs, debugger' },\n { title: 'Write failing test', details: 'Test must fail before fix' },\n { title: 'Implement fix', details: 'Smallest possible change' },\n { title: 'Verify fix', details: 'Test passes, reproduction no longer fails' },\n { title: 'Regression test', details: 'Ensure no related tests broken' },\n { title: 'Document in changelog', details: 'Brief description + issue link' },\n ],\n },\n 'refactor': {\n name: 'refactor',\n description: 'Safe refactoring workflow',\n category: 'maintenance',\n items: [\n { title: 'Identify refactoring target', details: 'Code smell, performance bottleneck, or tech debt' },\n { title: 'Ensure test coverage', details: 'Existing tests must pass before and after' },\n { title: 'Write characterization tests', details: 'Capture current behavior if tests weak' },\n { title: 'Apply refactoring', details: 'Small steps, frequent commits' },\n { title: 'Run full test suite', details: 'All tests must pass' },\n { title: 'Performance check', details: 'Ensure no regression' },\n { title: 'Code review', details: 'Explain the why, not just the what' },\n ],\n },\n 'release': {\n name: 'release',\n description: 'Preparing a new release',\n category: 'release',\n items: [\n { title: 'Version bump', details: 'package.json, lockfiles, tags' },\n { title: 'Update changelog', details: 'All changes since last release' },\n { title: 'Run full test suite', details: 'Unit + integration + e2e' },\n { title: 'Build artifacts', details: 'Docker images, bundles, binaries' },\n { title: 'Staging smoke tests', details: 'Deploy to staging, verify' },\n { title: 'Production deploy', details: 'Blue-green or canary' },\n { title: 'Post-deploy verification', details: 'Health checks, error rates' },\n { title: 'Announce release', details: 'Slack, email, GitHub release notes' },\n ],\n },\n 'security-audit': {\n name: 'security-audit',\n description: 'Security review and hardening',\n category: 'infrastructure',\n items: [\n { title: 'Dependency audit', details: 'npm audit, Snyk, Dependabot alerts' },\n { title: 'Secret scan', details: 'git-secrets, truffleHog, manual review' },\n { title: 'Access control review', details: 'IAM, roles, least privilege' },\n { title: 'Input validation audit', details: 'SQL injection, XSS, path traversal' },\n { title: 'Authentication review', details: 'Session management, MFA, password policy' },\n { title: 'Logging and monitoring', details: 'PII in logs, audit trails' },\n { title: 'Incident response plan', details: 'Runbooks, contacts, escalation' },\n ],\n },\n 'onboarding': {\n name: 'onboarding',\n description: 'New developer onboarding checklist',\n category: 'infrastructure',\n items: [\n { title: 'Repository access', details: 'GitHub/GitLab permissions' },\n { title: 'Local environment setup', details: 'Docker, dependencies, env files' },\n { title: 'Run tests locally', details: 'Verify green suite' },\n { title: 'Read architecture docs', details: 'ADR, README, onboarding guide' },\n { title: 'First commit', details: 'Docs fix or small improvement' },\n { title: 'Pair programming session', details: 'Walk through codebase with buddy' },\n { title: 'Deploy to staging', details: 'Verify CI/CD access' },\n ],\n },\n};\n\nexport function listPlanTemplates(): PlanTemplate[] {\n return Object.values(templates);\n}\n\nexport function getPlanTemplate(name: string): PlanTemplate | undefined {\n return templates[name];\n}\n\nexport function formatPlanTemplates(): string {\n const cats = new Map<PlanTemplate['category'], PlanTemplate[]>();\n for (const t of Object.values(templates)) {\n const arr = cats.get(t.category) ?? [];\n arr.push(t);\n cats.set(t.category, arr);\n }\n\n const lines: string[] = ['Available plan templates:'];\n for (const [cat, items] of cats) {\n lines.push(`\\n${cat}:`);\n for (const t of items) {\n lines.push(` ${t.name.padEnd(18)} — ${t.description}`);\n }\n }\n return lines.join('\\n');\n}\n","import * as fsp from 'node:fs/promises';\nimport type { EventBus } from '../kernel/events.js';\nimport { atomicWrite, withFileLock } from '../utils/atomic-write.js';\nimport { toErrorMessage } from '../utils/error.js';\nimport type { TaskItem } from '../utils/task-format.js';\nimport { SessionError } from '../types/errors.js';\n\n// ---------------------------------------------------------------------------\n// Task file persistence — one JSON file per session, resolved via\n// `sessionScopedPath(projectSessions, sessionId, '.tasks.json')`.\n//\n// Low-level load/save are exported for read-only consumers. Mutating callers\n// should use `mutateTasks` which wraps the entire read-modify-write cycle\n// under a file-level lock, preventing races from parallel tool invocations.\n// ---------------------------------------------------------------------------\n\nexport interface TaskFile {\n version: 1;\n sessionId: string;\n updatedAt: string;\n tasks: TaskItem[];\n}\n\nexport function emptyTaskFile(sessionId: string): TaskFile {\n return {\n version: 1,\n sessionId,\n updatedAt: new Date().toISOString(),\n tasks: [],\n };\n}\n\n/** Read the task file. Returns null when the file doesn't exist. */\nexport async function loadTasks(\n filePath: string,\n events?: EventBus,\n traceId?: string,\n): Promise<TaskFile | null> {\n const t0 = Date.now();\n let raw: string;\n try {\n raw = await fsp.readFile(filePath, 'utf8');\n } catch (err) {\n events?.emit('storage.error', {\n sessionId: traceId ?? '~boot~',\n store: 'tasks',\n filePath,\n operation: 'load',\n outcome: 'failure',\n error: toErrorMessage(err),\n recoverable: true,\n });\n return null;\n }\n try {\n const parsed = JSON.parse(raw) as TaskFile;\n if (parsed?.version !== 1 || !Array.isArray(parsed.tasks)) {\n events?.emit('storage.read', {\n sessionId: traceId ?? '~boot~',\n store: 'tasks',\n filePath,\n operation: 'load',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'invalid_schema',\n ...(traceId !== undefined && { traceId }),\n });\n return null;\n }\n events?.emit('storage.read', {\n sessionId: traceId ?? '~boot~',\n store: 'tasks',\n filePath,\n operation: 'load',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(traceId !== undefined && { traceId }),\n });\n return parsed;\n } catch {\n events?.emit('storage.read', {\n sessionId: traceId ?? '~boot~',\n store: 'tasks',\n filePath,\n operation: 'load',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'parse_failed',\n ...(traceId !== undefined && { traceId }),\n });\n return null;\n }\n}\n\n/**\n * Write the task file atomically. Prefer `mutateTasks` for read-modify-write\n * cycles — this low-level function does NOT acquire a lock.\n */\n/**\n * Persist the task file. Returns `true` on success, `false` if the write\n * failed (still emits `storage.error` + warns — does NOT throw). `mutateTasks`\n * inspects the result and throws so the task TOOL can report `ok:false`\n * instead of falsely claiming the tasks were saved.\n */\nexport async function saveTasks(\n filePath: string,\n tasks: TaskFile,\n events?: EventBus,\n traceId?: string,\n): Promise<boolean> {\n const t0 = Date.now();\n try {\n tasks.updatedAt = new Date().toISOString();\n await atomicWrite(filePath, JSON.stringify(tasks, null, 2), { mode: 0o600 });\n events?.emit('storage.write', {\n sessionId: traceId ?? '~boot~',\n store: 'tasks',\n filePath,\n operation: 'save',\n outcome: 'success',\n durationMs: Date.now() - t0,\n ...(traceId !== undefined && { traceId }),\n });\n return true;\n } catch (err) {\n events?.emit('storage.error', {\n sessionId: traceId ?? '~boot~',\n store: 'tasks',\n filePath,\n operation: 'save',\n outcome: 'failure',\n error: toErrorMessage(err),\n recoverable: false,\n ...(traceId !== undefined && { traceId }),\n });\n console.warn(\n '[task-store] save failed:',\n toErrorMessage(err),\n );\n return false;\n }\n}\n\n/**\n * Load, modify, and save the task file under a file-level lock.\n * `fn` receives the current TaskFile (or a fresh empty one) and must\n * return the mutated TaskFile (mutating in-place is fine — the returned\n * reference is what gets saved).\n *\n * This is the primary API for any code path that reads *and then writes*\n * the task file — it prevents races from parallel `batch_tool_use` calls.\n */\nexport async function mutateTasks(\n filePath: string,\n sessionId: string,\n fn: (file: TaskFile) => TaskFile | Promise<TaskFile>,\n events?: EventBus,\n traceId?: string,\n): Promise<TaskFile> {\n return withFileLock(filePath, async () => {\n const file = (await loadTasks(filePath, events, traceId)) ?? emptyTaskFile(sessionId);\n const updated = await fn(file);\n const persisted = await saveTasks(filePath, updated, events, traceId);\n if (!persisted) {\n throw new SessionError({\n message: `Failed to persist tasks to ${filePath} — the change was NOT saved.`,\n code: 'SESSION_WRITE_FAILED',\n sessionId,\n context: { filePath, operation: 'mutateTasks' },\n });\n }\n return updated;\n });\n}\n","import * as fsp from 'node:fs/promises';\nimport { hostname } from 'node:os';\nimport { atomicWrite } from '../utils/atomic-write.js';\nimport { toErrorMessage } from '../utils/error.js';\n\n/**\n * Director state checkpoint — written incrementally throughout a fleet\n * run so a crashed director can be inspected (and eventually resumed)\n * instead of leaving only a final `fleet.json` manifest after `shutdown()`.\n *\n * Schema is JSON-friendly and deliberately denormalized. Each mutation\n * triggers an atomic-write of the whole file — small payloads (typically\n * < 10 KB even with dozens of subagents) make this cheap.\n */\nexport interface DirectorSubagentState {\n id: string;\n name?: string | undefined;\n role?: string | undefined;\n provider?: string | undefined;\n model?: string | undefined;\n spawnedAt: string;\n}\n\nexport interface DirectorTaskState {\n taskId: string;\n subagentId?: string | undefined;\n description?: string | undefined;\n status: 'pending' | 'running' | 'completed' | 'failed' | 'stopped' | 'timeout';\n assignedAt?: string | undefined;\n completedAt?: string | undefined;\n iterations?: number | undefined;\n toolCalls?: number | undefined;\n durationMs?: number | undefined;\n error?: string | undefined;\n}\n\nexport interface DirectorStateSnapshot {\n version: 1;\n directorRunId: string;\n updatedAt: string;\n spawnCount: number;\n maxSpawns?: number | undefined;\n spawnDepth: number;\n maxSpawnDepth: number;\n directorBudget?: {\n maxCostUsd?: number | undefined;\n } | undefined;\n subagents: DirectorSubagentState[];\n tasks: DirectorTaskState[];\n /** Aggregated usage snapshot. Optional — populated by the Director on save when available. */\n usage?: unknown | undefined;\n}\n\nexport async function loadDirectorState(filePath: string): Promise<DirectorStateSnapshot | null> {\n let raw: string;\n try {\n raw = await fsp.readFile(filePath, 'utf8');\n } catch {\n return null;\n }\n try {\n const parsed = JSON.parse(raw) as DirectorStateSnapshot;\n if (parsed?.version !== 1) return null;\n return parsed;\n } catch {\n return null;\n }\n}\n\n/**\n * Lock file entry written when a director starts. Prevents two directors\n * from resuming the same run — the second one sees the lock and refuses\n * rather than corrupting the checkpoint by writing concurrently.\n */\nexport interface DirectorStateLock {\n pid: number;\n hostname: string;\n startedAt: string;\n}\n\n/**\n * Write a lock file to claim this checkpoint. Returns false if the lock\n * is already held by a live process; returns true if the lock was acquired\n * (either the file didn't exist, or the previous holder is dead).\n */\nexport async function acquireDirectorStateLock(\n lockPath: string,\n processId = process.pid,\n): Promise<boolean> {\n let existing: string | undefined;\n try {\n existing = await fsp.readFile(lockPath, 'utf8');\n } catch {\n // No lock file — we're safe to claim\n }\n\n if (existing) {\n try {\n const lock = JSON.parse(existing) as DirectorStateLock;\n // Check if the process is still alive\n try {\n process.kill(lock.pid, 0);\n // Signal success means the process is alive — another director\n // owns this checkpoint. Refuse.\n return false;\n } catch {\n // ESRCH means the process is dead — stale lock. We'll overwrite.\n }\n } catch {\n // Malformed lock — treat as stale.\n }\n }\n\n const lock: DirectorStateLock = {\n pid: processId,\n hostname: hostname(),\n startedAt: new Date().toISOString(),\n };\n await atomicWrite(lockPath, JSON.stringify(lock), { mode: 0o600 });\n return true;\n}\n\n/**\n * Remove the lock file. Call this on graceful Director.shutdown() so the\n * next director run can claim the checkpoint without stale-lock checks.\n */\nexport async function releaseDirectorStateLock(lockPath: string): Promise<void> {\n try {\n await fsp.unlink(lockPath);\n } catch {\n // ignore\n }\n}\n\n/**\n * In-memory accumulator with atomic-write checkpoint. The Director keeps\n * an instance, mutates it on every spawn/assign/complete/fail event, and\n * the instance debounces writes so a burst of activity collapses into a\n * single disk hit.\n *\n * Supports crash recovery: use `loadDirectorState()` to read an existing\n * checkpoint, then call `DirectorStateCheckpoint.resume(snapshot)` to\n * re-attach to a fleet mid-flight. The lock mechanism ensures no two\n * directors can claim the same checkpoint.\n */\nexport class DirectorStateCheckpoint {\n private snapshot: DirectorStateSnapshot;\n private readonly filePath: string;\n private readonly lockPath: string;\n private timer: NodeJS.Timeout | null = null;\n private readonly debounceMs: number;\n private writing = false;\n private rewriteRequested = false;\n\n constructor(\n filePath: string,\n init: {\n directorRunId: string;\n maxSpawns?: number | undefined;\n spawnDepth: number;\n maxSpawnDepth: number;\n directorBudget?: {\n maxCostUsd?: number | undefined;\n } | undefined;\n },\n debounceMs = 250,\n ) {\n this.filePath = filePath;\n // Lock file lives alongside the checkpoint — `<path>.lock`\n this.lockPath = `${filePath}.lock`;\n this.debounceMs = debounceMs;\n this.snapshot = {\n version: 1,\n directorRunId: init.directorRunId,\n updatedAt: new Date().toISOString(),\n spawnCount: 0,\n maxSpawns: init.maxSpawns,\n spawnDepth: init.spawnDepth,\n maxSpawnDepth: init.maxSpawnDepth,\n directorBudget: init.directorBudget,\n subagents: [],\n tasks: [],\n };\n }\n\n /**\n * Attempt to acquire the lock for this checkpoint. Call this before\n * resuming a crashed director run. If it returns false, another\n * director process is still running this fleet — do not resume.\n */\n async acquireLock(): Promise<boolean> {\n return acquireDirectorStateLock(this.lockPath);\n }\n\n /**\n * Release the lock on graceful shutdown. Call `flush()` first to ensure\n * the final checkpoint state is on disk before removing the lock.\n * Without this, the next resume will see a stale-lock and refuse.\n */\n async releaseLock(): Promise<void> {\n return releaseDirectorStateLock(this.lockPath);\n }\n\n /**\n * Resume from a snapshot previously loaded via `loadDirectorState()`.\n * Use this when `--resume <runId>` is triggered — the snapshot has\n * the full fleet state (subagents, tasks) from before the crash; the\n * checkpoint continues from there.\n */\n resume(snapshot: DirectorStateSnapshot): void {\n this.snapshot = snapshot;\n }\n\n current(): DirectorStateSnapshot {\n return this.snapshot;\n }\n\n recordSpawn(sub: DirectorSubagentState, spawnCount: number): void {\n this.snapshot = {\n ...this.snapshot,\n spawnCount,\n subagents: [...this.snapshot.subagents.filter((s) => s.id !== sub.id), sub],\n };\n this.bumpUpdatedAt();\n this.schedule();\n }\n\n recordTaskAssigned(task: DirectorTaskState): void {\n const exists = this.snapshot.tasks.some((t) => t.taskId === task.taskId);\n this.snapshot = {\n ...this.snapshot,\n tasks: exists\n ? this.snapshot.tasks.map((t) => (t.taskId === task.taskId ? { ...t, ...task } : t))\n : [...this.snapshot.tasks, task],\n };\n this.bumpUpdatedAt();\n this.schedule();\n }\n\n recordTaskStatus(\n taskId: string,\n patch: Partial<DirectorTaskState> & { status: DirectorTaskState['status'] },\n ): void {\n this.snapshot = {\n ...this.snapshot,\n tasks: this.snapshot.tasks.map((t) =>\n t.taskId === taskId ? { ...t, ...patch } : t,\n ),\n };\n this.bumpUpdatedAt();\n this.schedule();\n }\n\n setUsage(usage: unknown): void {\n this.snapshot = { ...this.snapshot, usage };\n this.bumpUpdatedAt();\n this.schedule();\n }\n\n /** Force a synchronous flush — used by Director.shutdown(). */\n async flush(): Promise<void> {\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n await this.persist();\n // If a rewrite was requested while we waited, persist() scheduled\n // a follow-up write. Loop until no more rewrites are requested so\n // shutdown doesn't return before the most recent state lands on disk.\n /* v8 ignore start -- concurrency-defensive: persist()'s finally clears the flag in single-threaded flow */\n while (this.rewriteRequested) {\n this.rewriteRequested = false;\n await this.persist();\n }\n /* v8 ignore stop */\n }\n\n private bumpUpdatedAt(): void {\n this.snapshot = { ...this.snapshot, updatedAt: new Date().toISOString() };\n }\n\n private schedule(): void {\n if (this.timer) return;\n this.timer = setTimeout(() => {\n this.timer = null;\n void this.persist();\n }, this.debounceMs);\n }\n\n private async persist(): Promise<void> {\n if (this.writing) {\n // A write is already in flight — defer to a follow-up flush so the\n // most recent state still lands. Without this guard, simultaneous\n // burst mutations can drop the latest snapshot if rename races.\n this.rewriteRequested = true;\n return;\n }\n this.writing = true;\n try {\n await atomicWrite(this.filePath, JSON.stringify(this.snapshot, null, 2), {\n mode: 0o600,\n });\n } catch (err) {\n console.warn(\n '[director-state] checkpoint write failed:',\n toErrorMessage(err),\n );\n } finally {\n this.writing = false;\n /* v8 ignore start -- concurrency-defensive: rewriteRequested is only set by an overlapping persist() */\n if (this.rewriteRequested) {\n this.rewriteRequested = false;\n this.schedule();\n }\n /* v8 ignore stop */\n }\n }\n}\n","import * as fsp from 'node:fs/promises';\nimport type { EventBus } from '../kernel/events.js';\nimport { atomicWrite, withFileLock } from '../utils/atomic-write.js';\nimport { toErrorMessage } from '../utils/error.js';\nimport { color } from '../utils/color.js';\nimport { resolveWstackPaths } from '../utils/wstack-paths.js';\nimport { FsError, ERROR_CODES } from '../types/errors.js';\n\n/**\n * Long-running autonomous mission. A goal survives across sessions and\n * drives the EternalAutonomyEngine — every iteration of the engine\n * consults the goal to choose what to do next.\n *\n * Storage: `~/.wrongstack/projects/<hash>/goal.json`. Persistent and\n * project-scoped on purpose: the goal belongs to the codebase, not the\n * REPL session.\n */\n\nexport interface JournalEntry {\n /** ISO timestamp of the iteration. */\n at: string;\n /** Sequential iteration counter (1-based, monotonically increasing). */\n iteration: number;\n /** Source that produced the action ('todo' | 'git' | 'brainstorm' | 'resume' | 'manual' | 'parallel'). */\n source: 'todo' | 'git' | 'brainstorm' | 'resume' | 'manual' | 'parallel';\n /** Short one-line description of what the iteration set out to do. */\n task: string;\n /** Outcome status. */\n status: 'success' | 'failure' | 'aborted' | 'skipped';\n /** Optional free-form note (error message, summary, etc.). */\n note?: string | undefined;\n /** Optional token usage delta for this iteration. */\n tokens?: { input: number; output: number } | undefined;\n /** Optional USD cost delta for this iteration (provider-estimated). */\n costUsd?: number | undefined;\n}\n\nexport interface GoalFile {\n version: 1;\n /** The raw mission statement as entered by the user. */\n goal: string;\n /**\n * LLM-refined version of the goal — unambiguous, with concrete\n * deliverables and acceptance criteria.\n */\n refinedGoal?: string | undefined;\n /**\n * Concrete, verifiable deliverables extracted from the refined goal.\n */\n deliverables?: string[] | undefined;\n /**\n * Estimated completion 0-100. Updated by the engine after each\n * iteration. Null means \"not yet assessed\".\n */\n progress?: number | undefined;\n /** Human-readable note explaining the current progress estimate. */\n progressNote?: string | undefined;\n /**\n * Time-series of progress measurements for trend analysis.\n * Last 200 entries retained. Use `recordProgress()` to append.\n */\n progressHistory?: ProgressSnapshot[] | undefined;\n /**\n * Computed trend from recent progress measurements.\n * 'accelerating' | 'steady' | 'stalling' | undefined.\n */\n progressTrend?: 'accelerating' | 'steady' | 'stalling' | undefined;\n /** When the goal was first set or last replaced. */\n setAt: string;\n /** Updated on every iteration completion. */\n lastActivityAt: string;\n /** Total iterations the engine has run against this goal (cumulative). */\n iterations: number;\n /** Engine lifecycle state — 'running' means another process owns this goal. */\n engineState: 'idle' | 'running' | 'stopped';\n /**\n * Mission-level lifecycle.\n */\n goalState?: 'active' | 'paused' | 'completed' | 'abandoned' | undefined;\n /**\n * Per-todo attempt counter.\n */\n todoAttempts?: Record<string, number>;\n /** Bounded ring buffer of recent iterations (newest last). */\n journal: JournalEntry[];\n}\n\n/** Cap on persisted journal entries — older entries are evicted FIFO. */\nexport const MAX_JOURNAL_ENTRIES = 500;\n\n/**\n * Resolve the goal file path for a given project root.\n *\n * SINGLE canonical location: the per-project directory that\n * `resolveWstackPaths()` uses for everything else (sessions, memory, specs) —\n * `~/.wrongstack/projects/<slug>/goal.json`. This is the same path the `/goal`\n * slash command writes via `opts.paths.projectGoal`, so every reader/writer\n * (the eternal/parallel autonomy engines, the CLI autonomy commands, the TUI\n * F9 panel, and `/goal` itself) now agree on one file.\n *\n * Previously this returned a SEPARATE hash-based dir (`projects/<hash>/`), which\n * disagreed with `/goal` and littered the home dir with thousands of stray\n * `<hash>/goal.json` directories that held nothing else.\n */\nexport function goalFilePath(projectRoot: string): string {\n return resolveWstackPaths({ projectRoot }).projectGoal;\n}\n\nexport async function loadGoal(filePath: string, events?: EventBus): Promise<GoalFile | null> {\n const t0 = Date.now();\n let raw: string;\n try {\n raw = await fsp.readFile(filePath, 'utf8');\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') {\n events?.emit('storage.read', {\n sessionId: '~boot~',\n store: 'goal',\n filePath,\n operation: 'load',\n outcome: 'success',\n durationMs: Date.now() - t0,\n });\n return null; // file doesn't exist — not an error\n }\n events?.emit('storage.error', {\n sessionId: '~boot~',\n store: 'goal',\n filePath,\n operation: 'load',\n error: toErrorMessage(err),\n recoverable: false,\n });\n throw err; // permission errors etc. should surface\n }\n try {\n const parsed = JSON.parse(raw) as GoalFile;\n if (parsed?.version !== 1 || typeof parsed.goal !== 'string' || !Array.isArray(parsed.journal)) {\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'goal_store.invalid_schema',\n path: filePath,\n message: 'invalid schema — consider deleting and re-creating',\n timestamp: new Date().toISOString(),\n }));\n events?.emit('storage.read', {\n sessionId: '~boot~',\n store: 'goal',\n filePath,\n operation: 'load',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'invalid_schema',\n });\n return null;\n }\n events?.emit('storage.read', {\n sessionId: '~boot~',\n store: 'goal',\n filePath,\n operation: 'load',\n outcome: 'success',\n durationMs: Date.now() - t0,\n });\n return parsed;\n } catch {\n console.warn(JSON.stringify({\n level: 'warn',\n event: 'goal_store.parse_failed',\n path: filePath,\n message: 'JSON parse failed — consider deleting and re-creating',\n timestamp: new Date().toISOString(),\n }));\n events?.emit('storage.read', {\n sessionId: '~boot~',\n store: 'goal',\n filePath,\n operation: 'load',\n outcome: 'failure',\n durationMs: Date.now() - t0,\n error: 'parse_failed',\n });\n return null;\n }\n}\n\nexport async function saveGoal(filePath: string, goal: GoalFile, events?: EventBus): Promise<void> {\n const t0 = Date.now();\n try {\n await atomicWrite(filePath, JSON.stringify(goal, null, 2), { mode: 0o600 });\n events?.emit('storage.write', {\n sessionId: '~boot~',\n store: 'goal',\n filePath,\n operation: 'save',\n outcome: 'success',\n durationMs: Date.now() - t0,\n });\n } catch (err) {\n events?.emit('storage.error', {\n sessionId: '~boot~',\n store: 'goal',\n filePath,\n operation: 'save',\n error: toErrorMessage(err),\n recoverable: false,\n });\n throw new FsError({\n message: toErrorMessage(err),\n code: ERROR_CODES.FS_ATOMIC_WRITE_FAILED,\n path: filePath,\n cause: err,\n });\n }\n}\n\n/**\n * Atomically load, modify, and save a goal file under a file lock.\n * Prevents lost-update races when the autonomy engine and CLI /goal commands\n * write concurrently (both eternal and parallel engines may run simultaneously).\n *\n * `fn` receives the current GoalFile (or `null` if no goal exists yet)\n * and must return the updated GoalFile (or `null` to delete).\n */\nexport async function updateGoal(\n filePath: string,\n fn: (current: GoalFile | null) => GoalFile | null,\n events?: EventBus,\n): Promise<void> {\n const t0 = Date.now();\n await withFileLock(filePath, async () => {\n const current = await loadGoal(filePath, events);\n const next = fn(current);\n if (next) {\n await saveGoal(filePath, next, events);\n } else {\n try {\n await fsp.unlink(filePath);\n events?.emit('storage.write', {\n sessionId: '~boot~',\n store: 'goal',\n filePath,\n operation: 'delete',\n outcome: 'success',\n durationMs: Date.now() - t0,\n });\n } catch (err) {\n events?.emit('storage.error', {\n sessionId: '~boot~',\n store: 'goal',\n filePath,\n operation: 'delete',\n error: toErrorMessage(err),\n recoverable: true,\n });\n // best-effort — file may not exist\n }\n }\n events?.emit('storage.write', {\n sessionId: '~boot~',\n store: 'goal',\n filePath,\n operation: 'update',\n outcome: 'success',\n durationMs: Date.now() - t0,\n });\n });\n}\n\nexport function emptyGoal(goal: string): GoalFile {\n const now = new Date().toISOString();\n return {\n version: 1,\n goal,\n setAt: now,\n lastActivityAt: now,\n iterations: 0,\n engineState: 'idle',\n goalState: 'active',\n todoAttempts: {},\n journal: [],\n };\n}\n\n/**\n * Set progress estimate on a goal. Returns a new GoalFile.\n * Clamps progress to 0-100.\n */\nexport function setProgress(\n goal: GoalFile,\n progress: number,\n note?: string,\n): GoalFile {\n const clamped = Math.min(100, Math.max(0, progress));\n return {\n ...goal,\n progress: clamped,\n progressNote: note ?? clamped + '% complete',\n };\n}\n\n/**\n * Append a journal entry, bumping iteration counters and trimming the\n * ring buffer. Returns a new GoalFile — does not mutate the argument.\n */\nexport function appendJournal(goal: GoalFile, entry: Omit<JournalEntry, 'iteration' | 'at'>): GoalFile {\n const iteration = goal.iterations + 1;\n const at = new Date().toISOString();\n const full: JournalEntry = { ...entry, iteration, at };\n const journal = [...goal.journal, full];\n const trimmed = journal.length > MAX_JOURNAL_ENTRIES\n ? journal.slice(journal.length - MAX_JOURNAL_ENTRIES)\n : journal;\n return {\n ...goal,\n iterations: iteration,\n lastActivityAt: at,\n journal: trimmed,\n };\n}\n\n/**\n * Aggregate cumulative cost + tokens across all journal entries.\n */\nexport function summarizeUsage(goal: GoalFile): {\n totalCostUsd: number;\n totalInputTokens: number;\n totalOutputTokens: number;\n iterationsWithUsage: number;\n} {\n let totalCostUsd = 0;\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n let iterationsWithUsage = 0;\n for (const e of goal.journal) {\n if (typeof e.costUsd === 'number') totalCostUsd += e.costUsd;\n if (e.tokens) {\n totalInputTokens += e.tokens.input;\n totalOutputTokens += e.tokens.output;\n }\n if (typeof e.costUsd === 'number' || e.tokens) iterationsWithUsage++;\n }\n return { totalCostUsd, totalInputTokens, totalOutputTokens, iterationsWithUsage };\n}\n\nconst DOLLAR = '\\u0024';\n\n/** Format the goal + recent journal as a human-readable status block. */\nexport function formatGoal(goal: GoalFile, journalLimit = 10): string {\n const lines: string[] = [];\n\n // Header — show refined goal, with original as annotation if different\n const displayGoal = goal.refinedGoal || goal.goal;\n lines.push(color.bold('Goal') + ': ' + displayGoal);\n if (goal.refinedGoal && goal.refinedGoal !== goal.goal) {\n const snippet = goal.goal.length > 60 ? goal.goal.slice(0, 60) + '…' : goal.goal;\n lines.push(color.dim(' (original: \"' + snippet + '\")'));\n }\n\n // Progress bar (20-segment)\n if (typeof goal.progress === 'number') {\n const pct = Math.min(100, Math.max(0, Math.round(goal.progress)));\n const filled = Math.round(pct / 5);\n const empty = 20 - filled;\n const bar = color.green('█'.repeat(filled)) + color.dim('░'.repeat(empty));\n lines.push('Progress: ' + bar + ' ' + color.bold(pct + '%'));\n if (goal.progressNote) {\n lines.push(' ' + color.dim(goal.progressNote));\n }\n // Trend indicator\n if (goal.progressTrend) {\n const trendIcon = goal.progressTrend === 'accelerating' ? '🚀'\n : goal.progressTrend === 'stalling' ? '⚠️'\n : '➡️';\n lines.push(' Trend: ' + trendIcon + ' ' + goal.progressTrend);\n }\n }\n\n // Deliverables checklist\n if (goal.deliverables && goal.deliverables.length > 0) {\n lines.push('');\n lines.push(color.bold('Deliverables:'));\n for (const d of goal.deliverables) {\n const done = /^\\[[x✓]\\]|✅|\\(done\\)/i.test(d);\n const marker = done ? color.green('✓') : color.dim('○');\n lines.push(' ' + marker + ' ' + d);\n }\n }\n\n lines.push('');\n lines.push('Set: ' + goal.setAt);\n lines.push('Last activity: ' + goal.lastActivityAt);\n lines.push('Iterations: ' + goal.iterations);\n const stateLabel = goal.goalState ?? 'active';\n lines.push('State: ' + stateLabel + (goal.iterations > 0 ? ' (iteration #' + goal.iterations + ')' : ''));\n lines.push('Engine: ' + goal.engineState);\n const usage = summarizeUsage(goal);\n if (usage.iterationsWithUsage > 0) {\n const spent = 'Spent: ' + DOLLAR + usage.totalCostUsd.toFixed(4)\n + ' (in ' + usage.totalInputTokens + ' / out ' + usage.totalOutputTokens\n + ' tokens across ' + usage.iterationsWithUsage + ' iterations)';\n lines.push(spent);\n }\n if (goal.journal.length > 0) {\n lines.push('');\n lines.push('Recent journal (last ' + Math.min(journalLimit, goal.journal.length) + '):');\n const tail = goal.journal.slice(-journalLimit);\n for (const e of tail) {\n const mark = e.status === 'success' ? '✓' : e.status === 'failure' ? '✗' : e.status === 'aborted' ? '⊘' : '·';\n const note = e.note ? ' — ' + e.note : '';\n const cost = typeof e.costUsd === 'number' ? ' (' + DOLLAR + e.costUsd.toFixed(4) + ')' : '';\n lines.push(' #' + e.iteration + ' ' + mark + ' [' + e.source + '] ' + e.task + cost + note);\n }\n }\n return lines.join('\\n');\n}\n\n/** A single progress measurement at a point in time. */\nexport interface ProgressSnapshot {\n at: string;\n progress: number;\n note?: string | undefined;\n}\n\n/**\n * Parse [PROGRESS: N%] from agent final text.\n * Supports formats:\n * [PROGRESS: 45%]\n * [PROGRESS: 45%] — 3/5 deliverables done\n * [progress: 100%]\n * Returns null if no match.\n */\nexport function parseProgressFromText(text: string): { progress: number; note?: string } | null {\n const re = /\\[progress:\\s*(\\d{1,3})%\\]\\s*(?:[—-]\\s*(.+))?/i;\n const m = text.match(re);\n if (!m) return null;\n // Regex match guarantees capture group 1 exists, but use ?? fallback to\n // satisfy noUncheckedIndexedAccess without a non-null assertion.\n const progress = Math.min(100, Math.max(0, Number.parseInt(m[1] ?? '0', 10)));\n const note = m[2]?.trim() || undefined;\n return note === undefined ? { progress } : { progress, note };\n}\n\n/**\n * Record a progress measurement. Returns a new GoalFile with:\n * - progress + progressNote updated\n * - progressHistory appended (last 200 entries kept)\n * - progress trend computed (accelerating/steady/stalling)\n */\nexport function recordProgress(\n goal: GoalFile,\n progress: number,\n note?: string,\n): GoalFile {\n const clamped = Math.min(100, Math.max(0, progress));\n const history = [...(goal.progressHistory ?? []), { at: new Date().toISOString(), progress: clamped, note }];\n // Keep last 200 snapshots\n const trimmed = history.length > 200 ? history.slice(-200) : history;\n\n return {\n ...goal,\n progress: clamped,\n progressNote: note ?? `${clamped}% complete`,\n progressHistory: trimmed,\n progressTrend: computeTrend(trimmed),\n };\n}\n\n/** Max progress history entries to retain. */\nexport const MAX_PROGRESS_HISTORY = 200;\n\nfunction computeTrend(history: ProgressSnapshot[]): 'accelerating' | 'steady' | 'stalling' | undefined {\n if (history.length < 3) return undefined;\n const recent = history.slice(-5);\n const deltas: number[] = [];\n for (let i = 1; i < recent.length; i++) {\n deltas.push((recent[i]?.progress ?? 0) - (recent[i - 1]?.progress ?? 0));\n }\n /* v8 ignore next -- unreachable: history.length>=3 guard above guarantees >=2 deltas */\n if (deltas.length < 2) return undefined;\n const avgDelta = deltas.reduce((a, b) => a + b, 0) / deltas.length;\n if (avgDelta > 2) return 'accelerating';\n if (avgDelta < -1) return 'stalling';\n return 'steady';\n}\n","import { createHash } from 'node:crypto';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { PromptEntry, PromptVariable } from '../types/prompt.js';\nimport { atomicWrite, ensureDir } from '../utils/atomic-write.js';\nimport { slugify } from '../utils/slug.js';\nimport { ulid } from '../utils/ulid.js';\nimport type { WstackPaths } from '../utils/wstack-paths.js';\n\nexport type { PromptEntry, PromptSource, PromptVariable } from '../types/prompt.js';\n\nexport interface PromptStore {\n list(): Promise<PromptEntry[]>;\n get(id: string): Promise<PromptEntry | null>;\n save(entry: PromptEntry): Promise<void>;\n delete(id: string): Promise<boolean>;\n find(query: string): Promise<PromptEntry[]>;\n}\n\n/** Current on-disk schema version. */\nconst SCHEMA_VERSION = 2;\n\ninterface RawPromptFile {\n version: number;\n entry: unknown;\n}\n\n/** sha256 of a prompt's content — used for builtin/synced integrity checks. */\nexport function promptChecksum(content: string): string {\n return createHash('sha256').update(content, 'utf8').digest('hex');\n}\n\n/**\n * Upgrade any persisted prompt record (v1 or v2) to a fully-populated v2\n * `PromptEntry`. Pure — does not touch disk. v1 records (only\n * `id/title/content/tags/createdAt/updatedAt`) get sensible defaults:\n * slug from title, empty description, `uncategorized` category, `user` source.\n */\nexport function migratePromptEntry(raw: unknown): PromptEntry | null {\n if (!raw || typeof raw !== 'object') return null;\n const r = raw as Record<string, unknown>;\n if (typeof r['id'] !== 'string' || typeof r['title'] !== 'string') return null;\n\n const title = r['title'];\n const content = typeof r['content'] === 'string' ? r['content'] : '';\n const now = typeof r['createdAt'] === 'string' ? r['createdAt'] : new Date(0).toISOString();\n const tags = Array.isArray(r['tags'])\n ? (r['tags'].filter((t) => typeof t === 'string') as string[])\n : [];\n\n return {\n id: r['id'],\n slug: typeof r['slug'] === 'string' && r['slug'].length > 0 ? r['slug'] : slugify(title),\n title,\n description: typeof r['description'] === 'string' ? r['description'] : '',\n content,\n category:\n typeof r['category'] === 'string' && r['category'].length > 0\n ? r['category']\n : 'uncategorized',\n tags,\n source: isPromptSource(r['source']) ? r['source'] : 'user',\n favorite: r['favorite'] === true,\n variables: normalizeVariables(r['variables']),\n author: typeof r['author'] === 'string' ? r['author'] : undefined,\n version: typeof r['version'] === 'string' ? r['version'] : undefined,\n license: typeof r['license'] === 'string' ? r['license'] : undefined,\n checksum: typeof r['checksum'] === 'string' ? r['checksum'] : undefined,\n forkedFrom: typeof r['forkedFrom'] === 'string' ? r['forkedFrom'] : undefined,\n createdAt: now,\n updatedAt: typeof r['updatedAt'] === 'string' ? r['updatedAt'] : now,\n };\n}\n\nfunction isPromptSource(v: unknown): v is PromptEntry['source'] {\n return v === 'builtin' || v === 'user' || v === 'project' || v === 'synced';\n}\n\nfunction normalizeVariables(v: unknown): PromptVariable[] | undefined {\n if (!Array.isArray(v)) return undefined;\n const out: PromptVariable[] = [];\n for (const item of v) {\n if (\n item &&\n typeof item === 'object' &&\n typeof (item as Record<string, unknown>)['name'] === 'string'\n ) {\n const o = item as Record<string, unknown>;\n const enumVals =\n Array.isArray(o['enum']) && o['enum'].every((x) => typeof x === 'string')\n ? (o['enum'] as string[])\n : undefined;\n out.push({\n name: o['name'] as string,\n description: typeof o['description'] === 'string' ? o['description'] : undefined,\n default: typeof o['default'] === 'string' ? o['default'] : undefined,\n required: o['required'] === true ? true : undefined,\n enum: enumVals && enumVals.length > 0 ? enumVals : undefined,\n multiline: o['multiline'] === true ? true : undefined,\n });\n }\n }\n return out.length > 0 ? out : undefined;\n}\n\n/**\n * DefaultPromptStore — file-per-prompt JSON in a single directory (the global\n * `~/.wrongstack/prompts` by default, or a layer dir the loader passes in).\n * Reads tolerate legacy v1 files via `migratePromptEntry`; writes always emit\n * the current v2 schema.\n */\nexport class DefaultPromptStore implements PromptStore {\n private readonly dir: string;\n\n constructor(pathsOrDir: WstackPaths | string) {\n this.dir = typeof pathsOrDir === 'string' ? pathsOrDir : pathsOrDir.globalPrompts;\n }\n\n async list(): Promise<PromptEntry[]> {\n await ensureDir(this.dir);\n const entries: PromptEntry[] = [];\n try {\n const files = await fs.readdir(this.dir);\n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n try {\n const raw: RawPromptFile = JSON.parse(\n await fs.readFile(path.join(this.dir, file), 'utf8'),\n );\n const migrated = migratePromptEntry(raw.entry);\n if (migrated) entries.push(migrated);\n } catch {\n // skip corrupt files\n }\n }\n } catch {\n // dir doesn't exist yet\n }\n return entries.sort(\n (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(),\n );\n }\n\n async get(id: string): Promise<PromptEntry | null> {\n const file = path.join(this.dir, `${id}.json`);\n try {\n const raw: RawPromptFile = JSON.parse(await fs.readFile(file, 'utf8'));\n return migratePromptEntry(raw.entry);\n } catch {\n return null;\n }\n }\n\n async save(entry: PromptEntry): Promise<void> {\n await ensureDir(this.dir);\n const file = path.join(this.dir, `${entry.id}.json`);\n const raw: RawPromptFile = { version: SCHEMA_VERSION, entry };\n await atomicWrite(file, JSON.stringify(raw, null, 2));\n }\n\n async delete(id: string): Promise<boolean> {\n const file = path.join(this.dir, `${id}.json`);\n try {\n await fs.unlink(file);\n return true;\n } catch {\n return false;\n }\n }\n\n async find(query: string): Promise<PromptEntry[]> {\n const all = await this.list();\n const lower = query.toLowerCase();\n return all.filter(\n (e) =>\n e.title.toLowerCase().includes(lower) ||\n e.description.toLowerCase().includes(lower) ||\n e.content.toLowerCase().includes(lower) ||\n e.category.toLowerCase().includes(lower) ||\n e.tags.some((t) => t.toLowerCase().includes(lower)),\n );\n }\n\n /** Create a new v2 entry and return it. Does NOT persist — call save() afterwards. */\n createNew(\n title: string,\n content: string,\n tags: string[] = [],\n extra: Partial<\n Omit<PromptEntry, 'id' | 'title' | 'content' | 'tags' | 'createdAt' | 'updatedAt'>\n > = {},\n ): PromptEntry {\n const now = new Date().toISOString();\n return {\n id: ulid(),\n slug: extra.slug && extra.slug.length > 0 ? extra.slug : slugify(title),\n title,\n description: extra.description ?? '',\n content,\n category: extra.category ?? 'uncategorized',\n tags,\n source: extra.source ?? 'user',\n favorite: extra.favorite ?? false,\n variables: extra.variables,\n author: extra.author,\n version: extra.version,\n license: extra.license,\n checksum: extra.checksum,\n forkedFrom: extra.forkedFrom,\n createdAt: now,\n updatedAt: now,\n };\n }\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { atomicWrite, ensureDir } from '../utils/atomic-write.js';\n\nexport interface PromptUsage {\n count: number;\n lastUsedAt: string;\n}\n\ninterface RawUsageFile {\n version: 1;\n usage: Record<string, PromptUsage>;\n}\n\n/**\n * Tracks how often each prompt is inserted, keyed by slug, in a single JSON\n * file (`~/.wrongstack/prompt-usage.json`). Kept SEPARATE from the prompt\n * entries so usage can be recorded for read-only builtin prompts without\n * copy-on-writing them into the user layer. Surfaces \"recent / most-used\"\n * views and a gentle search-ranking boost.\n */\nexport class PromptUsageStore {\n constructor(private readonly file: string) {}\n\n async load(): Promise<Record<string, PromptUsage>> {\n try {\n const raw: RawUsageFile = JSON.parse(await fs.readFile(this.file, 'utf8'));\n if (raw && typeof raw === 'object' && raw.usage && typeof raw.usage === 'object') {\n return raw.usage;\n }\n } catch {\n // missing or corrupt → empty\n }\n return {};\n }\n\n async record(slug: string, at: string = new Date().toISOString()): Promise<PromptUsage> {\n const usage = await this.load();\n const prev = usage[slug];\n const next: PromptUsage = { count: (prev?.count ?? 0) + 1, lastUsedAt: at };\n usage[slug] = next;\n await ensureDir(path.dirname(this.file));\n await atomicWrite(this.file, JSON.stringify({ version: 1, usage } satisfies RawUsageFile, null, 2));\n return next;\n }\n\n async get(slug: string): Promise<PromptUsage | undefined> {\n return (await this.load())[slug];\n }\n\n /** Slugs ordered by most-recently-used (then by count), capped at `limit`. */\n async recent(limit = 15): Promise<{ slug: string; usage: PromptUsage }[]> {\n const usage = await this.load();\n return Object.entries(usage)\n .map(([slug, u]) => ({ slug, usage: u }))\n .sort(\n (a, b) =>\n new Date(b.usage.lastUsedAt).getTime() - new Date(a.usage.lastUsedAt).getTime() ||\n b.usage.count - a.usage.count,\n )\n .slice(0, limit);\n }\n\n /** Slugs ordered by usage count (then recency), capped at `limit`. */\n async top(limit = 15): Promise<{ slug: string; usage: PromptUsage }[]> {\n const usage = await this.load();\n return Object.entries(usage)\n .map(([slug, u]) => ({ slug, usage: u }))\n .sort(\n (a, b) =>\n b.usage.count - a.usage.count ||\n new Date(b.usage.lastUsedAt).getTime() - new Date(a.usage.lastUsedAt).getTime(),\n )\n .slice(0, limit);\n }\n}\n","import { expectDefined } from '../utils/expect-defined.js';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { createHash } from 'node:crypto';\nimport type { WstackPaths } from '../utils/wstack-paths.js';\nimport type { SyncCategory, SyncConfig } from '../types/config.js';\nimport { FsError, WrongStackError, ERROR_CODES } from '../types/errors.js';\nexport const ALL_SYNC_CATEGORIES: SyncCategory[] = ['settings', 'skills', 'prompts', 'memory', 'history'];\n\nexport interface SyncResult {\n ok: boolean;\n action: 'push' | 'pull';\n categories: SyncCategory[];\n committedAt?: string | undefined;\n message: string;\n}\n\ninterface SyncStateFile {\n version: 1;\n sha: string;\n lastSyncedAt: string;\n localRev: string;\n}\n\n/**\n * CloudSync — push/pull user-selected ~/.wrongstack categories to a\n * private GitHub repo. No git CLI needed; uses GitHub REST API via fetch.\n * The token is stored encrypted via SecretVault (field named `githubToken`\n * so the vault walker picks it up automatically).\n */\nexport class CloudSync {\n private readonly statePath: string;\n private state: SyncStateFile | null = null;\n\n constructor(\n private readonly paths: WstackPaths,\n private readonly getConfig: () => SyncConfig | null,\n private readonly setConfig: (c: SyncConfig) => Promise<void>,\n ) {\n this.statePath = path.join(paths.globalRoot, 'sync-state.json');\n }\n\n // ── Public API ─────────────────────────────────────────────────────\n\n async status(): Promise<string> {\n const cfg = this.getConfig();\n if (!cfg?.enabled) {\n return 'CloudSync: disabled. Run `/sync enable` to activate.';\n }\n const last = this.state?.lastSyncedAt;\n const since = last ? timeAgo(last) : 'never';\n return [\n `CloudSync: enabled`,\n ` repo: ${cfg.repo}`,\n ` categories: ${cfg.categories.join(', ')}`,\n ` last sync: ${since}`,\n ].join('\\n');\n }\n\n async enable(_repo: string, _categories: SyncCategory[]): Promise<string> {\n // Persisted by the slash command via configStore.update.\n return 'Enable via /sync enable.';\n }\n\n async disable(): Promise<string> {\n const cfg = this.getConfig();\n if (!cfg) return 'CloudSync is not configured.';\n const next = { ...cfg, enabled: false };\n await this.setConfig(next);\n return 'CloudSync disabled. Local data kept.';\n }\n\n async push(token: string): Promise<SyncResult> {\n const cfg = this.getConfig();\n if (!cfg?.enabled) return { ok: false, action: 'push', categories: [], message: 'Not enabled.' };\n\n const parts = cfg.repo.split('/');\n const owner = expectDefined(parts[0]);\n const repoName = expectDefined(parts[1]);\n const branch = 'main';\n const baseTreeSha = this.state?.sha;\n\n const { treeEntries, rev } = await this.buildLocalTree(cfg.categories);\n const newTreeSha = await this.createGitTree(token, owner, repoName, treeEntries, baseTreeSha);\n\n const commitSha = await this.createCommit(\n token, owner, repoName, newTreeSha,\n baseTreeSha,\n `Sync ${cfg.categories.join(', ')} — ${new Date().toISOString()}`,\n );\n\n try {\n await this.updateRef(token, owner, repoName, branch, commitSha);\n } catch (err) {\n // 422 = not a fast forward — remote branch moved. Fetch latest SHA and retry.\n if (err instanceof Error && err.message.includes('422')) {\n const remote = await this.getRef(token, owner, repoName, branch);\n const currentSha = remote.object.sha;\n const rebasedCommitSha = await this.createCommit(\n token, owner, repoName, newTreeSha,\n currentSha,\n `Sync ${cfg.categories.join(', ')} — ${new Date().toISOString()}`,\n );\n await this.updateRef(token, owner, repoName, branch, rebasedCommitSha);\n } else {\n throw err;\n }\n }\n\n const syncState: SyncStateFile = {\n version: 1,\n sha: commitSha,\n lastSyncedAt: new Date().toISOString(),\n localRev: rev,\n };\n await fs.writeFile(this.statePath, JSON.stringify(syncState, null, 2), 'utf8');\n this.state = syncState;\n\n return {\n ok: true,\n action: 'push',\n categories: cfg.categories,\n committedAt: commitSha,\n message: `Pushed ${cfg.categories.join(', ')} to ${cfg.repo}. Commit: ${commitSha.slice(0, 7)}`,\n };\n }\n\n async pull(token: string): Promise<SyncResult> {\n const cfg = this.getConfig();\n if (!cfg?.enabled) return { ok: false, action: 'pull', categories: [], message: 'Not enabled.' };\n\n const pullParts = cfg.repo.split('/');\n const owner = expectDefined(pullParts[0]);\n const repoName = expectDefined(pullParts[1]);\n\n const branchData = await this.getRef(token, owner, repoName, 'main');\n const currentSha = branchData.object.sha;\n\n const commitData = await this.getCommit(token, owner, repoName, currentSha);\n const treeSha = commitData.tree.sha;\n\n const treeEntries = await this.getTreeEntries(token, owner, repoName, treeSha);\n\n for (const entry of treeEntries) {\n if (entry.type !== 'blob') continue;\n\n // Paths look like \"data/{category}/...\" — extract the category\n const segments = entry.path.split('/');\n if (segments[0] !== 'data' || !segments[1]) continue;\n const cat = segments[1] as SyncCategory;\n if (!['settings', 'skills', 'prompts', 'memory', 'history'].includes(cat)) continue;\n\n const localPath = this.categoryToPath(cat);\n if (!localPath) continue;\n\n // Reconstruct relative path under the category dir. Remote trees are\n // untrusted input: a compromised sync repo could contain paths like\n // data/skills/../../config.json. Keep every write inside the selected\n // category root, and only allow subpaths for directory-backed categories.\n const rel = segments.slice(2).join('/');\n const destPath = resolvePulledCategoryPath(cat, localPath, rel, entry.path);\n\n const blobData = await this.getBlob(token, owner, repoName, entry.sha);\n await fs.mkdir(path.dirname(destPath), { recursive: true });\n await fs.writeFile(destPath, Buffer.from(blobData, 'base64'));\n }\n\n const localRev = await this.hashLocalCategories(cfg.categories);\n const syncState: SyncStateFile = {\n version: 1,\n sha: currentSha,\n lastSyncedAt: new Date().toISOString(),\n localRev,\n };\n await fs.writeFile(this.statePath, JSON.stringify(syncState, null, 2), 'utf8');\n this.state = syncState;\n\n return {\n ok: true,\n action: 'pull',\n categories: cfg.categories,\n committedAt: currentSha,\n message: `Pulled ${cfg.categories.join(', ')} from ${cfg.repo}. Commit: ${currentSha.slice(0, 7)}`,\n };\n }\n\n async hasLocalChanges(): Promise<boolean> {\n if (!this.state) return true;\n const cfg = this.getConfig();\n if (!cfg) return true;\n const current = await this.hashLocalCategories(cfg.categories);\n return current !== this.state.localRev;\n }\n\n async loadState(): Promise<void> {\n try {\n const raw = await fs.readFile(this.statePath, 'utf8');\n this.state = JSON.parse(raw) as SyncStateFile;\n } catch {\n this.state = null;\n }\n }\n\n // ── GitHub API helpers ──────────────────────────────────────────────\n\n private async githubFetch(\n token: string,\n owner: string,\n repo: string,\n method: 'GET' | 'POST' | 'PUT' | 'PATCH',\n pathSegment: string,\n body?: unknown | undefined,\n ): Promise<unknown> {\n const url = `https://api.github.com/repos/${owner}/${repo}${pathSegment}`;\n const init: RequestInit = {\n signal: AbortSignal.timeout(15_000),\n method,\n headers: {\n Authorization: `Bearer ${token}`,\n Accept: 'application/vnd.github+json',\n 'X-GitHub-Api-Version': '2022-11-28',\n 'Content-Type': 'application/json',\n },\n };\n if (body !== undefined) init.body = JSON.stringify(body);\n const res = await fetch(url, init);\n\n if (!res.ok) {\n const errText = await res.text();\n throw new WrongStackError({\n message: `GitHub API ${method} ${pathSegment} failed (${res.status}): ${errText}`,\n code: ERROR_CODES.UNKNOWN,\n subsystem: 'general',\n context: { method, pathSegment, status: res.status, repo: `${owner}/${repo}` },\n });\n }\n\n const text = await res.text();\n return text ? JSON.parse(text) : {};\n }\n\n private async getRef(token: string, owner: string, repo: string, ref: string) {\n return (await this.githubFetch(token, owner, repo, 'GET', `/git/refs/heads/${ref}`)) as {\n object: { sha: string };\n };\n }\n\n private async updateRef(token: string, owner: string, repo: string, ref: string, sha: string) {\n await this.githubFetch(token, owner, repo, 'PATCH', `/git/refs/heads/${ref}`, {\n sha,\n force: false,\n });\n }\n\n private async getCommit(token: string, owner: string, repo: string, sha: string) {\n return (await this.githubFetch(token, owner, repo, 'GET', `/git/commits/${sha}`)) as {\n tree: { sha: string };\n message: string;\n };\n }\n\n private async getTreeEntries(token: string, owner: string, repo: string, treeSha: string) {\n return (await this.githubFetch(token, owner, repo, 'GET', `/git/trees/${treeSha}?recursive=1`)) as Array<{\n path: string;\n sha: string;\n type: 'blob' | 'tree';\n }>;\n }\n\n private async createCommit(\n token: string, owner: string, repo: string,\n treeSha: string, parentSha?: string | undefined, message = 'sync',\n ) {\n const body: Record<string, unknown> = { message, tree: treeSha };\n if (parentSha) body.parents = [parentSha];\n const result = (await this.githubFetch(token, owner, repo, 'POST', '/git/commits', body)) as { sha: string };\n return result.sha;\n }\n\n private async createGitTree(\n token: string, owner: string, repo: string,\n entries: Array<{ path: string; content: string; mode: string }>,\n baseTreeSha?: string | undefined,\n ): Promise<string> {\n const tree = entries.map((e) => ({\n path: e.path,\n mode: e.mode,\n type: 'blob',\n content: e.content,\n }));\n const body: Record<string, unknown> = { tree };\n if (baseTreeSha) body.base_tree = baseTreeSha;\n const result = (await this.githubFetch(token, owner, repo, 'POST', '/git/trees', body)) as { sha: string };\n return result.sha;\n }\n\n private async getBlob(token: string, owner: string, repo: string, sha: string): Promise<string> {\n const result = (await this.githubFetch(token, owner, repo, 'GET', `/git/blobs/${sha}`)) as { content: string };\n return result.content;\n }\n\n // ── Local file helpers ──────────────────────────────────────────────\n\n private async buildLocalTree(categories: SyncCategory[]): Promise<{\n treeEntries: Array<{ path: string; content: string; mode: string }>;\n rev: string;\n }> {\n const entries: Array<{ path: string; content: string; mode: string }> = [];\n const hashes: string[] = [];\n\n for (const cat of categories) {\n const localPath = this.categoryToPath(cat);\n if (!localPath) continue;\n try {\n const stat = await fs.stat(localPath);\n if (stat.isDirectory()) {\n const files = await this.walkDir(localPath, localPath);\n for (const file of files) {\n const content = await fs.readFile(file, 'utf8');\n const rel = path.relative(localPath, file).replace(/\\\\/g, '/');\n entries.push({ path: `data/${cat}/${rel}`, content, mode: '100644' });\n hashes.push(content);\n }\n } else {\n const content = await fs.readFile(localPath, 'utf8');\n entries.push({ path: `data/${cat}`, content, mode: '100644' });\n hashes.push(content);\n }\n } catch {\n // skip missing files/dirs\n }\n }\n\n const rev = createHash('sha256').update(hashes.join('')).digest('hex').slice(0, 12);\n return { treeEntries: entries, rev };\n }\n\n private async hashLocalCategories(categories: SyncCategory[]): Promise<string> {\n const hashes: string[] = [];\n for (const cat of categories) {\n const localPath = this.categoryToPath(cat);\n if (!localPath) continue;\n try {\n const stat = await fs.stat(localPath);\n if (stat.isDirectory()) {\n const files = await this.walkDir(localPath, localPath);\n for (const file of files) {\n const content = await fs.readFile(file);\n hashes.push(content.toString('base64') + file);\n }\n } else {\n const content = await fs.readFile(localPath);\n hashes.push(content.toString('base64') + localPath);\n }\n } catch {\n // skip\n }\n }\n return createHash('sha256').update(hashes.join('')).digest('hex').slice(0, 12);\n }\n\n private categoryToPath(cat: SyncCategory): string | null {\n switch (cat) {\n case 'settings': return this.paths.globalConfig;\n case 'skills': return this.paths.globalSkills;\n case 'prompts': return this.paths.globalPrompts;\n case 'memory': return this.paths.globalMemory;\n case 'history': return this.paths.historyFile;\n /* v8 ignore next -- unreachable: SyncCategory is exhaustively matched above */\n default: return null;\n }\n }\n\n private async walkDir(dir: string, base: string): Promise<string[]> {\n const results: string[] = [];\n const entries = await fs.readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n results.push(...(await this.walkDir(full, base)));\n } else {\n results.push(full);\n }\n }\n return results;\n }\n}\n\nfunction resolvePulledCategoryPath(\n cat: SyncCategory,\n localPath: string,\n rel: string,\n remotePath: string,\n): string {\n const directoryBacked = cat === 'skills' || cat === 'prompts';\n if (!directoryBacked) {\n if (rel) throw new FsError({\n message: `Refusing nested CloudSync path for file category: ${remotePath}`,\n code: ERROR_CODES.FS_DELETE_FAILED,\n path: remotePath,\n context: { reason: 'nested_file_category', category: cat },\n });\n return localPath;\n }\n\n if (!rel) return localPath;\n const normalizedRel = path.normalize(rel);\n const traversesUp = normalizedRel === '..' || normalizedRel.startsWith(`..${path.sep}`);\n if (path.isAbsolute(normalizedRel) || traversesUp) {\n throw new FsError({\n message: `Refusing CloudSync path traversal: ${remotePath}`,\n code: ERROR_CODES.FS_DELETE_FAILED,\n path: remotePath,\n context: { reason: 'path_traversal', normalizedRel },\n });\n }\n\n const dest = path.resolve(localPath, normalizedRel);\n const root = path.resolve(localPath);\n const relative = path.relative(root, dest);\n /* v8 ignore start -- unreachable: the normalizedRel '..' guard above already rejects traversal */\n if (relative.startsWith('..') || path.isAbsolute(relative)) {\n throw new FsError({\n message: `Refusing CloudSync path outside category root: ${remotePath}`,\n code: ERROR_CODES.FS_DELETE_FAILED,\n path: remotePath,\n context: { reason: 'outside_category_root', category: cat },\n });\n }\n /* v8 ignore stop */\n return dest;\n}\n\nfunction timeAgo(iso: string): string {\n const diff = Date.now() - new Date(iso).getTime();\n const mins = Math.floor(diff / 60_000);\n if (mins < 1) return 'just now';\n if (mins < 60) return `${mins}m ago`;\n const hrs = Math.floor(mins / 60);\n if (hrs < 24) return `${hrs}h ago`;\n const days = Math.floor(hrs / 24);\n return `${days}d ago`;\n}\n","import type { SessionEvent, SessionWriter } from '../types/session.js';\n\nexport type AuditLevel = 'minimal' | 'standard' | 'full';\n\n/**\n * Configuration for sampling high-volume events inside the bridge.\n * This allows callers (CLI, TUI, WebUI, plugins) to tune how aggressively\n * noisy events like tool progress are persisted.\n */\nexport interface ToolProgressSamplingOptions {\n /**\n * How often to persist 'log' and 'partial_output' progress events.\n * - 1 = every message (no sampling)\n * - 8 = keep the first message + every 8th after that (default)\n */\n sampleRate?: number | undefined;\n}\n\nexport interface SessionSamplingOptions {\n /** Controls sampling behavior for `tool_progress` events (only relevant at auditLevel 'full'). */\n toolProgress?: ToolProgressSamplingOptions | undefined;\n}\n\nexport interface SessionEventBridgeOptions {\n /** Sampling rules for high-volume audit events. */\n sampling?: SessionSamplingOptions | undefined;\n}\n\n/**\n * Small, safe helper that wraps a SessionWriter and enforces the\n * configured auditLevel.\n *\n * All appends are best-effort. Failures are swallowed (with optional\n * diagnostics) so they never crash the agent loop.\n */\nexport interface SessionEventBridge {\n /** Append an event if allowed by the current audit level. */\n append(event: SessionEvent): Promise<void>;\n /** Batch-append events allowed by the current audit level. */\n appendBatch(events: SessionEvent[]): Promise<void>;\n\n /** Current audit level. Reflects the latest {@link setAuditLevel} value. */\n readonly level: AuditLevel;\n\n /**\n * Change the audit level on a live bridge. Subsequent appends are filtered\n * by the new level — used by the TUI `/settings` picker to apply an\n * `auditLevel` change to the running session without a restart.\n */\n setAuditLevel(level: AuditLevel): void;\n\n /** Returns true if an event of this type should be written at the current level. */\n allows(type: SessionEvent['type']): boolean;\n}\n\n/** Core events that are always written regardless of auditLevel. */\nconst CORE_RECONSTRUCT_EVENTS = new Set<SessionEvent['type']>([\n 'session_start',\n 'session_resumed',\n 'user_input',\n 'llm_response',\n 'tool_result',\n 'checkpoint',\n 'file_snapshot',\n 'rewound',\n 'in_flight_start',\n 'in_flight_end',\n 'session_end',\n]);\n\n/**\n * Events that are considered \"standard\" audit detail.\n * These are lightweight and high-value for forensics.\n */\nconst STANDARD_AUDIT_EVENTS = new Set<SessionEvent['type']>([\n 'llm_request',\n 'tool_use',\n 'tool_call_start',\n 'tool_call_end',\n 'compaction',\n 'error',\n 'message_truncated',\n 'provider_retry',\n 'provider_error',\n]);\n\n/**\n * Events that are only allowed at 'full' audit level because they can be\n * very high volume (e.g. streaming tool output).\n */\nconst FULL_ONLY_EVENTS = new Set<SessionEvent['type']>([\n 'tool_progress',\n]);\n\n/**\n * \"full\" level allows everything (including potentially heavy events\n * that plugins or future code may emit).\n */\nfunction isAllowed(type: SessionEvent['type'], level: AuditLevel): boolean {\n if (CORE_RECONSTRUCT_EVENTS.has(type)) return true;\n if (level === 'minimal') return false;\n\n if (STANDARD_AUDIT_EVENTS.has(type)) return true;\n if (level === 'standard') return false;\n\n // 'full' level events (high volume)\n if (FULL_ONLY_EVENTS.has(type)) {\n return level === 'full';\n }\n\n // 'full' — allow everything else\n return true;\n}\n\n/**\n * Create a safe, audit-level-aware bridge around a SessionWriter.\n *\n * The bridge can also apply sampling for high-volume events (e.g. `tool_progress`)\n * when `auditLevel` is set to `'full'`.\n *\n * @example\n * const bridge = createSessionEventBridge(sessionWriter, 'full', {\n * sampling: {\n * toolProgress: { sampleRate: 5 } // more aggressive sampling\n * }\n * });\n */\nexport function createSessionEventBridge(\n writer:\n | SessionWriter\n | (() => SessionWriter | undefined | null)\n | undefined\n | null,\n level: AuditLevel = 'standard',\n options: SessionEventBridgeOptions = {},\n): SessionEventBridge {\n // Mutable so setAuditLevel() can re-tune a live bridge in place.\n let currentLevel: AuditLevel = level ?? 'standard';\n\n // Accept either a writer instance or a getter. A getter lets long-lived\n // hosts (CLI/TUI/WebUI) resolve the CURRENT writer on every append — when\n // the user resumes another session mid-run, audit events follow the swap\n // instead of being silently dropped into the old, closed writer.\n const resolveWriter: () => SessionWriter | undefined | null =\n typeof writer === 'function' ? writer : () => writer;\n\n // Internal sampling state for high-volume events (e.g. tool_progress).\n // Keyed by tool call id (or name as fallback) to keep sampling per-call.\n const progressCounters = new Map<string, number>();\n\n const toolProgressConfig = options.sampling?.toolProgress ?? {};\n const TOOL_PROGRESS_SAMPLE_RATE = toolProgressConfig.sampleRate ?? 8;\n\n /**\n * Decide whether a high-volume event should be sampled in.\n * Currently only implements sampling for 'tool_progress'.\n */\n function shouldSample(event: SessionEvent): boolean {\n if (event.type !== 'tool_progress') return true;\n\n const progEvent = event as Extract<SessionEvent, { type: 'tool_progress' }>;\n const innerType = progEvent.event?.type;\n\n // Always let through high-signal structured events\n if (innerType === 'warning' || innerType === 'metric' || innerType === 'file_changed') {\n return true;\n }\n\n // Sample noisy text streams (log / partial_output)\n if (innerType === 'log' || innerType === 'partial_output') {\n const key = progEvent.id || progEvent.name;\n const count = (progressCounters.get(key) || 0) + 1;\n progressCounters.set(key, count);\n\n // Always keep the first message + every Nth after that\n return count === 1 || (count % TOOL_PROGRESS_SAMPLE_RATE === 0);\n }\n\n return true;\n }\n\n return {\n get level() {\n return currentLevel;\n },\n\n setAuditLevel(next) {\n currentLevel = next ?? 'standard';\n },\n\n allows(type) {\n return isAllowed(type, currentLevel);\n },\n\n async append(event) {\n const target = resolveWriter();\n if (!target) return;\n if (!isAllowed(event.type, currentLevel)) return;\n\n // Apply sampling for high-volume events (only at 'full' level)\n if (!shouldSample(event)) return;\n\n try {\n await target.append(event);\n } catch (_err) {\n // Best-effort: never let session logging break the agent.\n // The existing FileSessionWriter already does throttled warnings,\n // but we keep this wrapper silent by default to avoid log spam.\n // Callers that care can listen to EventBus 'session.damaged' etc.\n }\n },\n\n async appendBatch(events) {\n const target = resolveWriter();\n if (!target || events.length === 0) return;\n const allowed = events.filter(\n (e) => isAllowed(e.type, currentLevel) && shouldSample(e),\n );\n if (allowed.length === 0) return;\n try {\n await target.appendBatch(allowed);\n } catch {\n // best-effort — same contract as append()\n }\n },\n };\n}\n\n/** Convenience re-export of the allowed core set for tests/docs. */\nexport { CORE_RECONSTRUCT_EVENTS, STANDARD_AUDIT_EVENTS };\n\n/**\n * Safely extract the auditLevel from a (possibly partial) Config object.\n * Falls back to 'standard' if not present or invalid.\n */\nexport function resolveAuditLevel(\n cfg?: { session?: { auditLevel?: AuditLevel | undefined } | undefined } | null,\n): AuditLevel {\n const raw = cfg?.session?.auditLevel;\n if (raw === 'minimal' || raw === 'standard' || raw === 'full') {\n return raw;\n }\n return 'standard';\n}\n\n/**\n * Fully resolves the session logging configuration with sensible defaults.\n * This is the recommended way for the CLI / TUI / WebUI to read session config.\n */\nexport function resolveSessionLoggingConfig(\n cfg?: {\n session?: {\n auditLevel?: AuditLevel | undefined;\n sampling?: {\n toolProgress?: { sampleRate?: number | undefined };\n };\n };\n } | null,\n): {\n auditLevel: AuditLevel;\n sampling: {\n toolProgress: { sampleRate: number };\n };\n} {\n const session = cfg?.session ?? {};\n\n const auditLevel = resolveAuditLevel(cfg);\n\n const toolProgressSampleRate =\n session.sampling?.toolProgress?.sampleRate ?? 8;\n\n return {\n auditLevel,\n sampling: {\n toolProgress: {\n sampleRate: Math.max(1, Math.floor(toolProgressSampleRate)),\n },\n },\n };\n}"]}