@letrquan/book 0.2.0 → 0.3.0

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 (157) hide show
  1. package/CHANGELOG.md +2747 -40
  2. package/README.md +132 -1311
  3. package/dist/additional-roots-H7UNAEHS.js +31 -0
  4. package/dist/{app-MOXXWEOY.js → app-GE4OHJOC.js} +5740 -4045
  5. package/dist/app-GE4OHJOC.js.map +1 -0
  6. package/dist/{chunk-5GDZ22YP.js → chunk-224FJZLH.js} +99 -108
  7. package/dist/chunk-224FJZLH.js.map +1 -0
  8. package/dist/chunk-2AAOF5B5.js +28 -0
  9. package/dist/chunk-2AAOF5B5.js.map +1 -0
  10. package/dist/{chunk-CAGOB2N4.js → chunk-4AS7LKKQ.js} +6 -4
  11. package/dist/chunk-4AS7LKKQ.js.map +1 -0
  12. package/dist/chunk-525CAZPY.js +120 -0
  13. package/dist/chunk-525CAZPY.js.map +1 -0
  14. package/dist/{chunk-URLQAXTR.js → chunk-56SIEMDX.js} +2 -2
  15. package/dist/chunk-56SIEMDX.js.map +1 -0
  16. package/dist/{chunk-XIFFTATU.js → chunk-5YHTKWJN.js} +5420 -4031
  17. package/dist/chunk-5YHTKWJN.js.map +1 -0
  18. package/dist/chunk-62QL5QUP.js +283 -0
  19. package/dist/chunk-62QL5QUP.js.map +1 -0
  20. package/dist/{chunk-KWHQ2XXL.js → chunk-67UZEWWF.js} +3 -3
  21. package/dist/chunk-67UZEWWF.js.map +1 -0
  22. package/dist/chunk-6OQQOMZR.js +785 -0
  23. package/dist/chunk-6OQQOMZR.js.map +1 -0
  24. package/dist/{chunk-GTVB4HEM.js → chunk-AQEQX4FF.js} +344 -315
  25. package/dist/chunk-AQEQX4FF.js.map +1 -0
  26. package/dist/chunk-C7ADUNPR.js +273 -0
  27. package/dist/chunk-C7ADUNPR.js.map +1 -0
  28. package/dist/{chunk-E75IPST5.js → chunk-EFJ2NH6E.js} +12 -58
  29. package/dist/chunk-EFJ2NH6E.js.map +1 -0
  30. package/dist/{chunk-5KLVH3PY.js → chunk-HQI7NYGX.js} +5 -3
  31. package/dist/chunk-HQI7NYGX.js.map +1 -0
  32. package/dist/chunk-IME7R2UI.js +6541 -0
  33. package/dist/chunk-IME7R2UI.js.map +1 -0
  34. package/dist/chunk-J4F2QLM2.js +273 -0
  35. package/dist/chunk-J4F2QLM2.js.map +1 -0
  36. package/dist/{chunk-MAQXCUR4.js → chunk-J62VZYOB.js} +444 -112
  37. package/dist/chunk-J62VZYOB.js.map +1 -0
  38. package/dist/chunk-JTPOI3KU.js +826 -0
  39. package/dist/chunk-JTPOI3KU.js.map +1 -0
  40. package/dist/{chunk-WKBO5R4O.js → chunk-KBQS35OV.js} +2 -2
  41. package/dist/chunk-KBQS35OV.js.map +1 -0
  42. package/dist/chunk-KXAYUIKP.js +90 -0
  43. package/dist/chunk-KXAYUIKP.js.map +1 -0
  44. package/dist/{chunk-VZQXX3WW.js → chunk-QYBD22H5.js} +1 -1
  45. package/dist/chunk-QYBD22H5.js.map +1 -0
  46. package/dist/{chunk-V4BOYR52.js → chunk-RFJ6Q6LE.js} +763 -198
  47. package/dist/chunk-RFJ6Q6LE.js.map +1 -0
  48. package/dist/{chunk-7N4J557C.js → chunk-RT5SATF7.js} +1 -1
  49. package/dist/chunk-RT5SATF7.js.map +1 -0
  50. package/dist/{chunk-C7D4NJ2D.js → chunk-S4JMID4G.js} +68 -26
  51. package/dist/chunk-S4JMID4G.js.map +1 -0
  52. package/dist/{chunk-ANSJPYGI.js → chunk-SOW4WRQP.js} +3 -3
  53. package/dist/chunk-SOW4WRQP.js.map +1 -0
  54. package/dist/{chunk-J7MIZ5CA.js → chunk-TLX3H2CL.js} +518 -79
  55. package/dist/chunk-TLX3H2CL.js.map +1 -0
  56. package/dist/{chunk-DGMQEI6Y.js → chunk-VPNLCMVR.js} +22 -9
  57. package/dist/chunk-VPNLCMVR.js.map +1 -0
  58. package/dist/{chunk-BTZZUCLI.js → chunk-W3XFHEF4.js} +173 -29
  59. package/dist/chunk-W3XFHEF4.js.map +1 -0
  60. package/dist/{chunk-574C6MQR.js → chunk-X4NJT436.js} +130 -60
  61. package/dist/chunk-X4NJT436.js.map +1 -0
  62. package/dist/chunk-X66I2NQO.js +137 -0
  63. package/dist/chunk-X66I2NQO.js.map +1 -0
  64. package/dist/chunk-XHAO3K7I.js +18 -0
  65. package/dist/chunk-XHAO3K7I.js.map +1 -0
  66. package/dist/{chunk-3U5IBM24.js → chunk-Y2VHN7TC.js} +2 -2
  67. package/dist/chunk-Y2VHN7TC.js.map +1 -0
  68. package/dist/chunk-YC6W4EJH.js +947 -0
  69. package/dist/chunk-YC6W4EJH.js.map +1 -0
  70. package/dist/{chunk-24AXE6SP.js → chunk-ZPSZZUWF.js} +1 -1
  71. package/dist/chunk-ZPSZZUWF.js.map +1 -0
  72. package/dist/{command-approvals-6Y57VCWZ.js → command-approvals-VBIU6BLM.js} +6 -5
  73. package/dist/context-CBOBDY5Q.js +38 -0
  74. package/dist/{hook-approvals-CTUFKEJT.js → hook-approvals-ZVT4V7IM.js} +5 -5
  75. package/dist/index.js +996 -155
  76. package/dist/index.js.map +1 -1
  77. package/dist/{interactive-assets-CCAAWVKH.js → interactive-assets-T4I4SEHU.js} +13 -9
  78. package/dist/interactive-assets-T4I4SEHU.js.map +1 -0
  79. package/dist/job-runner.js +159 -111
  80. package/dist/job-runner.js.map +1 -1
  81. package/dist/job-supervisor.d.ts +2 -0
  82. package/dist/job-supervisor.js +112 -0
  83. package/dist/job-supervisor.js.map +1 -0
  84. package/dist/loader-S77OVTHH.js +18 -0
  85. package/dist/{mcp-approvals-WNPH65BK.js → mcp-approvals-HJ2VDYMC.js} +5 -5
  86. package/dist/{mcp-config-YIJIES2C.js → mcp-config-RNB5LEVE.js} +3 -3
  87. package/dist/memory-store-DZUT5HUH.js +75 -0
  88. package/dist/{model-window-store-YFVNXCIP.js → model-window-store-MTSQ5JDJ.js} +8 -4
  89. package/dist/openai-compatible-2OB54YST.js +14 -0
  90. package/dist/{permission-approvals-76PVREFD.js → permission-approvals-YLV6UC5W.js} +5 -5
  91. package/dist/permissions-DHOKF3W2.js +45 -0
  92. package/dist/sandbox-WRYTZH3D.js +41 -0
  93. package/dist/{scrollback-LUKLIBVI.js → scrollback-35ME2GFX.js} +32 -22
  94. package/dist/scrollback-35ME2GFX.js.map +1 -0
  95. package/dist/sdk.d.ts +2219 -2361
  96. package/dist/sdk.js +53 -38
  97. package/dist/sdk.js.map +1 -1
  98. package/dist/settings-loader-JUNPGAAM.js +35 -0
  99. package/dist/settings-loader-JUNPGAAM.js.map +1 -0
  100. package/dist/{shell-selection-V6QAYXPX.js → shell-selection-CDHGJ4GC.js} +2 -2
  101. package/dist/shell-selection-CDHGJ4GC.js.map +1 -0
  102. package/package.json +23 -22
  103. package/dist/app-MOXXWEOY.js.map +0 -1
  104. package/dist/chunk-24AXE6SP.js.map +0 -1
  105. package/dist/chunk-3U5IBM24.js.map +0 -1
  106. package/dist/chunk-574C6MQR.js.map +0 -1
  107. package/dist/chunk-5GDZ22YP.js.map +0 -1
  108. package/dist/chunk-5KLVH3PY.js.map +0 -1
  109. package/dist/chunk-7N4J557C.js.map +0 -1
  110. package/dist/chunk-A7JLBK2Y.js +0 -3506
  111. package/dist/chunk-A7JLBK2Y.js.map +0 -1
  112. package/dist/chunk-ANSJPYGI.js.map +0 -1
  113. package/dist/chunk-BTZZUCLI.js.map +0 -1
  114. package/dist/chunk-C7D4NJ2D.js.map +0 -1
  115. package/dist/chunk-CAGOB2N4.js.map +0 -1
  116. package/dist/chunk-DGMQEI6Y.js.map +0 -1
  117. package/dist/chunk-E75IPST5.js.map +0 -1
  118. package/dist/chunk-EYGD6X2T.js +0 -180
  119. package/dist/chunk-EYGD6X2T.js.map +0 -1
  120. package/dist/chunk-GTVB4HEM.js.map +0 -1
  121. package/dist/chunk-J7MIZ5CA.js.map +0 -1
  122. package/dist/chunk-KWHQ2XXL.js.map +0 -1
  123. package/dist/chunk-L6LK2QIQ.js +0 -657
  124. package/dist/chunk-L6LK2QIQ.js.map +0 -1
  125. package/dist/chunk-MAQXCUR4.js.map +0 -1
  126. package/dist/chunk-S4XL7HOM.js +0 -402
  127. package/dist/chunk-S4XL7HOM.js.map +0 -1
  128. package/dist/chunk-URLQAXTR.js.map +0 -1
  129. package/dist/chunk-V4BOYR52.js.map +0 -1
  130. package/dist/chunk-VZQXX3WW.js.map +0 -1
  131. package/dist/chunk-WKBO5R4O.js.map +0 -1
  132. package/dist/chunk-XIFFTATU.js.map +0 -1
  133. package/dist/context-ZC5IFEAX.js +0 -25
  134. package/dist/interactive-assets-CCAAWVKH.js.map +0 -1
  135. package/dist/loader-4IDS2RIE.js +0 -15
  136. package/dist/openai-compatible-RHZUBHV6.js +0 -10
  137. package/dist/permissions-CHCKTFQQ.js +0 -28
  138. package/dist/sandbox-CNVAQDA7.js +0 -23
  139. package/dist/scrollback-LUKLIBVI.js.map +0 -1
  140. package/dist/settings-loader-M2QP5TX2.js +0 -21
  141. package/patches/ink+6.8.0.patch +0 -13
  142. package/scripts/apply-ink-patch.mjs +0 -29
  143. package/scripts/ink-patch.mjs +0 -59
  144. package/scripts/verify-ink-patch.mjs +0 -11
  145. /package/dist/{command-approvals-6Y57VCWZ.js.map → additional-roots-H7UNAEHS.js.map} +0 -0
  146. /package/dist/{context-ZC5IFEAX.js.map → command-approvals-VBIU6BLM.js.map} +0 -0
  147. /package/dist/{hook-approvals-CTUFKEJT.js.map → context-CBOBDY5Q.js.map} +0 -0
  148. /package/dist/{loader-4IDS2RIE.js.map → hook-approvals-ZVT4V7IM.js.map} +0 -0
  149. /package/dist/{mcp-approvals-WNPH65BK.js.map → loader-S77OVTHH.js.map} +0 -0
  150. /package/dist/{mcp-config-YIJIES2C.js.map → mcp-approvals-HJ2VDYMC.js.map} +0 -0
  151. /package/dist/{model-window-store-YFVNXCIP.js.map → mcp-config-RNB5LEVE.js.map} +0 -0
  152. /package/dist/{openai-compatible-RHZUBHV6.js.map → memory-store-DZUT5HUH.js.map} +0 -0
  153. /package/dist/{permission-approvals-76PVREFD.js.map → model-window-store-MTSQ5JDJ.js.map} +0 -0
  154. /package/dist/{permissions-CHCKTFQQ.js.map → openai-compatible-2OB54YST.js.map} +0 -0
  155. /package/dist/{sandbox-CNVAQDA7.js.map → permission-approvals-YLV6UC5W.js.map} +0 -0
  156. /package/dist/{settings-loader-M2QP5TX2.js.map → permissions-DHOKF3W2.js.map} +0 -0
  157. /package/dist/{shell-selection-V6QAYXPX.js.map → sandbox-WRYTZH3D.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/memory-store.ts","../src/secret-detect.ts"],"sourcesContent":["import {\n existsSync,\n lstatSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n renameSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from 'fs';\nimport { createHash } from 'crypto';\nimport { basename, isAbsolute, join, relative, resolve } from 'path';\nimport { parseFrontmatter } from './frontmatter.js';\nimport { writeFileAtomic } from './settings-repository.js';\nimport { permissionRuleMatchesCall } from './permissions.js';\nimport { resolveBookHome } from './book-home.js';\nimport { looksLikeSecretOrUnfit } from './secret-detect.js';\nimport type { SessionDriver } from './types/runtime.js';\n\nexport const MEMORY_TYPES = ['user', 'feedback', 'project', 'reference'] as const;\nexport type MemoryType = (typeof MEMORY_TYPES)[number];\nexport type MemoryStatus = 'approved' | 'pending' | 'discarded' | 'superseded';\nexport type MemoryOrigin = 'model-tool' | 'extraction' | 'user-text';\n\nexport const MAX_BODY_CHARS = 1600;\n\nexport function sanitizeMemorySlug(rawSlug: string): string | null {\n const cleaned = rawSlug\n .replace(/[\\x00-\\x1f\\x7f]/g, '')\n .replace(/[/\\\\]/g, '')\n // Index entries are parsed by their `](file)` link; these must not appear in a file name.\n .replace(/[[\\]()]/g, '')\n .trim()\n .replace(/^\\.+/, '')\n .trim();\n return cleaned.length > 0 ? cleaned : null;\n}\n\n/**\n * The last segment of a slug. Both separators are split on, so a Windows-style\n * `C:\\notes\\memory.md` names its file rather than being pasted onto `dir`.\n */\nfunction lastSlugSegment(raw: string): string {\n return raw.split(/[/\\\\]/).pop() ?? '';\n}\n\n/**\n * Resolve a raw slug to the one file it names inside the memory directory.\n *\n * The last path segment is taken first, so a path-like slug (`memory/build-cmd.md`,\n * an absolute path) names its file instead of being pasted onto `dir`. This is the\n * only place a slug is sanitized: every caller passes raw model or user input and\n * gets back a resolved filename, or the reason it cannot be used.\n */\nexport function memoryFileForSlug(\n dir: string,\n raw: string,\n): { filename: string; target: string } | { error: string } {\n const cleanSlug = sanitizeMemorySlug(lastSlugSegment(raw.trim()));\n if (!cleanSlug) return { error: 'Invalid memory slug.' };\n const filename = cleanSlug.toLowerCase().endsWith('.md') ? cleanSlug : `${cleanSlug}.md`;\n if (filename.toLowerCase() === INDEX_FILE.toLowerCase()) {\n return { error: 'Target filename cannot be the index file.' };\n }\n const target = join(dir, filename);\n const rel = relative(dir, target);\n if (rel === '' || rel.startsWith('..') || isAbsolute(rel)) {\n return { error: 'Target path must stay inside the project memory directory.' };\n }\n return { filename, target };\n}\n\n/** Whether a permission rule list names MemorySave (a bare `MemorySave` or a pattern on it). */\nexport function rulesNameMemorySave(rules: readonly string[]): boolean {\n return rules.some((rule) =>\n permissionRuleMatchesCall(rule, { id: 'memory', name: 'MemorySave', arguments: {} }),\n );\n}\n\nexport function isMemorySaveAvailable(settings?: {\n memory?: { enabled?: boolean; autoSave?: boolean };\n}): boolean {\n if (!settings?.memory) return true;\n return settings.memory.enabled !== false && settings.memory.autoSave !== false;\n}\n\n/**\n * What the model may write to memory in this session — the one rule the catalog, the prompt, the\n * tool and `/memory status` all read:\n *\n * - `none`: the settings turn model writes off.\n * - `learnings`: another agent drives the session. Its task prompt is that agent's per-task\n * contract — saving from it is how a spec's \"Ground rules\" became permanent repository memory —\n * but what the run learned by doing the work (a decision and its reason, an outcome with a\n * lesson, a verified fact) is worth keeping. So only `DELEGATED_MEMORY_TYPES`, marked\n * `driver: agent`, and only delegated entries may be changed or deleted.\n * - `full`: a person drives it.\n */\nexport type MemoryWriteScope = 'none' | 'learnings' | 'full';\n\nexport function memoryWriteScope(config: {\n settings?: { memory?: { enabled?: boolean; autoSave?: boolean } };\n sessionDriver?: SessionDriver;\n}): MemoryWriteScope {\n if (!isMemorySaveAvailable(config.settings)) return 'none';\n return config.sessionDriver === 'agent' ? 'learnings' : 'full';\n}\n\nexport function canModelWriteMemory(config: Parameters<typeof memoryWriteScope>[0]): boolean {\n return memoryWriteScope(config) !== 'none';\n}\n\n/** The types a session another agent drives may save: what it learned, never a person's preferences. */\nexport const DELEGATED_MEMORY_TYPES: readonly MemoryType[] = ['project', 'reference'];\n\nexport function sanitizeMemoryTitle(rawTitle: string): string {\n return rawTitle\n .replace(/[\\x00-\\x1f\\x7f-\\x9f]/g, ' ')\n .replace(/[[\\]()]/g, '')\n .replace(/^[\\s#]+/, '')\n .replace(/\\s+/g, ' ')\n .trim()\n .slice(0, 120)\n .trim();\n}\n\nexport function shouldRejectMemoryText(text: string): string | null {\n const trimmed = text.trim();\n if (trimmed.length === 0) return 'empty';\n if (trimmed.length > MAX_BODY_CHARS * 2) return 'too long';\n return looksLikeSecretOrUnfit(trimmed);\n}\n\nexport interface MemoryFileSummary {\n name: string;\n path: string;\n type?: MemoryType;\n status?: MemoryStatus;\n title?: string;\n created?: string;\n updated?: string;\n size: number;\n driver?: SessionDriver;\n}\n\nexport interface LoadedMemoryContext {\n dir: string;\n indexFile: string | null;\n indexLoaded: boolean;\n indexLineCount: number;\n loadedLineCount: number;\n indexText: string;\n files: MemoryFileSummary[];\n candidates: MemoryFileSummary[];\n}\n\nexport interface MemoryCandidate {\n type: MemoryType;\n title: string;\n body: string;\n origin: MemoryOrigin;\n source?: 'auto' | 'manual';\n confidence?: 'low' | 'medium' | 'high';\n tags?: string[];\n sessionId?: string;\n externalContext: boolean;\n evidence?: string[];\n targetSlug?: string;\n /** File name of an approved memory this one replaces; it is kept on disk, out of the index. */\n supersedes?: string;\n /** `agent` when a session another agent drove saved it (a delegated run's learning). */\n driver?: SessionDriver;\n}\n\nexport interface MemoryWriteInput extends Partial<MemoryCandidate> {\n supersededBy?: string;\n type: MemoryType;\n title: string;\n body: string;\n status?: MemoryStatus;\n created?: string;\n targetSlug?: string;\n}\n\nexport interface MemoryStoreOptions {\n bookRoot?: string;\n now?: Date;\n maxIndexLines?: number;\n dir?: string;\n}\n\nexport interface MemoryWriteResult {\n ok: boolean;\n path?: string;\n /** Approve only: the memory this approval retired, or why a recorded retirement was skipped. */\n retired?: string;\n retireSkipped?: string;\n error?: string;\n}\n\nexport interface SaveMemoryOptions extends MemoryStoreOptions {\n requireApproval?: boolean;\n quarantineExternal?: boolean;\n slug?: string;\n}\n\nexport interface SaveMemoryResult {\n ok: boolean;\n path?: string;\n indexLine?: string;\n /** Lines in MEMORY.md after the write — the model is asked to consolidate near the load limit. */\n indexLineCount?: number;\n /** File name of the memory this save retired (superseded). */\n retired?: string;\n status: MemoryStatus;\n quarantined?: boolean;\n error?: string;\n}\n\nexport const DEFAULT_MAX_INDEX_LINES = 200;\nconst INDEX_FILE = 'MEMORY.md';\nconst INBOX_DIR = '.inbox';\nconst DISCARDED_DIR = 'discarded';\n\nexport function slugifyWorkspace(workspace: string): string {\n return (\n workspace\n .replace(/[/\\\\:]+/g, '-')\n .replace(/[^a-zA-Z0-9._-]/g, '-')\n .replace(/^-+|-+$/g, '') || 'workspace'\n );\n}\n\nfunction bookRoot(opts?: MemoryStoreOptions): string {\n return opts?.bookRoot ?? resolveBookHome();\n}\n\nexport function getProjectMemoryDir(workspace: string, opts?: MemoryStoreOptions): string {\n return join(bookRoot(opts), 'projects', slugifyWorkspace(workspace), 'memory');\n}\n\nexport function getMemoryInboxDir(workspace: string, opts?: MemoryStoreOptions): string {\n return opts?.dir\n ? join(opts.dir, INBOX_DIR)\n : join(getProjectMemoryDir(workspace, opts), INBOX_DIR);\n}\n\nexport function getMemoryExtractionStatePath(workspace: string, opts?: MemoryStoreOptions): string {\n return join(getProjectMemoryDir(workspace, opts), '.extraction-state.json');\n}\n\nexport function getMemoryExtractionLockPath(workspace: string, opts?: MemoryStoreOptions): string {\n return join(getProjectMemoryDir(workspace, opts), '.extraction.lock');\n}\n\nfunction isMemoryType(value: unknown): value is MemoryType {\n return typeof value === 'string' && (MEMORY_TYPES as readonly string[]).includes(value);\n}\n\nfunction isMemoryStatus(value: unknown): value is MemoryStatus {\n return (\n value === 'approved' || value === 'pending' || value === 'discarded' || value === 'superseded'\n );\n}\n\nfunction titleFromBody(body: string): string | undefined {\n const firstHeading = body.split('\\n').find((line) => line.startsWith('# '));\n return firstHeading?.replace(/^#\\s+/, '').trim();\n}\n\nfunction summarizeMemoryFile(path: string, name = basename(path)): MemoryFileSummary | null {\n try {\n const st = statSync(path);\n if (!st.isFile()) return null;\n const raw = readFileSync(path, 'utf-8');\n const { body, frontmatter } = parseFrontmatter(raw);\n const proposedTitle =\n typeof frontmatter.proposedTitle === 'string' ? frontmatter.proposedTitle : undefined;\n const title =\n proposedTitle ??\n (typeof frontmatter.title === 'string' ? frontmatter.title : undefined) ??\n titleFromBody(body);\n return {\n name,\n path,\n type: isMemoryType(frontmatter.type) ? frontmatter.type : undefined,\n status: isMemoryStatus(frontmatter.status) ? frontmatter.status : undefined,\n title,\n created: typeof frontmatter.created === 'string' ? frontmatter.created : undefined,\n updated: typeof frontmatter.updated === 'string' ? frontmatter.updated : undefined,\n size: st.size,\n ...(frontmatter.driver === 'agent' ? { driver: 'agent' as const } : {}),\n };\n } catch {\n return null;\n }\n}\n\nexport function listMemoryFiles(workspace: string, opts?: MemoryStoreOptions): MemoryFileSummary[] {\n const dir = getProjectMemoryDir(workspace, opts);\n if (!existsSync(dir)) return [];\n const files: MemoryFileSummary[] = [];\n try {\n for (const entry of readdirSync(dir).sort()) {\n if (!entry.toLowerCase().endsWith('.md')) continue;\n if (entry.toLowerCase() === INDEX_FILE.toLowerCase()) continue; // MEMORY.md is the index, not an approved memory file.\n const full = join(dir, entry);\n const summary = summarizeMemoryFile(full, entry);\n // A superseded memory stays on disk as history but is no longer an active entry.\n if (summary && summary.status !== 'superseded') files.push(summary);\n }\n } catch {\n return files;\n }\n return files;\n}\n\nexport function listMemoryCandidates(\n workspace: string,\n opts?: MemoryStoreOptions,\n): MemoryFileSummary[] {\n const dir = getMemoryInboxDir(workspace, opts);\n if (!existsSync(dir)) return [];\n const files: MemoryFileSummary[] = [];\n try {\n for (const entry of readdirSync(dir).sort()) {\n if (!entry.endsWith('.md')) continue;\n const full = join(dir, entry);\n const summary = summarizeMemoryFile(full, entry);\n if (summary) files.push(summary);\n }\n } catch {\n return files;\n }\n return files;\n}\n\n// Deliberately cheaper than listMemoryCandidates(): readdir only, no frontmatter parse.\nexport function countMemoryCandidates(workspace: string, opts?: MemoryStoreOptions): number {\n const dir = getMemoryInboxDir(workspace, opts);\n if (!existsSync(dir)) return 0;\n try {\n return readdirSync(dir).filter((entry) => !entry.startsWith('.') && entry.endsWith('.md'))\n .length;\n } catch {\n return 0;\n }\n}\n\nfunction readFirstLines(\n path: string,\n maxLines: number,\n): { text: string; totalLines: number; loadedLines: number } {\n const raw = readFileSync(path, 'utf-8');\n const lines = raw.split('\\n');\n const loaded = lines.slice(0, maxLines);\n return {\n text: loaded.join('\\n').trim(),\n totalLines: lines.filter((line) => line.trim().length > 0).length,\n loadedLines: loaded.filter((line) => line.trim().length > 0).length,\n };\n}\n\nexport function loadMemoryContext(\n workspace: string,\n opts?: MemoryStoreOptions,\n): LoadedMemoryContext {\n const dir = getProjectMemoryDir(workspace, opts);\n const maxIndexLines = opts?.maxIndexLines ?? DEFAULT_MAX_INDEX_LINES;\n const result: LoadedMemoryContext = {\n dir,\n indexFile: null,\n indexLoaded: false,\n indexLineCount: 0,\n loadedLineCount: 0,\n indexText: '',\n files: [],\n candidates: [],\n };\n\n if (!existsSync(dir)) return result;\n\n const indexFile = join(dir, INDEX_FILE);\n if (existsSync(indexFile)) {\n try {\n const st = statSync(indexFile);\n if (st.isFile()) {\n const index = readFirstLines(indexFile, maxIndexLines);\n result.indexFile = indexFile;\n result.indexLoaded = index.text.length > 0;\n result.indexLineCount = index.totalLines;\n result.loadedLineCount = index.loadedLines;\n result.indexText = index.text;\n }\n } catch {\n result.indexFile = indexFile;\n }\n }\n\n result.files = listMemoryFiles(workspace, opts);\n result.candidates = listMemoryCandidates(workspace, opts);\n return result;\n}\n\nexport interface MemoryHealth {\n approvedCount: number;\n supersededCount: number;\n inboxCount: number;\n indexLineCount: number;\n lastWrite: Date | null;\n}\n\nexport function getNewestMemoryWriteTime(memoryDir: string): Date | null {\n if (!existsSync(memoryDir)) return null;\n let newestMs = 0;\n\n function scanEntries(dir: string, isInbox: boolean): void {\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (entry.startsWith('.')) {\n if (!isInbox && entry === INBOX_DIR) {\n scanEntries(join(dir, entry), true);\n }\n continue;\n }\n if (isInbox && entry === DISCARDED_DIR) {\n continue;\n }\n const full = join(dir, entry);\n try {\n const st = lstatSync(full);\n if (st.isSymbolicLink()) continue;\n if (st.isFile()) {\n if (st.mtimeMs > newestMs) newestMs = st.mtimeMs;\n }\n } catch {\n // ignore unreadable entries\n }\n }\n }\n\n scanEntries(memoryDir, false);\n return newestMs > 0 ? new Date(newestMs) : null;\n}\n\nexport function getMemoryHealth(\n workspaceOrContext: string | LoadedMemoryContext,\n opts?: MemoryStoreOptions,\n): MemoryHealth {\n const dir =\n typeof workspaceOrContext === 'string'\n ? (opts?.dir ?? getProjectMemoryDir(workspaceOrContext, opts))\n : workspaceOrContext.dir;\n const workspace = typeof workspaceOrContext === 'string' ? workspaceOrContext : '';\n\n let approvedCount = 0;\n let supersededCount = 0;\n if (existsSync(dir)) {\n try {\n for (const entry of readdirSync(dir)) {\n // Same rule as listMemoryFiles, so Health agrees with the listing.\n if (\n !entry.toLowerCase().endsWith('.md') ||\n entry.toLowerCase() === INDEX_FILE.toLowerCase()\n )\n continue;\n const full = join(dir, entry);\n try {\n const st = lstatSync(full);\n if (st.isSymbolicLink() || !st.isFile()) continue;\n const summary = summarizeMemoryFile(full, entry);\n if (summary && (summary.status === 'approved' || summary.status === undefined)) {\n approvedCount++;\n } else if (summary?.status === 'superseded') {\n supersededCount++;\n }\n } catch {\n // ignore unreadable file\n }\n }\n } catch {\n // ignore unreadable directory\n }\n }\n\n const inboxCount = countMemoryCandidates(workspace, { ...opts, dir });\n\n // Counted the way a save counts it, so Health and the pressure warning agree.\n let indexLineCount = 0;\n try {\n indexLineCount = readIndexLines(dir).length;\n } catch {\n // unreadable index\n }\n\n const lastWrite = getNewestMemoryWriteTime(dir);\n return {\n approvedCount,\n supersededCount,\n inboxCount,\n indexLineCount,\n lastWrite,\n };\n}\n\nfunction safeTitle(title: string): string {\n return (\n title\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 60) || 'memory'\n );\n}\n\nfunction shortHash(input: string): string {\n return createHash('sha256').update(input).digest('hex').slice(0, 8);\n}\n\nfunction formatTags(tags: string[] | undefined): string {\n if (!tags?.length) return '';\n return `tags:\\n${tags.map((tag) => `- ${tag}`).join('\\n')}\\n`;\n}\n\nfunction renderMemoryMarkdown(input: MemoryWriteInput, status: MemoryStatus, now: Date): string {\n const created = input.created ?? now.toISOString();\n const updated = now.toISOString();\n const sanitizedTitle = sanitizeMemoryTitle(input.title);\n const title = status === 'pending' ? `Candidate: ${sanitizedTitle}` : sanitizedTitle;\n const origin: MemoryOrigin = input.origin ?? 'user-text';\n const source = input.source ?? (origin === 'user-text' ? 'manual' : 'auto');\n const externalContext = input.externalContext ?? false;\n\n // Build frontmatter fields, dropping optional ones that are absent so we\n // don't rely on a blanket ''.filter() that would also strip the blank\n // spacer lines between the closing fence, the heading, and the body.\n const fm: string[] = [\n `type: ${input.type}`,\n `status: ${status}`,\n `origin: ${origin}`,\n `source: ${source}`,\n `externalContext: ${externalContext}`,\n `created: ${created}`,\n `updated: ${updated}`,\n ];\n if (input.sessionId) fm.push(`sessionId: ${input.sessionId}`);\n // Only the delegated case is marked: a person's memories keep the shape they always had.\n if (input.driver === 'agent') fm.push('driver: agent');\n if (input.evidence?.length) {\n fm.push(`evidence:\\n${input.evidence.map((e) => `- ${e}`).join('\\n')}`);\n }\n // Already a resolved file name: `memoryFileForSlug` sanitized it (and\n // `readMemoryFile` did the same for a candidate read back from disk).\n if (input.targetSlug) fm.push(`targetSlug: ${input.targetSlug}`);\n if (input.supersedes) fm.push(`supersedes: ${input.supersedes}`);\n if (input.supersededBy) fm.push(`supersededBy: ${input.supersededBy}`);\n if ('confidence' in input && input.confidence) fm.push(`confidence: ${input.confidence}`);\n if (status === 'pending') fm.push(`proposedTitle: ${sanitizedTitle}`);\n if (input.tags?.length) {\n fm.push(formatTags(input.tags).trimEnd());\n }\n return ['---', ...fm, '---', '', `# ${title}`, '', input.body.trim(), ''].join('\\n');\n}\n\nexport function writeMemoryCandidate(\n workspace: string,\n candidate: MemoryWriteInput,\n opts?: MemoryStoreOptions,\n): MemoryWriteResult {\n try {\n const title = sanitizeMemoryTitle(candidate.title);\n if (!title) {\n return { ok: false, error: 'title must not be empty after sanitizing.' };\n }\n const now = opts?.now ?? new Date();\n const inbox = getMemoryInboxDir(workspace, opts);\n mkdirSync(inbox, { recursive: true });\n const stamp = now.toISOString().replace(/[-:.]/g, '').slice(0, 15);\n const hash = shortHash(`${candidate.type}\\n${title}\\n${candidate.body}\\n${now.toISOString()}`);\n const filename = `${stamp}-cand-${safeTitle(title)}-${hash}.md`;\n const path = join(inbox, filename);\n writeFileSync(path, renderMemoryMarkdown({ ...candidate, title }, 'pending', now), 'utf-8');\n return { ok: true, path };\n } catch (e) {\n return { ok: false, error: e instanceof Error ? e.message : String(e) };\n }\n}\n\nfunction resolveCandidatePath(\n workspace: string,\n candidateFile: string,\n opts?: MemoryStoreOptions,\n): string | null {\n const inbox = resolve(getMemoryInboxDir(workspace, opts));\n const raw = isAbsolute(candidateFile) ? candidateFile : join(inbox, candidateFile);\n const resolved = resolve(raw);\n const rel = relative(inbox, resolved);\n if (rel === '' || rel.startsWith('..') || isAbsolute(rel)) return null;\n return resolved;\n}\n\nfunction activeMemoryFilename(\n input: { type: MemoryType; title: string; body: string },\n now: Date,\n): string {\n const date = now.toISOString().slice(0, 10);\n const hash = shortHash(`${input.type}\\n${input.title}\\n${input.body}`);\n return `${date}-${input.type}-${safeTitle(input.title)}-${hash}.md`;\n}\n\n/** A slug read back from frontmatter: last path segment, then sanitized (as on write). */\nfunction frontmatterSlug(raw: string | undefined): string | undefined {\n return raw?.trim() ? (sanitizeMemorySlug(lastSlugSegment(raw.trim())) ?? undefined) : undefined;\n}\n\nexport function readMemoryFile(\n path: string,\n): (MemoryCandidate & { created?: string; updated?: string; status?: MemoryStatus }) | null {\n try {\n const raw = readFileSync(path, 'utf-8');\n const { body, frontmatter } = parseFrontmatter(raw);\n if (!isMemoryType(frontmatter.type)) return null;\n const rawProposed =\n typeof frontmatter.proposedTitle === 'string' ? frontmatter.proposedTitle : undefined;\n const proposedTitle = rawProposed ? sanitizeMemoryTitle(rawProposed) || undefined : undefined;\n // `||`, not `??`: a title that sanitizes to '' falls through to the next source.\n const heading = titleFromBody(body)?.replace(/^Candidate:\\s*/i, '');\n const title =\n proposedTitle ||\n (typeof frontmatter.title === 'string' ? sanitizeMemoryTitle(frontmatter.title) : '') ||\n (heading ? sanitizeMemoryTitle(heading) : '') ||\n basename(path, '.md');\n const tags = Array.isArray(frontmatter.tags)\n ? frontmatter.tags.filter((t): t is string => typeof t === 'string')\n : undefined;\n const evidence = Array.isArray(frontmatter.evidence)\n ? frontmatter.evidence.filter((e): e is string => typeof e === 'string')\n : undefined;\n const cleanBody = body.replace(/^#\\s+[^\\n]*\\n+/i, '').trim() || body.trim();\n const origin: MemoryOrigin =\n frontmatter.origin === 'model-tool' ||\n frontmatter.origin === 'extraction' ||\n frontmatter.origin === 'user-text'\n ? frontmatter.origin\n : 'user-text';\n const source: 'auto' | 'manual' =\n frontmatter.source === 'manual' || frontmatter.source === 'auto'\n ? frontmatter.source\n : origin === 'user-text'\n ? 'manual'\n : 'auto';\n const externalContext =\n frontmatter.externalContext === true || frontmatter.externalContext === 'true';\n const sessionId = typeof frontmatter.sessionId === 'string' ? frontmatter.sessionId : undefined;\n const rawTargetSlug =\n typeof frontmatter.targetSlug === 'string' ? frontmatter.targetSlug : undefined;\n // The last path segment, the same rule `memoryFileForSlug` applies on write:\n // a legacy `targetSlug: notes/build` names a file in the memory directory,\n // and sanitizing alone would glue the segments together.\n const targetSlug = frontmatterSlug(rawTargetSlug);\n const status = isMemoryStatus(frontmatter.status) ? frontmatter.status : undefined;\n const created = typeof frontmatter.created === 'string' ? frontmatter.created : undefined;\n const updated = typeof frontmatter.updated === 'string' ? frontmatter.updated : undefined;\n const supersedes = frontmatterSlug(\n typeof frontmatter.supersedes === 'string' ? frontmatter.supersedes : undefined,\n );\n return {\n supersedes,\n type: frontmatter.type,\n title,\n body: cleanBody,\n origin,\n source,\n externalContext,\n sessionId,\n evidence,\n targetSlug,\n status,\n confidence:\n frontmatter.confidence === 'low' ||\n frontmatter.confidence === 'medium' ||\n frontmatter.confidence === 'high'\n ? frontmatter.confidence\n : undefined,\n tags,\n created,\n updated,\n ...(frontmatter.driver === 'agent' ? { driver: 'agent' as const } : {}),\n };\n } catch {\n return null;\n }\n}\n\nfunction parseCandidateFile(path: string): (MemoryCandidate & { created?: string }) | null {\n return readMemoryFile(path);\n}\n\n/**\n * Characters index text must not carry: control characters, and `[]()<>` — an entry is parsed\n * by its `](file)` link, and the index is embedded in a <memory-index> block.\n */\nconst INDEX_UNSAFE = /[\\x00-\\x1f\\x7f-\\x9f[\\]()<>]/g;\n\n/** The first line of a memory's body — the fact itself — as a short index hook. */\nfunction indexHook(body: string): string {\n const first =\n body.trim().split('\\n')[0]?.replace(INDEX_UNSAFE, ' ').replace(/\\s+/g, ' ').trim() ?? '';\n return first.length > 100 ? `${first.slice(0, 100)}…` : first;\n}\n\nconst sameFile = (a: string, b: string) => a.toLowerCase() === b.toLowerCase();\n\n/** The file an index entry links to; undefined for the header or any free-form line. */\nfunction indexEntryFile(line: string): string | undefined {\n return /^- \\[[^\\]]*\\]\\(([^()]+)\\)/.exec(line)?.[1];\n}\n\n/** The index's non-empty lines; throws when it exists but cannot be read, so a caller never\n * rewrites (and wipes) an index it could not read. */\nfunction readIndexLines(dir: string): string[] {\n const indexPath = join(dir, INDEX_FILE);\n if (!existsSync(indexPath)) return [];\n return readFileSync(indexPath, 'utf-8')\n .split('\\n')\n .filter((line) => line.trim().length > 0);\n}\n\n/** Atomic: a crash mid-write must not leave a truncated index that silently loads nothing. */\nfunction writeIndexLines(dir: string, lines: string[]): void {\n writeFileAtomic(\n join(dir, INDEX_FILE),\n lines.length > 0 ? lines.join('\\n') + '\\n' : '# Book memory index\\n',\n );\n}\n\n/**\n * The index lines that still describe a loadable memory. Entries whose file is gone or\n * superseded are pruned on every rewrite — so a line a failed write left behind does not load\n * forever — and so are entries for the files in `drop`.\n */\nfunction liveIndexLines(dir: string, lines: string[], drop: readonly string[]): string[] {\n return lines.filter((line) => {\n const file = indexEntryFile(line);\n if (!file) return true;\n if (drop.some((name) => sameFile(name, file))) return false;\n const path = join(dir, file);\n if (!existsSync(path)) return false;\n return summarizeMemoryFile(path, file)?.status !== 'superseded';\n });\n}\n\n/** Drop a file's line from MEMORY.md; no index means nothing to drop (and none is created). */\nfunction removeIndexEntry(dir: string, filename: string): void {\n if (!existsSync(join(dir, INDEX_FILE))) return;\n writeIndexLines(dir, liveIndexLines(dir, readIndexLines(dir), [filename]));\n}\n\n/**\n * Write or replace a file's line in MEMORY.md in one read-modify-write, also dropping the line\n * of a memory it supersedes; returns the line and the index's entry count.\n */\nfunction updateMemoryIndex(\n dir: string,\n title: string,\n filename: string,\n type: MemoryType,\n now: Date,\n body: string,\n supersedes?: string,\n): { entry: string; lineCount: number } {\n const hook = indexHook(body);\n const entry = `- [${title}](${filename}) — ${type} — ${now.toISOString().slice(0, 10)}${hook && hook !== title ? ` — ${hook}` : ''}`;\n const drop = supersedes ? [filename, supersedes] : [filename];\n let lines = liveIndexLines(dir, readIndexLines(dir), drop);\n if (lines.length === 0) {\n lines = ['# Book memory index', entry];\n } else if (lines[0].startsWith('#')) {\n lines = [lines[0], entry, ...lines.slice(1)];\n } else {\n lines = [entry, ...lines];\n }\n writeIndexLines(dir, lines);\n return { entry, lineCount: lines.length };\n}\n\n/** Set frontmatter fields in place, leaving every other field, the headings and the body as they are. */\nfunction setFrontmatterFields(raw: string, fields: Record<string, string>): string {\n const match = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?/.exec(raw);\n const entries = Object.entries(fields);\n if (!match) {\n return `---\\n${entries.map(([k, v]) => `${k}: ${v}`).join('\\n')}\\n---\\n\\n${raw}`;\n }\n let frontmatter = match[1];\n for (const [key, value] of entries) {\n const line = new RegExp(`^${key}:.*$`, 'm');\n frontmatter = line.test(frontmatter)\n ? frontmatter.replace(line, `${key}: ${value}`)\n : `${frontmatter}\\n${key}: ${value}`;\n }\n return `---\\n${frontmatter}\\n---\\n${raw.slice(match[0].length)}`;\n}\n\n/**\n * Retire a memory another replaced: only its status, `supersededBy` and `updated` change, so the\n * file stays intact as history. Best effort, after the index already dropped its line — if the\n * rewrite fails, the file stays `approved` on disk, and the next index write prunes it anyway.\n */\nfunction markSuperseded(dir: string, oldFilename: string, byFilename: string, now: Date): void {\n try {\n const target = join(dir, oldFilename);\n if (isSymlink(target)) return;\n const raw = readFileSync(target, 'utf-8');\n writeFileAtomic(\n target,\n setFrontmatterFields(raw, {\n status: 'superseded',\n supersededBy: byFilename,\n updated: now.toISOString(),\n }),\n );\n } catch {\n // see above\n }\n}\n\n/**\n * Resolve a `supersedes` slug to the on-disk name of an active memory other than `own`. A name\n * that matches no file, or one already superseded, is an error the caller reports — never a\n * silent no-op that leaves two versions loading.\n */\nfunction resolveSupersedes(\n dir: string,\n raw: string | undefined,\n own: string | undefined,\n): { filename?: string } | { error: string } {\n if (!raw?.trim()) return {};\n const named = memoryFileForSlug(dir, raw);\n if ('error' in named) return { error: `supersedes: ${named.error}` };\n // The on-disk spelling: a case-insensitive file system finds `Deploy.md` for `deploy.md`,\n // and the index and frontmatter must name the file exactly as it is.\n let actual: string | undefined;\n try {\n actual = readdirSync(dir).find((f) => sameFile(f, named.filename));\n } catch {\n actual = undefined;\n }\n if (!actual || isSymlink(join(dir, actual))) {\n return {\n error: `supersedes: no memory file ${named.filename}. Use the file name from <memory-index>.`,\n };\n }\n if (own && sameFile(actual, own)) return {};\n const current = summarizeMemoryFile(join(dir, actual), actual);\n if (current?.status === 'superseded') {\n return {\n error: `supersedes: ${actual} is already superseded; supersede its replacement instead.`,\n };\n }\n return { filename: actual };\n}\n\n/** True for a symlink, dangling or not: `existsSync` follows links, `lstat` does not. */\nfunction isSymlink(path: string): boolean {\n try {\n return lstatSync(path).isSymbolicLink();\n } catch {\n return false;\n }\n}\n\n/**\n * Where an approved memory lands — the named slug's file, or a generated name — with the\n * original creation time when it updates an entry. Refuses a symlinked target, including a\n * dangling one, which `writeFileSync` would follow out of the memory directory.\n */\nfunction approvedTarget(\n dir: string,\n input: { type: MemoryType; title: string },\n slug: string | undefined,\n now: Date,\n): { filename: string; target: string; existingCreated?: string } | { error: string } {\n const named = slug?.trim() ? memoryFileForSlug(dir, slug) : null;\n if (named && 'error' in named) return { error: named.error };\n const filename = named?.filename ?? activeMemoryFilename(input as MemoryCandidate, now);\n const target = named?.target ?? join(dir, filename);\n if (isSymlink(target)) return { error: 'Refusing to overwrite symlinked memory file.' };\n const existingCreated = named && existsSync(target) ? readMemoryFile(target)?.created : undefined;\n return { filename, target, existingCreated };\n}\n\nexport function saveMemory(\n workspace: string,\n candidate: MemoryWriteInput,\n opts?: SaveMemoryOptions,\n): SaveMemoryResult {\n const quarantineExternal = opts?.quarantineExternal ?? true;\n const isQuarantined = candidate.externalContext === true && quarantineExternal;\n const requireApproval = (opts?.requireApproval ?? false) || isQuarantined;\n const title = sanitizeMemoryTitle(candidate.title);\n if (!title) {\n return {\n ok: false,\n error: 'title must not be empty after sanitizing.',\n status: requireApproval ? 'pending' : 'approved',\n quarantined: isQuarantined,\n };\n }\n\n if (requireApproval) {\n const rawSlug = opts?.slug?.trim()\n ? opts.slug\n : candidate.targetSlug?.trim()\n ? candidate.targetSlug\n : undefined;\n let targetSlug: string | undefined;\n if (rawSlug) {\n const named = memoryFileForSlug(getProjectMemoryDir(workspace, opts), rawSlug);\n if ('error' in named) {\n return { ok: false, error: named.error, status: 'pending', quarantined: isQuarantined };\n }\n targetSlug = named.filename;\n }\n // Resolved against the entry's own target; re-checked when the candidate is approved.\n const retire = resolveSupersedes(\n getProjectMemoryDir(workspace, opts),\n candidate.supersedes,\n targetSlug,\n );\n if ('error' in retire) {\n return { ok: false, error: retire.error, status: 'pending', quarantined: isQuarantined };\n }\n const candidateInput: MemoryWriteInput = {\n ...candidate,\n title,\n targetSlug,\n supersedes: retire.filename,\n };\n const writeResult = writeMemoryCandidate(workspace, candidateInput, opts);\n if (!writeResult.ok) {\n return { ok: false, error: writeResult.error, status: 'pending', quarantined: isQuarantined };\n }\n return { ok: true, path: writeResult.path, status: 'pending', quarantined: isQuarantined };\n }\n\n try {\n const now = opts?.now ?? new Date();\n const dir = getProjectMemoryDir(workspace, opts);\n mkdirSync(dir, { recursive: true });\n\n const placed = approvedTarget(dir, { ...candidate, title }, opts?.slug, now);\n if ('error' in placed) return { ok: false, error: placed.error, status: 'approved' };\n const { filename, target, existingCreated } = placed;\n // Against the real target, generated name included, so a save never retires itself.\n const retire = resolveSupersedes(dir, candidate.supersedes, filename);\n if ('error' in retire) return { ok: false, error: retire.error, status: 'approved' };\n // Fail before writing anything when the index cannot be read, rather than leave a memory\n // on disk that no index line will ever load.\n readIndexLines(dir);\n const memoryInput: MemoryWriteInput = {\n ...candidate,\n title,\n supersedes: retire.filename,\n created: existingCreated ?? candidate.created,\n };\n writeFileSync(target, renderMemoryMarkdown(memoryInput, 'approved', now), 'utf-8');\n const index = updateMemoryIndex(\n dir,\n title,\n filename,\n candidate.type,\n now,\n candidate.body,\n memoryInput.supersedes,\n );\n if (memoryInput.supersedes) markSuperseded(dir, memoryInput.supersedes, filename, now);\n return {\n ok: true,\n path: target,\n indexLine: index.entry,\n indexLineCount: index.lineCount,\n retired: memoryInput.supersedes,\n status: 'approved',\n };\n } catch (e) {\n return { ok: false, error: e instanceof Error ? e.message : String(e), status: 'approved' };\n }\n}\n\n/**\n * Who wrote an existing memory entry: `agent` for a delegated run's, `human` for any other, and\n * null when there is no such entry. A delegated run may change only its own kind of entry.\n */\nexport function memoryEntryDriver(\n workspace: string,\n slug: string,\n opts?: MemoryStoreOptions,\n): SessionDriver | null {\n const named = memoryFileForSlug(getProjectMemoryDir(workspace, opts), slug);\n if ('error' in named || !existsSync(named.target)) return null;\n return readMemoryFile(named.target)?.driver === 'agent' ? 'agent' : 'human';\n}\n\nexport function deleteMemoryEntry(\n workspace: string,\n slug: string,\n opts?: MemoryStoreOptions,\n): { ok: boolean; path?: string; error?: string } {\n try {\n const dir = getProjectMemoryDir(workspace, opts);\n const named = memoryFileForSlug(dir, slug);\n if ('error' in named) return { ok: false, error: named.error };\n const { filename, target } = named;\n if (!existsSync(target)) {\n return { ok: false, error: `Memory file not found: ${filename}` };\n }\n if (lstatSync(target).isSymbolicLink()) {\n return { ok: false, error: 'Refusing to delete symlinked file.' };\n }\n\n unlinkSync(target);\n try {\n removeIndexEntry(dir, filename);\n } catch {\n // The file is gone either way; a stale index line points at nothing and is dropped by the\n // next index write.\n }\n return { ok: true, path: target };\n } catch (e) {\n return { ok: false, error: e instanceof Error ? e.message : String(e) };\n }\n}\n\nexport function approveMemoryCandidate(\n workspace: string,\n candidateFile: string,\n opts?: MemoryStoreOptions,\n): MemoryWriteResult {\n try {\n const candidatePath = resolveCandidatePath(workspace, candidateFile, opts);\n if (!candidatePath)\n return { ok: false, error: 'Candidate path must stay inside the memory inbox.' };\n if (!existsSync(candidatePath))\n return { ok: false, error: `Candidate not found: ${candidateFile}` };\n if (lstatSync(candidatePath).isSymbolicLink())\n return { ok: false, error: 'Refusing to approve symlinked candidate.' };\n\n const candidate = parseCandidateFile(candidatePath);\n if (!candidate)\n return { ok: false, error: 'Candidate has invalid or missing memory frontmatter.' };\n\n const now = opts?.now ?? new Date();\n const dir = getProjectMemoryDir(workspace, opts);\n mkdirSync(dir, { recursive: true });\n\n if (!candidate.title.trim()) return { ok: false, error: 'Candidate has an empty title.' };\n const placed = approvedTarget(dir, candidate, candidate.targetSlug, now);\n if ('error' in placed) return { ok: false, error: placed.error };\n const { filename, target, existingCreated } = placed;\n\n // A candidate's `supersedes` was resolved when it was saved; re-check it now, since the\n // target may have gone or be the entry being approved.\n const retire = resolveSupersedes(dir, candidate.supersedes, filename);\n const supersedes = 'error' in retire ? undefined : retire.filename;\n const retireSkipped = 'error' in retire ? retire.error : undefined;\n const memoryInput: MemoryWriteInput = {\n ...candidate,\n supersedes,\n created: existingCreated ?? candidate.created,\n };\n const rendered = renderMemoryMarkdown(memoryInput, 'approved', now);\n // Move the candidate to discarded BEFORE writing the approved file and\n // updating the index, so a rename failure cannot leave an orphan approved\n // memory + index entry behind on disk. If the rename throws, nothing has\n // been committed yet and the caller can safely retry.\n // An unreadable index fails the approval here, while the candidate is still in the inbox.\n readIndexLines(dir);\n renameSync(candidatePath, join(getDiscardedDir(workspace, opts), basename(candidatePath)));\n writeFileSync(target, rendered, 'utf-8');\n updateMemoryIndex(\n dir,\n candidate.title,\n filename,\n candidate.type,\n now,\n candidate.body,\n supersedes,\n );\n if (supersedes) markSuperseded(dir, supersedes, filename, now);\n return { ok: true, path: target, retired: supersedes, retireSkipped };\n } catch (e) {\n return { ok: false, error: e instanceof Error ? e.message : String(e) };\n }\n}\n\nfunction getDiscardedDir(workspace: string, opts?: MemoryStoreOptions): string {\n const dir = join(getMemoryInboxDir(workspace, opts), DISCARDED_DIR);\n mkdirSync(dir, { recursive: true });\n return dir;\n}\n\nexport function discardMemoryCandidate(\n workspace: string,\n candidateFile: string,\n opts?: MemoryStoreOptions,\n): MemoryWriteResult {\n try {\n const candidatePath = resolveCandidatePath(workspace, candidateFile, opts);\n if (!candidatePath)\n return { ok: false, error: 'Candidate path must stay inside the memory inbox.' };\n if (!existsSync(candidatePath))\n return { ok: false, error: `Candidate not found: ${candidateFile}` };\n if (lstatSync(candidatePath).isSymbolicLink())\n return { ok: false, error: 'Refusing to discard symlinked candidate.' };\n const discardedPath = join(getDiscardedDir(workspace, opts), basename(candidatePath));\n renameSync(candidatePath, discardedPath);\n return { ok: true, path: discardedPath };\n } catch (e) {\n return { ok: false, error: e instanceof Error ? e.message : String(e) };\n }\n}\n","/**\n * Shared secret / high-entropy text detector.\n *\n * Used by the memory auto-capture path to avoid persisting secrets as memory\n * candidates. Intended to be reused by future log redactors and tool-output\n * scrubbers so the pattern list lives in one place.\n */\n\nexport const SECRET_PATTERNS = [\n /-----BEGIN [A-Z ]*PRIVATE KEY-----/i,\n /\\b(api[_-]?key|token|password|passwd|secret)\\s*[:=]\\s*\\S{8,}/i,\n /https?:\\/\\/[^\\s/]+:[^\\s/]+@/i,\n /\\bgh[pousr]_[A-Za-z0-9_]{20,}\\b/,\n /\\bsk-[A-Za-z0-9_-]{20,}\\b/,\n];\n\n/**\n * Whether `text` contains an explicit credential shape (a private key, an\n * `api_key=`/`token=` assignment, basic-auth in a URL, a GitHub or `sk-` token).\n * Unlike `looksLikeSecretOrUnfit` this does not apply the high-entropy rule,\n * which is sized for a sentence and flags any run of text that names a long\n * path -- the wrong test for a whole user turn.\n */\nexport function containsSecretPattern(text: string): boolean {\n return SECRET_PATTERNS.some((re) => re.test(text));\n}\n\n/**\n * Returns a short reason string when `text` looks like a secret or is\n * otherwise unfit to persist, or `null` when the text is acceptable.\n */\nexport function looksLikeSecretOrUnfit(text: string): string | null {\n const trimmed = text.trim();\n if (trimmed.length === 0) return 'empty';\n if (SECRET_PATTERNS.some((re) => re.test(trimmed))) return 'looks like a secret';\n const longTokens = trimmed.match(/[A-Za-z0-9+/=_-]{48,}/g) ?? [];\n if (longTokens.some((token) => new Set(token).size > 20)) return 'contains high-entropy text';\n return null;\n}\n"],"mappings":"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","names":[]}