@letrquan/book 0.2.0 → 0.4.0-beta.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.
- package/CHANGELOG.md +3771 -40
- package/README.md +135 -1311
- package/dist/additional-roots-VAWRQ625.js +32 -0
- package/dist/{app-MOXXWEOY.js → app-J7BVPSUH.js} +9648 -5509
- package/dist/app-J7BVPSUH.js.map +1 -0
- package/dist/chunk-2AAOF5B5.js +28 -0
- package/dist/chunk-2AAOF5B5.js.map +1 -0
- package/dist/chunk-32WBCUAN.js +660 -0
- package/dist/chunk-32WBCUAN.js.map +1 -0
- package/dist/chunk-4DKHLZRI.js +120 -0
- package/dist/chunk-4DKHLZRI.js.map +1 -0
- package/dist/{chunk-CAGOB2N4.js → chunk-62EEAUID.js} +6 -4
- package/dist/chunk-62EEAUID.js.map +1 -0
- package/dist/chunk-AHC7OU75.js +1124 -0
- package/dist/chunk-AHC7OU75.js.map +1 -0
- package/dist/{chunk-E75IPST5.js → chunk-AJZWLKLQ.js} +73 -70
- package/dist/chunk-AJZWLKLQ.js.map +1 -0
- package/dist/chunk-B5FC3MYZ.js +395 -0
- package/dist/chunk-B5FC3MYZ.js.map +1 -0
- package/dist/{chunk-KWHQ2XXL.js → chunk-DNFQTSMJ.js} +55 -13
- package/dist/chunk-DNFQTSMJ.js.map +1 -0
- package/dist/{chunk-J7MIZ5CA.js → chunk-E5WLQSKA.js} +719 -89
- package/dist/chunk-E5WLQSKA.js.map +1 -0
- package/dist/chunk-ECLC4CIJ.js +1181 -0
- package/dist/chunk-ECLC4CIJ.js.map +1 -0
- package/dist/chunk-EEX6QNXV.js +127 -0
- package/dist/chunk-EEX6QNXV.js.map +1 -0
- package/dist/chunk-EFXVSQ5J.js +931 -0
- package/dist/chunk-EFXVSQ5J.js.map +1 -0
- package/dist/{chunk-V4BOYR52.js → chunk-ENLB7NYV.js} +1304 -326
- package/dist/chunk-ENLB7NYV.js.map +1 -0
- package/dist/chunk-FPR7SKIE.js +6926 -0
- package/dist/chunk-FPR7SKIE.js.map +1 -0
- package/dist/{chunk-DGMQEI6Y.js → chunk-HFB74CLM.js} +30 -9
- package/dist/chunk-HFB74CLM.js.map +1 -0
- package/dist/{chunk-5RDRAO4B.js → chunk-HOZXKOE3.js} +37 -1
- package/dist/chunk-HOZXKOE3.js.map +1 -0
- package/dist/chunk-IDYWN37T.js +36 -0
- package/dist/chunk-IDYWN37T.js.map +1 -0
- package/dist/chunk-J4F2QLM2.js +273 -0
- package/dist/chunk-J4F2QLM2.js.map +1 -0
- package/dist/chunk-JGF5HLSI.js +1065 -0
- package/dist/chunk-JGF5HLSI.js.map +1 -0
- package/dist/{chunk-XIFFTATU.js → chunk-KDNWMKXV.js} +7166 -4237
- package/dist/chunk-KDNWMKXV.js.map +1 -0
- package/dist/chunk-KXAYUIKP.js +90 -0
- package/dist/chunk-KXAYUIKP.js.map +1 -0
- package/dist/{chunk-3U5IBM24.js → chunk-MEOB2DZA.js} +12 -2
- package/dist/chunk-MEOB2DZA.js.map +1 -0
- package/dist/{chunk-WKBO5R4O.js → chunk-MV5PQNIA.js} +2 -2
- package/dist/chunk-MV5PQNIA.js.map +1 -0
- package/dist/chunk-N2G4Q7ME.js +2672 -0
- package/dist/chunk-N2G4Q7ME.js.map +1 -0
- package/dist/chunk-OJBMDM5H.js +299 -0
- package/dist/chunk-OJBMDM5H.js.map +1 -0
- package/dist/{chunk-URLQAXTR.js → chunk-PTDC7ZUP.js} +2 -2
- package/dist/chunk-PTDC7ZUP.js.map +1 -0
- package/dist/{chunk-574C6MQR.js → chunk-REASC2QG.js} +173 -64
- package/dist/chunk-REASC2QG.js.map +1 -0
- package/dist/{chunk-7N4J557C.js → chunk-RT5SATF7.js} +1 -1
- package/dist/chunk-RT5SATF7.js.map +1 -0
- package/dist/chunk-SBTU5BEC.js +114 -0
- package/dist/chunk-SBTU5BEC.js.map +1 -0
- package/dist/{chunk-5KLVH3PY.js → chunk-SWPDKLNM.js} +5 -3
- package/dist/chunk-SWPDKLNM.js.map +1 -0
- package/dist/chunk-UCFJ43OS.js +520 -0
- package/dist/chunk-UCFJ43OS.js.map +1 -0
- package/dist/{chunk-VZQXX3WW.js → chunk-W7SLYS3M.js} +80 -16
- package/dist/chunk-W7SLYS3M.js.map +1 -0
- package/dist/{chunk-ANSJPYGI.js → chunk-WV3O5PGX.js} +3 -3
- package/dist/chunk-WV3O5PGX.js.map +1 -0
- package/dist/chunk-XHAO3K7I.js +18 -0
- package/dist/chunk-XHAO3K7I.js.map +1 -0
- package/dist/chunk-XJRJVXJR.js +1050 -0
- package/dist/chunk-XJRJVXJR.js.map +1 -0
- package/dist/chunk-YIL6HTJX.js +663 -0
- package/dist/chunk-YIL6HTJX.js.map +1 -0
- package/dist/{chunk-24AXE6SP.js → chunk-ZPSZZUWF.js} +1 -1
- package/dist/chunk-ZPSZZUWF.js.map +1 -0
- package/dist/{command-approvals-6Y57VCWZ.js → command-approvals-ZRY66LCW.js} +7 -5
- package/dist/context-C3RAP6K5.js +41 -0
- package/dist/{hook-approvals-CTUFKEJT.js → hook-approvals-DPQD5H65.js} +6 -5
- package/dist/index.js +947 -203
- package/dist/index.js.map +1 -1
- package/dist/{interactive-assets-CCAAWVKH.js → interactive-assets-73AQO5WP.js} +18 -9
- package/dist/interactive-assets-73AQO5WP.js.map +1 -0
- package/dist/job-runner.js +166 -111
- package/dist/job-runner.js.map +1 -1
- package/dist/job-supervisor.d.ts +2 -0
- package/dist/job-supervisor.js +121 -0
- package/dist/job-supervisor.js.map +1 -0
- package/dist/loader-DQNPDKOX.js +27 -0
- package/dist/{mcp-approvals-WNPH65BK.js → mcp-approvals-27LJYADQ.js} +6 -5
- package/dist/{mcp-config-YIJIES2C.js → mcp-config-GXSODNCM.js} +4 -3
- package/dist/memory-store-I6Z54VUN.js +51 -0
- package/dist/{model-window-store-YFVNXCIP.js → model-window-store-6VKXXTPJ.js} +9 -4
- package/dist/openai-compatible-IPUNBJ53.js +16 -0
- package/dist/permission-approvals-Q5IMFEZI.js +15 -0
- package/dist/permissions-7Y35X6HZ.js +62 -0
- package/dist/provider-approvals-5AGH3RVT.js +76 -0
- package/dist/sandbox-N2RY72GN.js +42 -0
- package/dist/{scrollback-LUKLIBVI.js → scrollback-GD76GNM4.js} +44 -26
- package/dist/scrollback-GD76GNM4.js.map +1 -0
- package/dist/sdk.d.ts +2739 -2069
- package/dist/sdk.js +77 -42
- package/dist/sdk.js.map +1 -1
- package/dist/settings-loader-KDBH45AQ.js +43 -0
- package/dist/settings-loader-KDBH45AQ.js.map +1 -0
- package/dist/{settings-removed-JWWPT4WA.js → settings-removed-3ATWJEF3.js} +2 -2
- package/dist/settings-removed-3ATWJEF3.js.map +1 -0
- package/dist/shell-selection-Z5WORZU4.js +31 -0
- package/dist/shell-selection-Z5WORZU4.js.map +1 -0
- package/package.json +25 -24
- package/dist/app-MOXXWEOY.js.map +0 -1
- package/dist/chunk-24AXE6SP.js.map +0 -1
- package/dist/chunk-3U5IBM24.js.map +0 -1
- package/dist/chunk-574C6MQR.js.map +0 -1
- package/dist/chunk-5GDZ22YP.js +0 -449
- package/dist/chunk-5GDZ22YP.js.map +0 -1
- package/dist/chunk-5KLVH3PY.js.map +0 -1
- package/dist/chunk-5RDRAO4B.js.map +0 -1
- package/dist/chunk-7N4J557C.js.map +0 -1
- package/dist/chunk-A7JLBK2Y.js +0 -3506
- package/dist/chunk-A7JLBK2Y.js.map +0 -1
- package/dist/chunk-ANSJPYGI.js.map +0 -1
- package/dist/chunk-BTZZUCLI.js +0 -264
- package/dist/chunk-BTZZUCLI.js.map +0 -1
- package/dist/chunk-C7D4NJ2D.js +0 -217
- package/dist/chunk-C7D4NJ2D.js.map +0 -1
- package/dist/chunk-CAGOB2N4.js.map +0 -1
- package/dist/chunk-DGMQEI6Y.js.map +0 -1
- package/dist/chunk-E75IPST5.js.map +0 -1
- package/dist/chunk-EYGD6X2T.js +0 -180
- package/dist/chunk-EYGD6X2T.js.map +0 -1
- package/dist/chunk-GTVB4HEM.js +0 -765
- package/dist/chunk-GTVB4HEM.js.map +0 -1
- package/dist/chunk-J7MIZ5CA.js.map +0 -1
- package/dist/chunk-KWHQ2XXL.js.map +0 -1
- package/dist/chunk-L6LK2QIQ.js +0 -657
- package/dist/chunk-L6LK2QIQ.js.map +0 -1
- package/dist/chunk-MAQXCUR4.js +0 -1007
- package/dist/chunk-MAQXCUR4.js.map +0 -1
- package/dist/chunk-S4XL7HOM.js +0 -402
- package/dist/chunk-S4XL7HOM.js.map +0 -1
- package/dist/chunk-URLQAXTR.js.map +0 -1
- package/dist/chunk-V4BOYR52.js.map +0 -1
- package/dist/chunk-VZQXX3WW.js.map +0 -1
- package/dist/chunk-WKBO5R4O.js.map +0 -1
- package/dist/chunk-XIFFTATU.js.map +0 -1
- package/dist/context-ZC5IFEAX.js +0 -25
- package/dist/interactive-assets-CCAAWVKH.js.map +0 -1
- package/dist/loader-4IDS2RIE.js +0 -15
- package/dist/openai-compatible-RHZUBHV6.js +0 -10
- package/dist/permission-approvals-76PVREFD.js +0 -14
- package/dist/permissions-CHCKTFQQ.js +0 -28
- package/dist/sandbox-CNVAQDA7.js +0 -23
- package/dist/scrollback-LUKLIBVI.js.map +0 -1
- package/dist/settings-loader-M2QP5TX2.js +0 -21
- package/dist/shell-selection-V6QAYXPX.js +0 -17
- package/patches/ink+6.8.0.patch +0 -13
- package/scripts/apply-ink-patch.mjs +0 -29
- package/scripts/ink-patch.mjs +0 -59
- package/scripts/verify-ink-patch.mjs +0 -11
- /package/dist/{command-approvals-6Y57VCWZ.js.map → additional-roots-VAWRQ625.js.map} +0 -0
- /package/dist/{context-ZC5IFEAX.js.map → command-approvals-ZRY66LCW.js.map} +0 -0
- /package/dist/{hook-approvals-CTUFKEJT.js.map → context-C3RAP6K5.js.map} +0 -0
- /package/dist/{loader-4IDS2RIE.js.map → hook-approvals-DPQD5H65.js.map} +0 -0
- /package/dist/{mcp-approvals-WNPH65BK.js.map → loader-DQNPDKOX.js.map} +0 -0
- /package/dist/{mcp-config-YIJIES2C.js.map → mcp-approvals-27LJYADQ.js.map} +0 -0
- /package/dist/{model-window-store-YFVNXCIP.js.map → mcp-config-GXSODNCM.js.map} +0 -0
- /package/dist/{openai-compatible-RHZUBHV6.js.map → memory-store-I6Z54VUN.js.map} +0 -0
- /package/dist/{permission-approvals-76PVREFD.js.map → model-window-store-6VKXXTPJ.js.map} +0 -0
- /package/dist/{permissions-CHCKTFQQ.js.map → openai-compatible-IPUNBJ53.js.map} +0 -0
- /package/dist/{sandbox-CNVAQDA7.js.map → permission-approvals-Q5IMFEZI.js.map} +0 -0
- /package/dist/{settings-loader-M2QP5TX2.js.map → permissions-7Y35X6HZ.js.map} +0 -0
- /package/dist/{settings-removed-JWWPT4WA.js.map → provider-approvals-5AGH3RVT.js.map} +0 -0
- /package/dist/{shell-selection-V6QAYXPX.js.map → sandbox-N2RY72GN.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/memory-store.ts","../src/memory-limits.ts"],"sourcesContent":["import {\n closeSync,\n constants,\n copyFileSync,\n existsSync,\n fstatSync,\n linkSync,\n lstatSync,\n mkdirSync,\n openSync,\n readdirSync,\n readFileSync,\n readSync,\n realpathSync,\n renameSync,\n rmdirSync,\n rmSync,\n statSync,\n unlinkSync,\n type Stats,\n} from 'fs';\nimport { basename, dirname, isAbsolute, join, relative, resolve } from 'path';\nimport { createDebugLogger } from './debug-log.js';\nimport { parseFrontmatter } from './frontmatter.js';\nimport { writeFileAtomic } from './settings-repository.js';\nimport { resolveBookHome } from './book-home.js';\nimport { DEFAULT_MAX_INDEX_LINES, MAX_INDEX_BYTES } from './memory-limits.js';\nimport { isUserHome, tryRealPath } from './repo-containment.js';\nimport { createUncGuard, type UncGuard } from './unc-path.js';\nimport type { SessionDriver } from './types/runtime.js';\n\nconst MEMORY_TYPES = ['user', 'feedback', 'project', 'reference'] as const;\ntype MemoryType = (typeof MEMORY_TYPES)[number];\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`. Used by\n * `/memory delete`, which passes raw user input and gets back a resolved filename,\n * 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/**\n * What the model may write to memory in this session — the one rule the prompt, the guard and\n * `/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 `project` and `reference` memories, marked\n * `driver: agent`, and only delegated files 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 const memory = config.settings?.memory;\n if (memory && (memory.enabled === false || memory.autoSave === false)) return 'none';\n return config.sessionDriver === 'agent' ? 'learnings' : 'full';\n}\n\nexport interface MemoryFileSummary {\n name: string;\n path: string;\n type?: MemoryType;\n title?: string;\n /** The frontmatter `description`: what the memory is for, in a line. */\n description?: string;\n size: number;\n driver?: SessionDriver;\n /**\n * The file still carries the retired `status: superseded` frontmatter of the old save tool. It\n * is no longer retired by anything, so it loads like any other file; `/memory status` lists it\n * as legacy.\n */\n legacySuperseded?: boolean;\n}\n\nexport interface LoadedMemoryContext {\n dir: string;\n indexFile: string | null;\n indexLoaded: boolean;\n /** Non-empty lines in MEMORY.md (the whole file, not only what loaded). */\n indexLineCount: number;\n /** Non-empty lines that loaded, the cut marker excluded. */\n loadedLineCount: number;\n /** UTF-8 size of the trimmed MEMORY.md. */\n indexByteCount: number;\n /** The index was cut at the line limit. */\n wasLineTruncated: boolean;\n /** The index was cut at the byte limit. */\n wasByteTruncated: boolean;\n /** The loaded index; ends with a warning marker when it was cut. */\n indexText: string;\n files: MemoryFileSummary[];\n}\n\nexport interface MemoryStoreOptions {\n bookRoot?: string;\n maxIndexLines?: number;\n}\n\nexport { DEFAULT_MAX_INDEX_LINES, MAX_INDEX_BYTES };\nconst INDEX_FILE = 'MEMORY.md';\n// Only the move from the old cwd-keyed directory still knows these: an existing inbox is carried\n// over untouched, and left for the migration to back up.\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\nconst log = createDebugLogger('memory-store');\n\nfunction errorCode(error: unknown): string | undefined {\n return typeof error === 'object' && error !== null && 'code' in error\n ? String((error as { code: unknown }).code)\n : undefined;\n}\n\n/** The file-system path as the walk and the key see it: absolute, links followed when it exists. */\nfunction canonicalPath(path: string): string {\n const absolute = resolve(path);\n try {\n return realpathSync(absolute);\n } catch {\n return absolute;\n }\n}\n\n/** `lstat` without following links; null when the path is absent. Other errors throw. */\nfunction lstatIfPresent(path: string): Stats | null {\n try {\n return lstatSync(path);\n } catch (e) {\n if (errorCode(e) === 'ENOENT' || errorCode(e) === 'ENOTDIR') return null;\n throw e;\n }\n}\n\nfunction statIfPresent(path: string): Stats | null {\n try {\n return statSync(path);\n } catch (e) {\n if (errorCode(e) === 'ENOENT' || errorCode(e) === 'ENOTDIR') return null;\n throw e;\n }\n}\n\n/** Git's pointer files (`.git`, `commondir`, `gitdir`) hold one path; a bigger file is none. */\nconst MAX_POINTER_FILE_BYTES = 64 * 1024;\n\n/**\n * The first line of the git pointer file `path`, trimmed; undefined when it is absent or no\n * regular file. A checkout from an archive controls these files, so the read never blocks or\n * runs on: it opens without blocking (a FIFO, even one swapped in late), checks the open file,\n * and reads at most one byte past the limit (a procfs file reports size 0 and never ends).\n * Throws on one it cannot read or that is too big. Undefined, unopened, for one that is, or\n * reaches through a link, a UNC location on Windows (`reachesUnc`, #579).\n */\nfunction readPointerFile(path: string, reachesUnc: UncGuard): string | undefined {\n if (reachesUnc(path)) return undefined;\n let fd: number;\n try {\n fd = openSync(path, constants.O_RDONLY | (constants.O_NONBLOCK ?? 0));\n } catch (e) {\n const code = errorCode(e);\n if (code === 'ENOENT' || code === 'ENOTDIR' || code === 'EISDIR') return undefined;\n throw e;\n }\n try {\n if (!fstatSync(fd).isFile()) return undefined;\n const buffer = Buffer.alloc(MAX_POINTER_FILE_BYTES + 1);\n let length = 0;\n while (length < buffer.length) {\n const n = readSync(fd, buffer, length, buffer.length - length, null);\n if (n === 0) break;\n length += n;\n }\n if (length > MAX_POINTER_FILE_BYTES) throw new Error(`not a git pointer file: ${path}`);\n return buffer.toString('utf-8', 0, length).split(/\\r?\\n/, 1)[0].trim();\n } finally {\n closeSync(fd);\n }\n}\n\n/**\n * The git root `dir` itself marks with a `.git` entry; undefined when `dir` has none. Throws on a\n * `.git` it cannot read, and on one that is, or reaches through a link, a UNC location on Windows,\n * which is not opened (#579). A git dir or common dir there is not opened either: `dir` is then\n * its own root, as a checkout with no common dir is.\n */\nfunction gitRootMarkedBy(dir: string, reachesUnc: UncGuard): string | undefined {\n const dotGit = join(dir, '.git');\n if (reachesUnc(dotGit)) throw new Error(`.git on a UNC path: ${dotGit}`);\n const st = statIfPresent(dotGit);\n if (!st) return undefined;\n if (st.isDirectory()) return dir;\n if (!st.isFile()) return undefined;\n\n const pointer = /^gitdir:[ \\t]*(\\S.*)$/.exec(readPointerFile(dotGit, reachesUnc) ?? '');\n if (!pointer) throw new Error(`unrecognized .git file: ${dotGit}`);\n // A relative gitdir resolves against the directory holding the `.git` file.\n const gitDir = resolve(dir, pointer[1]);\n if (reachesUnc(gitDir)) return dir;\n const commonDir = readPointerFile(join(gitDir, 'commondir'), reachesUnc);\n // A submodule or `--separate-git-dir` checkout has no commondir: it is its own root.\n if (commonDir === undefined) return dir;\n const commonPath = resolve(gitDir, commonDir);\n if (reachesUnc(commonPath)) return dir;\n const common = canonicalPath(commonPath);\n // A linked worktree's common dir is the main checkout's `.git`, which lists the worktree back.\n return basename(common) === '.git' && isListedWorktree(dir, gitDir, common, reachesUnc)\n ? dirname(common)\n : dir;\n}\n\n/**\n * The real path to compare, links followed and Windows 8.3 short names expanded as git writes\n * them. Only for comparing: the key itself stays `canonicalPath`'s, so no stored key changes.\n */\nfunction comparablePath(path: string): string {\n return tryRealPath(path) ?? resolve(path);\n}\n\n/** Whether `a` and `b` name one path; `relative`, so case folds where the platform's paths do (Windows). */\nfunction samePath(a: string, b: string): boolean {\n return relative(comparablePath(a), comparablePath(b)) === '';\n}\n\n/**\n * Whether the repository at `common` lists `dir` as one of its linked worktrees, git's own round\n * trip: the git dir `dir/.git` names must be an entry `<common>/worktrees/<name>`, and that entry's\n * `gitdir` file must name `dir/.git` back. Without it a `.git` file anywhere (an archive, a shared\n * directory) could name another project's `.git`, the home directory's included, and take that\n * project's memory (#575). A worktree moved without `git worktree move` fails it until\n * `git worktree repair` relinks it.\n *\n * Stricter than git's own pointers: `dir/.git` and the entry's `gitdir` must have one owner, as\n * every `git worktree add`, `move` and `repair` writes both. Another user's `.git` planted where a\n * removed worktree's still-listed path was (a shared directory, `/tmp`) fails it. Windows reports\n * uid 0 for every file, so there the owners always match.\n */\nfunction isListedWorktree(\n dir: string,\n gitDir: string,\n common: string,\n reachesUnc: UncGuard,\n): boolean {\n const entry = comparablePath(gitDir);\n if (!samePath(dirname(entry), join(common, 'worktrees'))) return false;\n const listing = join(entry, 'gitdir');\n try {\n const backPointer = readPointerFile(listing, reachesUnc);\n if (!backPointer) return false;\n // A relative back-pointer (`worktree.useRelativePaths`) resolves against the entry.\n const target = resolve(entry, backPointer);\n // The directories are compared, not the `.git` entries: a `.git` link in another directory to\n // a real worktree's `.git` file makes that directory no worktree.\n if (basename(target) !== '.git' || !samePath(dirname(target), dir)) return false;\n return lstatSync(join(dir, '.git')).uid === statSync(listing).uid;\n } catch {\n // An entry it cannot read lists nothing, so every subdirectory keys by this checkout alike.\n return false;\n }\n}\n\n/**\n * The directory memory is keyed by: the git repository root the workspace belongs to, so every\n * subdirectory and every linked worktree of one repository shares one memory. Only reads files\n * (never spawns git). Falls back to the resolved workspace when there is no repository, or when\n * the walk meets anything it cannot read.\n *\n * A `.git` file maps to the main checkout only for a linked worktree the main checkout lists\n * back (`isListedWorktree`); any other is its own root.\n *\n * A `.git` at the user's home directory is a dotfiles repository, not a project\n * (`findRepositoryRoot` in `repo-containment.ts`): the walk stops there with no repository, so\n * each project under the home directory without its own `.git` keeps its own memory instead of\n * sharing the home directory's. Memory already stored under the home directory's key stays\n * there.\n */\nexport function findGitRoot(workspace: string): string {\n // A workspace that is, or reaches through a link, a UNC location on Windows is neither resolved\n // nor walked up (#579): it is its own key, as written. One guard serves the whole walk up.\n const reachesUnc = createUncGuard();\n if (reachesUnc(workspace)) return resolve(workspace);\n const resolved = canonicalPath(workspace);\n try {\n for (let dir = resolved; ;) {\n const root = gitRootMarkedBy(dir, reachesUnc);\n if (root !== undefined) {\n return isUserHome(tryRealPath(dir) ?? dir, undefined) ? resolved : root;\n }\n const parent = dirname(dir);\n if (parent === dir) return resolved;\n dir = parent;\n }\n } catch {\n return resolved;\n }\n}\n\nfunction memoryDirIn(root: string, workspaceKey: string): string {\n return join(root, 'projects', slugifyWorkspace(workspaceKey), 'memory');\n}\n\nexport function getProjectMemoryDir(workspace: string, opts?: MemoryStoreOptions): string {\n return memoryDirIn(bookRoot(opts), findGitRoot(workspace));\n}\n\n/** Link `src` to `dst` without replacing `dst`, then drop `src`. A race lost to another process is not an error. */\nfunction moveFileNoClobber(src: string, dst: string): 'moved' | 'exists' | 'gone' {\n try {\n linkSync(src, dst);\n } catch (e) {\n if (errorCode(e) === 'EEXIST') return 'exists';\n if (errorCode(e) === 'ENOENT' && !lstatIfPresent(src)) return 'gone';\n // Hard links unsupported here (EPERM, EXDEV, ...): copy exclusively instead.\n try {\n copyFileSync(src, dst, constants.COPYFILE_EXCL);\n } catch (copyError) {\n if (errorCode(copyError) === 'EEXIST') return 'exists';\n if (errorCode(copyError) === 'ENOENT' && !lstatIfPresent(src)) return 'gone';\n throw copyError;\n }\n }\n try {\n unlinkSync(src);\n } catch (e) {\n if (errorCode(e) !== 'ENOENT') throw e;\n }\n return 'moved';\n}\n\n/** Move `dir/name` into `target`, suffixing `-2`, `-3`, … before `.md` on a collision. Returns the final name, or null when the source vanished. */\nfunction moveKeepingBoth(sourceDir: string, targetDir: string, name: string): string | null {\n const stem = name.slice(0, -'.md'.length);\n for (let n = 1; n <= 1000; n++) {\n const candidate = n === 1 ? name : `${stem}-${n}.md`;\n const outcome = moveFileNoClobber(join(sourceDir, name), join(targetDir, candidate));\n if (outcome === 'moved') return candidate;\n if (outcome === 'gone') return null;\n }\n throw new Error(`too many name collisions moving ${name}`);\n}\n\n/** True when `path` is a real directory (created when absent); a symlink or file there is never followed. */\nfunction ensureRealDir(path: string): boolean {\n const st = lstatIfPresent(path);\n if (!st) {\n mkdirSync(path, { recursive: true });\n return true;\n }\n return st.isDirectory();\n}\n\nfunction isMemoryTopicFile(name: string): boolean {\n const lower = name.toLowerCase();\n return lower.endsWith('.md') && lower !== INDEX_FILE.toLowerCase();\n}\n\n/** The regular `*.md` files directly in `dir` (symlinks excluded). */\nfunction regularMarkdownFiles(dir: string, accept: (name: string) => boolean): string[] {\n const st = lstatIfPresent(dir);\n if (!st?.isDirectory()) return [];\n return readdirSync(dir, { withFileTypes: true })\n .filter((entry) => entry.isFile() && accept(entry.name))\n .map((entry) => entry.name)\n .sort();\n}\n\n/** Move the old index's entry lines into the new index, right after its header. */\nfunction mergeLegacyIndex(oldDir: string, newDir: string, renamed: Map<string, string>): void {\n const oldIndex = join(oldDir, INDEX_FILE);\n if (!lstatIfPresent(oldIndex)?.isFile()) return;\n const newIndexStat = lstatIfPresent(join(newDir, INDEX_FILE));\n if (newIndexStat && !newIndexStat.isFile()) return;\n\n let oldText: string;\n try {\n oldText = readFileSync(oldIndex, 'utf-8');\n } catch (e) {\n if (errorCode(e) === 'ENOENT') return; // another process merged it\n throw e;\n }\n const lines = readIndexLines(newDir);\n const listed = new Set<string>();\n for (const line of lines) {\n const file = indexEntryFile(line);\n if (file) listed.add(file.toLowerCase());\n }\n const additions: string[] = [];\n for (const line of oldText.split('\\n')) {\n const file = indexEntryFile(line);\n if (!file) continue;\n const target = renamed.get(file) ?? file;\n if (listed.has(target.toLowerCase())) continue;\n listed.add(target.toLowerCase());\n additions.push(target === file ? line : line.replace(`](${file})`, `](${target})`));\n }\n if (additions.length > 0) {\n const merged =\n lines.length === 0\n ? ['# Book memory index', ...additions]\n : lines[0].startsWith('#')\n ? [lines[0], ...additions, ...lines.slice(1)]\n : [...additions, ...lines];\n writeIndexLines(newDir, merged);\n }\n try {\n unlinkSync(oldIndex);\n } catch (e) {\n if (errorCode(e) !== 'ENOENT') throw e;\n }\n}\n\nfunction mergeLegacyMemoryDir(oldDir: string, newDir: string): void {\n const renamed = new Map<string, string>();\n for (const name of regularMarkdownFiles(oldDir, isMemoryTopicFile)) {\n const final = moveKeepingBoth(oldDir, newDir, name);\n if (final && final !== name) renamed.set(name, final);\n }\n for (const sub of [INBOX_DIR, join(INBOX_DIR, DISCARDED_DIR)]) {\n const files = regularMarkdownFiles(join(oldDir, sub), (name) =>\n name.toLowerCase().endsWith('.md'),\n );\n if (files.length === 0) continue;\n // `.inbox` and `.inbox/discarded` are checked one by one: neither may be a link.\n const targetDir = join(newDir, sub);\n if (!ensureRealDir(join(newDir, INBOX_DIR)) || !ensureRealDir(targetDir)) continue;\n for (const name of files) moveKeepingBoth(join(oldDir, sub), targetDir, name);\n }\n mergeLegacyIndex(oldDir, newDir, renamed);\n // Best effort: only an empty directory goes. The old extraction state and lock files stay, so\n // the old directory is usually left holding just those.\n for (const leftover of [\n join(oldDir, INBOX_DIR, DISCARDED_DIR),\n join(oldDir, INBOX_DIR),\n oldDir,\n ]) {\n try {\n if (lstatIfPresent(leftover)?.isDirectory()) rmdirSync(leftover);\n } catch {\n // not empty, or already gone\n }\n }\n}\n\n/** Best effort: remove the old `projects/<slug>/` directory when it is a real, empty directory. */\nfunction removeEmptyLegacyProjectDir(projectDir: string): void {\n try {\n if (lstatIfPresent(projectDir)?.isDirectory()) rmdirSync(projectDir);\n } catch {\n // not empty, or already gone\n }\n}\n\n/**\n * Memory used to be keyed by the workspace string as given. Move that directory to the git-root\n * key: rename it when the new one is absent, otherwise merge (both copies of a colliding name are\n * kept). Never follows a symlink; never throws — a failure is logged and the session continues\n * with the new directory.\n */\nexport function migrateLegacyMemoryDir(workspace: string, opts?: MemoryStoreOptions): void {\n try {\n const legacySlug = slugifyWorkspace(workspace);\n if (legacySlug === '.' || legacySlug === '..') return;\n const oldDir = memoryDirIn(bookRoot(opts), workspace);\n const newDir = getProjectMemoryDir(workspace, opts);\n if (oldDir === newDir) return;\n if (!lstatIfPresent(oldDir)?.isDirectory()) return; // absent, a file, or a symlink\n\n if (!lstatIfPresent(newDir)) {\n mkdirSync(dirname(newDir), { recursive: true });\n try {\n renameSync(oldDir, newDir);\n removeEmptyLegacyProjectDir(dirname(oldDir));\n return;\n } catch (e) {\n const code = errorCode(e);\n if (code === 'ENOENT' && !lstatIfPresent(oldDir)) return; // another process moved it\n // The new directory appeared meanwhile: merge into it below.\n if (code !== 'EEXIST' && code !== 'ENOTEMPTY' && code !== 'ENOENT') throw e;\n }\n }\n if (!lstatIfPresent(newDir)?.isDirectory()) return;\n mergeLegacyMemoryDir(oldDir, newDir);\n removeEmptyLegacyProjectDir(dirname(oldDir));\n } catch (e) {\n log.warn('memory move from the old directory failed', e);\n }\n}\n\n// -- the one-time move from the old file layout -------------------------------------------------\n\n/** Written once a directory is in the current layout; its content is the layout's version. */\nconst FORMAT_FILE = '.format';\nconst FORMAT_VERSION = '2';\nconst BACKUP_PREFIX = 'memory.legacy-';\nconst BACKUP_NAME = /^memory\\.legacy-(\\d{8})(?:-(\\d+))?$/;\nconst SLUG_MAX = 60;\n/** A converted file's frontmatter `description`. */\nconst DESCRIPTION_MAX = 150;\n/** A converted index line, link included; longer than this is too long to scan. */\nconst INDEX_LINE_MAX = 200;\nconst TITLE_MAX = 120;\nconst DROPPED_STATUSES = new Set(['superseded', 'pending', 'discarded']);\n\n/** What the old inbox and extraction left in the directory. */\nconst isLegacyLeftover = (name: string): boolean =>\n name === INBOX_DIR || /^\\.extraction[-.]/.test(name);\n\ninterface LegacyFile {\n /** The top-level frontmatter keys, values as written (trimmed). */\n keys: Map<string, string>;\n /** The lines under each key that are not a `key:` line of their own (a list's items). */\n extra: Map<string, string[]>;\n body: string;\n}\n\n/**\n * The frontmatter of a memory file as the old layout wrote it: only keys at column 0 count, so a\n * current file's `metadata.type` is not mistaken for a legacy top-level `type`.\n */\nfunction parseLegacyFile(text: string): LegacyFile | null {\n const lines = text.replace(/\\r\\n?/g, '\\n').split('\\n');\n if (lines[0].trim() !== '---') return null;\n const close = lines.indexOf('---', 1);\n if (close < 0) return null;\n const keys = new Map<string, string>();\n const extra = new Map<string, string[]>();\n let current: string | null = null;\n for (const line of lines.slice(1, close)) {\n const key = /^([A-Za-z][\\w-]*)[ \\t]*:[ \\t]*(.*)$/.exec(line);\n if (key) {\n current = key[1];\n keys.set(current, key[2].trim());\n extra.set(current, []);\n } else if (current && line.trim() !== '' && !line.startsWith('#')) {\n extra.get(current)?.push(line);\n }\n }\n return { keys, extra, body: lines.slice(close + 1).join('\\n') };\n}\n\nconst unquote = (value: string): string => value.replace(/^([\"'])(.*)\\1$/, '$2').trim();\n\nconst stripControls = (text: string): string => text.replace(/[\\x00-\\x1f\\x7f]/g, '').trim();\n\n/**\n * `text` shortened to at most `max` characters, ending with `…` when anything was cut. The cut\n * is only ever between words, and never inside a backtick code span: a cut that lands in an\n * unclosed span backs up to before its opening backtick. When no whole word fits (one long word)\n * the result is just `…`; a half word would say less than nothing.\n */\nexport function shortenAtWord(text: string, max: number): string {\n if (text.length <= max) return text;\n if (max < 1) return '';\n let end = max - 1; // room for the ellipsis\n for (;;) {\n const atBoundary = end === 0 || /\\s/.test(text[end]) || /\\s/.test(text[end - 1]);\n if (!atBoundary) {\n end = Math.max(0, text.slice(0, end).search(/\\s\\S*$/));\n continue;\n }\n const ticks = text.slice(0, end).split('`').length - 1;\n if (ticks % 2 === 1) {\n end = text.lastIndexOf('`', end - 1);\n continue;\n }\n break;\n }\n const kept = text.slice(0, end).trimEnd();\n return `${kept}…`;\n}\n\n/** A YAML plain scalar when `value` is safe as one, otherwise a double-quoted one. */\nfunction yamlValue(value: string): string {\n const risky =\n value === '' ||\n /^[\\s\\-?:,[\\]{}#&*!|>'\"%@`]/.test(value) ||\n /:(\\s|$)|\\s#|\\s$/.test(value) ||\n /^(?:true|false|null|yes|no|on|off|~|[-+]?[\\d.]+)$/i.test(value);\n return risky ? JSON.stringify(value) : value;\n}\n\n/** A kebab-case slug cut to `max` characters at a `-` (a lone longer word is cut hard). */\nfunction capSlug(slug: string, max: number): string {\n if (slug.length <= max) return slug;\n const cut = slug.slice(0, max);\n const whole = slug[max] === '-' ? cut : cut.slice(0, Math.max(cut.lastIndexOf('-'), 0) || max);\n return whole.replace(/-+$/, '');\n}\n\nfunction kebabSlug(text: string): string {\n return capSlug(\n text\n .normalize('NFKD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, ''),\n SLUG_MAX,\n );\n}\n\n/** What is left of `YYYY-MM-DD-<type>-<title>-<hash>.md` without the date, type and hash. */\nfunction titleFromLegacyName(name: string): string {\n return name\n .replace(/\\.md$/i, '')\n .replace(/^\\d{4}-\\d{2}-\\d{2}-/, '')\n .replace(/^(?:user|feedback|project|reference)-/, '')\n .replace(/-(?=[a-f]*\\d)[0-9a-f]{6,12}$/, '')\n .replace(/-+/g, ' ')\n .trim();\n}\n\nconst OLD_ENTRY_TAIL = /^\\s*—\\s*[^—]*?\\s*—\\s*\\d{4}-\\d{2}-\\d{2}(?:\\s*—\\s*(.*))?$/;\n\n/** An old index line (`- [Title](file) — type — YYYY-MM-DD — hook`), as its target and hook. */\nfunction parseIndexEntry(line: string): { target: string; hook: string; old: boolean } | null {\n const entry = /^- \\[[^\\]]*\\]\\(([^()]+)\\)(.*)$/.exec(line);\n if (!entry) return null;\n const target = entry[1].replace(/^\\.\\//, '').toLowerCase();\n const old = OLD_ENTRY_TAIL.exec(entry[2]);\n if (old) return { target, hook: old[1] ?? '', old: true };\n return { target, hook: entry[2].replace(/^\\s*—\\s*/, ''), old: false };\n}\n\n/**\n * `- [Title](file) — hook`, at most `INDEX_LINE_MAX` characters: the title stays whole (up to\n * `TITLE_MAX`) and the hook gives way first; a title the link leaves no room for is shortened and\n * the hook dropped.\n */\nfunction indexLine(title: string, file: string, description: string): string {\n const plain = title.replace(/[[\\]()]/g, '').trim() || file;\n const linkCost = 6 + file.length; // `- [` + `](` + `)` around the file name\n let shown = shortenAtWord(plain, Math.min(TITLE_MAX, INDEX_LINE_MAX - linkCost));\n if (shown === '…') shown = file;\n const head = `- [${shown}](${file})`;\n const room = INDEX_LINE_MAX - head.length - 3;\n const hook = room > 1 ? shortenAtWord(description, room) : '';\n return hook && hook !== '…' ? `${head} — ${hook}` : head;\n}\n\ninterface ConvertedMemory {\n oldName: string;\n slug: string;\n title: string;\n description: string;\n content: string;\n modifiedMs: number;\n}\n\nfunction legacyModifiedMs(file: LegacyFile, name: string, mtimeMs: number): number {\n const stamped = Date.parse(unquote(file.keys.get('updated') || file.keys.get('created') || ''));\n if (!Number.isNaN(stamped)) return stamped;\n const named = Date.parse(/^\\d{4}-\\d{2}-\\d{2}/.exec(name)?.[0] ?? '');\n return Number.isNaN(named) ? mtimeMs : named;\n}\n\n/** The current-layout text of one legacy file, with the title and description it was given. */\nfunction convertLegacyFile(\n name: string,\n file: LegacyFile,\n hook: string | undefined,\n slug: (title: string) => string,\n mtimeMs: number,\n): ConvertedMemory {\n const lines = file.body.split('\\n');\n let start = 0;\n while (start < lines.length && lines[start].trim() === '') start++;\n let heading: string | undefined;\n if (start < lines.length && /^#\\s+\\S/.test(lines[start])) {\n heading = lines[start]\n .replace(/^#\\s+/, '')\n .replace(/^Candidate:\\s*/i, '')\n .trim();\n start++;\n }\n const body = lines\n .slice(start)\n .join('\\n')\n .replace(/^(?:[ \\t]*\\n)+/, '')\n .trimEnd();\n const title = heading || titleFromLegacyName(name) || 'Memory';\n const firstLine = body.split('\\n').find((line) => line.trim() !== '') ?? '';\n const description = shortenAtWord(\n stripControls(hook ?? '') || stripControls(firstLine) || stripControls(title),\n DESCRIPTION_MAX,\n );\n const finalSlug = slug(title);\n\n const value = (key: string): string => unquote(file.keys.get(key) ?? '');\n const meta: string[] = [];\n if (value('type')) meta.push(` type: ${yamlValue(value('type'))}`);\n if (value('sessionId')) meta.push(` originSessionId: ${yamlValue(value('sessionId'))}`);\n const modified = value('updated') || value('created');\n if (modified) meta.push(` modified: ${yamlValue(modified)}`);\n if (value('driver') === 'agent') meta.push(' driver: agent');\n const evidence = file.keys.get('evidence') ?? '';\n const evidenceLines = file.extra.get('evidence') ?? [];\n if (evidence !== '') {\n meta.push(` evidence: ${evidence}`);\n } else if (evidenceLines.length > 0) {\n meta.push(' evidence:');\n for (const line of evidenceLines) {\n const item = /^\\s*-\\s+(.*)$/.exec(line)?.[1]?.trim();\n meta.push(\n item === undefined\n ? ` ${line}`\n : ` - ${/^([\"']).*\\1$/.test(item) ? item : yamlValue(item)}`,\n );\n }\n }\n\n const content =\n [\n '---',\n `name: ${finalSlug}`,\n `description: ${yamlValue(description)}`,\n ...(meta.length > 0 ? ['metadata:', ...meta] : []),\n '---',\n ...(body ? [body] : []),\n ].join('\\n') + '\\n';\n return {\n oldName: name,\n slug: finalSlug,\n title,\n description,\n content,\n modifiedMs: legacyModifiedMs(file, name, mtimeMs),\n };\n}\n\nfunction localDateStamp(now: Date): string {\n const pad = (n: number): string => String(n).padStart(2, '0');\n return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}`;\n}\n\n/** Copy the regular files and directories under `source`; a link is never followed, nor copied. */\nfunction copyTreeWithoutLinks(source: string, target: string): void {\n for (const entry of readdirSync(source, { withFileTypes: true })) {\n const from = join(source, entry.name);\n const to = join(target, entry.name);\n if (entry.isDirectory()) {\n mkdirSync(to);\n copyTreeWithoutLinks(from, to);\n } else if (entry.isFile()) {\n copyFileSync(from, to, constants.COPYFILE_EXCL);\n }\n }\n}\n\n/** Copy `dir` to a fresh `memory.legacy-<YYYYMMDD>[-n]` beside it; throws, leaving nothing behind, on failure. */\nfunction backUpMemoryDir(dir: string): string {\n const stamp = localDateStamp(new Date());\n for (let n = 1; n <= 1000; n++) {\n const target = join(dirname(dir), `${BACKUP_PREFIX}${stamp}${n === 1 ? '' : `-${n}`}`);\n try {\n mkdirSync(target);\n } catch (e) {\n if (errorCode(e) === 'EEXIST') continue;\n throw e;\n }\n try {\n copyTreeWithoutLinks(dir, target);\n return target;\n } catch (e) {\n rmSync(target, { recursive: true, force: true });\n throw e;\n }\n }\n throw new Error('too many memory backups for one day');\n}\n\n/** The newest `memory.legacy-*` backup beside `dir`, or null when the migration left none. */\nexport function findLegacyMemoryBackup(dir: string): string | null {\n try {\n const found = readdirSync(dirname(dir), { withFileTypes: true })\n .filter((entry) => entry.isDirectory() && BACKUP_NAME.test(entry.name))\n .map((entry) => {\n const [, date, n] = BACKUP_NAME.exec(entry.name) ?? [];\n return { name: entry.name, date, n: Number(n ?? 1) };\n })\n .sort((a, b) => a.date.localeCompare(b.date) || a.n - b.n);\n const newest = found.at(-1);\n return newest ? join(dirname(dir), newest.name) : null;\n } catch {\n return null;\n }\n}\n\nexport function legacyBackupNotice(backup: string): string {\n return `Migrated to the new memory format; the old files are in ${backup}.`;\n}\n\n/** The new MEMORY.md: hand-written lines kept, then one pointer line per converted file. */\nfunction migratedIndexLines(\n oldText: string | null,\n converted: ConvertedMemory[],\n droppedNames: Set<string>,\n): string[] {\n const byTarget = new Map(converted.map((c) => [`${c.slug}.md`, c]));\n // An old name that is also a new slug is the same file, converted in place.\n for (const c of converted) byTarget.set(c.oldName.toLowerCase(), c);\n const kept: string[] = [];\n const ordered: ConvertedMemory[] = [];\n for (const raw of oldText?.split('\\n') ?? []) {\n const line = raw.replace(/\\r$/, '');\n if (/^#\\s*Book memory index\\s*$/i.test(line)) continue;\n const entry = parseIndexEntry(line);\n if (!entry) {\n kept.push(line);\n continue;\n }\n const match = byTarget.get(entry.target);\n if (match) {\n if (!ordered.includes(match)) ordered.push(match);\n } else if (!droppedNames.has(entry.target) && !entry.old) {\n kept.push(line);\n }\n }\n const missing = converted\n .filter((c) => !ordered.includes(c))\n .sort((a, b) => b.modifiedMs - a.modifiedMs || b.oldName.localeCompare(a.oldName));\n\n const tidy: string[] = [];\n for (const line of kept) {\n if (line.trim() === '' && (tidy.length === 0 || tidy[tidy.length - 1].trim() === '')) continue;\n tidy.push(line);\n }\n while (tidy.length > 0 && tidy[tidy.length - 1].trim() === '') tidy.pop();\n return [\n ...tidy,\n ...[...ordered, ...missing].map((c) => indexLine(c.title, `${c.slug}.md`, c.description)),\n ];\n}\n\nfunction migrateFormat(dir: string): void {\n if (!lstatIfPresent(dir)?.isDirectory()) return; // absent, a file, or a link: never followed\n const marker = join(dir, FORMAT_FILE);\n if (lstatIfPresent(marker)?.isFile() && readFileSync(marker, 'utf-8').trim() === FORMAT_VERSION) {\n return;\n }\n\n // Detect. Links are skipped throughout: nothing is read, converted or removed through one.\n const everything = readdirSync(dir, { withFileTypes: true });\n const entries = everything.filter((e) => !e.isSymbolicLink());\n const leftovers = entries.filter((e) => isLegacyLeftover(e.name)).map((e) => e.name);\n const legacy: Array<{ name: string; file: LegacyFile; mtimeMs: number }> = [];\n for (const entry of entries) {\n if (!entry.isFile() || entry.name.startsWith('.') || !isMemoryTopicFile(entry.name)) continue;\n const path = join(dir, entry.name);\n const file = parseLegacyFile(readFileSync(path, 'utf-8'));\n if (file && (file.keys.has('status') || file.keys.has('type'))) {\n legacy.push({ name: entry.name, file, mtimeMs: statSync(path).mtimeMs });\n }\n }\n if (legacy.length === 0 && leftovers.length === 0) {\n writeFileAtomic(marker, `${FORMAT_VERSION}\\n`);\n return;\n }\n\n // Everything is read before the backup, and the backup is made before anything changes.\n const indexPath = join(dir, INDEX_FILE);\n const indexStat = lstatIfPresent(indexPath);\n const oldIndex = indexStat?.isFile() ? readFileSync(indexPath, 'utf-8') : null;\n const hooks = new Map<string, string>();\n for (const line of oldIndex?.split('\\n') ?? []) {\n const entry = parseIndexEntry(line.replace(/\\r$/, ''));\n if (entry && !hooks.has(entry.target)) hooks.set(entry.target, entry.hook);\n }\n const backup = backUpMemoryDir(dir);\n log.info(`memory backed up to ${backup}`);\n\n // Every name in the directory is taken (a file never lands on another's name), and so is\n // MEMORY.md on a case-insensitive file system.\n const taken = new Set(everything.map((e) => e.name.toLowerCase()));\n taken.add(INDEX_FILE.toLowerCase());\n const converted: ConvertedMemory[] = [];\n const dropped = new Set<string>();\n for (const { name, file, mtimeMs } of legacy.sort((a, b) => a.name.localeCompare(b.name))) {\n const status = unquote(file.keys.get('status') ?? '').toLowerCase();\n if (DROPPED_STATUSES.has(status)) {\n dropped.add(name.toLowerCase());\n continue;\n }\n const own = name.toLowerCase();\n const claim = (title: string): string => {\n const base =\n kebabSlug(title) ||\n kebabSlug(titleFromLegacyName(name)) ||\n kebabSlug(unquote(file.keys.get('type') ?? '')) ||\n 'memory';\n for (let n = 1; ; n++) {\n const suffix = n === 1 ? '' : `-${n}`;\n const slug = `${capSlug(base, SLUG_MAX - suffix.length)}${suffix}`;\n const lower = `${slug}.md`;\n if (!taken.has(lower) || lower === own) {\n taken.add(lower);\n return slug;\n }\n }\n };\n converted.push(convertLegacyFile(name, file, hooks.get(own) || undefined, claim, mtimeMs));\n }\n\n for (const c of converted) {\n writeFileAtomic(join(dir, `${c.slug}.md`), c.content);\n if (`${c.slug}.md` !== c.oldName) unlinkSync(join(dir, c.oldName));\n }\n for (const name of dropped) {\n const original = legacy.find((l) => l.name.toLowerCase() === name)?.name;\n if (original) unlinkSync(join(dir, original));\n }\n for (const name of leftovers) rmSync(join(dir, name), { recursive: true, force: true });\n\n if (indexStat === null || indexStat.isFile()) {\n const lines = migratedIndexLines(oldIndex, converted, dropped);\n if (oldIndex !== null || lines.length > 0) {\n writeFileAtomic(indexPath, lines.length > 0 ? `${lines.join('\\n')}\\n` : '');\n }\n } else {\n log.warn('MEMORY.md is not a regular file; it was left as it is');\n }\n writeFileAtomic(marker, `${FORMAT_VERSION}\\n`);\n}\n\n/**\n * Bring a memory directory still in the old layout (`status` / `type` frontmatter, an inbox,\n * extraction state, a typed index) to the current one, once. The whole directory is copied to\n * `memory.legacy-<date>/` first; if that fails nothing is changed. Approved files become\n * `<slug>.md` with `name` / `description` / `metadata`; superseded, pending and discarded files,\n * the inbox and the extraction files are dropped (they survive only in the backup); `MEMORY.md`\n * is rewritten in the pointer format. A `.format` file records that it is done. Never throws,\n * never blocks the session: a failure is logged, and the next load tries again.\n */\nexport function migrateLegacyMemoryFormat(dir: string): void {\n try {\n migrateFormat(dir);\n } catch (e) {\n log.warn('memory format migration failed', e);\n }\n}\n\nfunction isMemoryType(value: unknown): value is MemoryType {\n return typeof value === 'string' && (MEMORY_TYPES as readonly string[]).includes(value);\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\n/**\n * One file's listing entry. `parseFrontmatter` reads a nested `metadata:` block's children as\n * top-level keys, so `metadata.type` (the current layout) and a top-level `type` (the legacy\n * layout) come out as the same key.\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 { body, frontmatter } = parseFrontmatter(readFileSync(path, 'utf-8'));\n const title =\n (typeof frontmatter.title === 'string' && frontmatter.title) ||\n titleFromBody(body) ||\n (typeof frontmatter.name === 'string' && frontmatter.name) ||\n undefined;\n return {\n name,\n path,\n type: isMemoryType(frontmatter.type) ? frontmatter.type : undefined,\n title,\n ...(typeof frontmatter.description === 'string' && frontmatter.description.trim()\n ? { description: frontmatter.description.trim() }\n : {}),\n size: st.size,\n ...(frontmatter.driver === 'agent' ? { driver: 'agent' as const } : {}),\n ...(frontmatter.status === 'superseded' ? { legacySuperseded: true 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 // MEMORY.md is the index, not a memory file; a dot-entry is not one either.\n if (entry.startsWith('.') || !isMemoryTopicFile(entry)) continue;\n const summary = summarizeMemoryFile(join(dir, entry), entry);\n if (summary) files.push(summary);\n }\n } catch {\n return files;\n }\n return files;\n}\n\ninterface IndexLoad {\n /** What loads: the kept text, then a blank line and the warning marker when anything was cut. */\n text: string;\n /** Non-empty lines in the whole index. */\n totalLines: number;\n /** Non-empty lines kept. */\n loadedLines: number;\n /** UTF-8 size of the trimmed index. */\n byteCount: number;\n wasLineTruncated: boolean;\n wasByteTruncated: boolean;\n}\n\nconst formatCount = (n: number): string => n.toLocaleString('en-US');\n\nfunction countNonEmptyLines(text: string): number {\n return text.split('\\n').filter((line) => line.trim().length > 0).length;\n}\n\n/**\n * What the model gets of MEMORY.md: the first `maxLines` lines, then cut again at the last\n * newline within `MAX_INDEX_BYTES` (at the last whole character when line 1 alone is longer).\n * The cut drops the end of the file, and the marker says so instead of letting entries vanish\n * silently.\n */\nfunction cutIndex(raw: string, maxLines: number): IndexLoad {\n const trimmed = raw.trim();\n const byteCount = Buffer.byteLength(trimmed);\n const lines = trimmed.length > 0 ? trimmed.split('\\n') : [];\n const wasLineTruncated = lines.length > maxLines;\n let kept = wasLineTruncated ? lines.slice(0, maxLines).join('\\n') : trimmed;\n let keptLineCount = Math.min(lines.length, maxLines);\n let wasByteTruncated = false;\n let bytesKeptOfLine1: number | undefined;\n\n if (Buffer.byteLength(kept) > MAX_INDEX_BYTES) {\n wasByteTruncated = true;\n const bytes = Buffer.from(kept, 'utf-8');\n const newline = bytes.lastIndexOf(0x0a, MAX_INDEX_BYTES);\n if (newline > 0) {\n kept = bytes.subarray(0, newline).toString('utf-8');\n keptLineCount = kept.split('\\n').length;\n } else {\n // No newline in range: cut inside line 1, backing up to a character boundary.\n let end = MAX_INDEX_BYTES;\n while (end > 0 && (bytes[end] & 0xc0) === 0x80) end--;\n kept = bytes.subarray(0, end).toString('utf-8');\n keptLineCount = 1;\n bytesKeptOfLine1 = end;\n }\n }\n\n let text = kept;\n if (wasLineTruncated || wasByteTruncated) {\n const detail =\n bytesKeptOfLine1 !== undefined\n ? `everything after the first ${formatCount(bytesKeptOfLine1)} bytes of line 1 was cut off`\n : `${formatCount(lines.length - keptLineCount)} of ${formatCount(lines.length)} lines were cut off, starting at line ${formatCount(keptLineCount + 1)} (\"${Array.from(lines[keptLineCount]).slice(0, 80).join('')}\")`;\n text =\n `${kept}\\n\\n> WARNING: MEMORY.md is ${formatCount(lines.length)} lines and ${formatCount(byteCount)} bytes ` +\n `(limits: ${formatCount(maxLines)} lines, ${formatCount(MAX_INDEX_BYTES)} bytes). ` +\n `Only part of it was loaded: ${detail}. ` +\n 'Keep each entry to one line and move detail into the memory file.';\n }\n return {\n text,\n totalLines: countNonEmptyLines(trimmed),\n loadedLines: countNonEmptyLines(kept),\n byteCount,\n wasLineTruncated,\n wasByteTruncated,\n };\n}\n\nexport function loadMemoryContext(\n workspace: string,\n opts?: MemoryStoreOptions,\n): LoadedMemoryContext {\n // Before anything is read: a directory keyed the old way moves to the git-root key first,\n // and then the files in it are brought to the current layout.\n migrateLegacyMemoryDir(workspace, opts);\n const dir = getProjectMemoryDir(workspace, opts);\n migrateLegacyMemoryFormat(dir);\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 indexByteCount: 0,\n wasLineTruncated: false,\n wasByteTruncated: false,\n indexText: '',\n files: [],\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 = cutIndex(readFileSync(indexFile, 'utf-8'), maxIndexLines);\n result.indexFile = indexFile;\n result.indexLoaded = index.text.length > 0;\n result.indexLineCount = index.totalLines;\n result.loadedLineCount = index.loadedLines;\n result.indexByteCount = index.byteCount;\n result.wasLineTruncated = index.wasLineTruncated;\n result.wasByteTruncated = index.wasByteTruncated;\n result.indexText = index.text;\n }\n } catch {\n result.indexFile = indexFile;\n }\n }\n\n result.files = listMemoryFiles(workspace, opts);\n return result;\n}\n\nexport interface MemoryHealth {\n /** Memory files (every `*.md` but MEMORY.md), legacy superseded ones included. */\n fileCount: number;\n /** Files that still carry the retired `status: superseded` frontmatter. */\n legacySupersededCount: number;\n indexLineCount: number;\n /** UTF-8 size of the trimmed MEMORY.md. */\n indexByteCount: number;\n /** The index is over the line limit, so a session loads only part of it. */\n wasLineTruncated: boolean;\n /** The index is over the byte limit, so a session loads only part of it. */\n wasByteTruncated: boolean;\n lastWrite: Date | null;\n}\n\nexport function getNewestMemoryWriteTime(memoryDir: string): Date | null {\n if (!existsSync(memoryDir)) return null;\n let newestMs = 0;\n let entries: string[];\n try {\n entries = readdirSync(memoryDir);\n } catch {\n return null;\n }\n for (const entry of entries) {\n if (entry.startsWith('.')) continue;\n try {\n const st = lstatSync(join(memoryDir, entry));\n if (st.isSymbolicLink() || !st.isFile()) continue;\n if (st.mtimeMs > newestMs) newestMs = st.mtimeMs;\n } catch {\n // ignore unreadable entries\n }\n }\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 ? getProjectMemoryDir(workspaceOrContext, opts)\n : workspaceOrContext.dir;\n\n let fileCount = 0;\n let legacySupersededCount = 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 (entry.startsWith('.') || !isMemoryTopicFile(entry)) 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) continue;\n fileCount++;\n if (summary.legacySuperseded) legacySupersededCount++;\n } catch {\n // ignore unreadable file\n }\n }\n } catch {\n // ignore unreadable directory\n }\n }\n\n let indexLineCount = 0;\n let indexByteCount = 0;\n let wasLineTruncated = false;\n let wasByteTruncated = false;\n try {\n indexLineCount = readIndexLines(dir).length;\n const indexPath = join(dir, INDEX_FILE);\n if (existsSync(indexPath)) {\n const cut = cutIndex(\n readFileSync(indexPath, 'utf-8'),\n opts?.maxIndexLines ?? DEFAULT_MAX_INDEX_LINES,\n );\n indexByteCount = cut.byteCount;\n wasLineTruncated = cut.wasLineTruncated;\n wasByteTruncated = cut.wasByteTruncated;\n }\n } catch {\n // unreadable index\n }\n\n return {\n fileCount,\n legacySupersededCount,\n indexLineCount,\n indexByteCount,\n wasLineTruncated,\n wasByteTruncated,\n lastWrite: getNewestMemoryWriteTime(dir),\n };\n}\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 * Drop every MEMORY.md line that links to `filename` (a user's `/memory delete`). The index is the\n * model's own, so every other line stays exactly as it is, and an index with no such line is not\n * rewritten at all.\n */\nfunction removeIndexEntries(dir: string, filename: string): void {\n const indexPath = join(dir, INDEX_FILE);\n if (!lstatIfPresent(indexPath)?.isFile()) return;\n const raw = readFileSync(indexPath, 'utf-8');\n const target = filename.toLowerCase();\n const lines = raw.split('\\n');\n const kept = lines.filter((line) => {\n const file = indexEntryFile(line);\n return file === undefined || file.replace(/^\\.\\//, '').toLowerCase() !== target;\n });\n if (kept.length !== lines.length) writeFileAtomic(indexPath, kept.join('\\n'));\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 (!lstatIfPresent(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 removeIndexEntries(dir, filename);\n } catch {\n // The file is gone either way; a stale index line points at nothing.\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","/**\n * The two limits `MEMORY.md` is loaded under. A leaf module so the memory write guard can read\n * them without importing `memory-store.ts`, which would close an import cycle through\n * `permissions.ts` and the file tools.\n */\nexport const DEFAULT_MAX_INDEX_LINES = 200;\nexport const MAX_INDEX_BYTES = 25_000;\n"],"mappings":"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","names":[]}
|