@latysh-development/monolith 0.1.0-alpha.0 → 0.1.0-alpha.1

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 (100) hide show
  1. package/README.md +63 -16
  2. package/dist/brief/collect.d.ts.map +1 -1
  3. package/dist/brief/collect.js +41 -1
  4. package/dist/brief/constants.d.ts +2 -0
  5. package/dist/brief/constants.d.ts.map +1 -1
  6. package/dist/brief/constants.js +2 -0
  7. package/dist/brief/render.d.ts +7 -0
  8. package/dist/brief/render.d.ts.map +1 -1
  9. package/dist/brief/render.js +52 -1
  10. package/dist/brief/types.d.ts +17 -1
  11. package/dist/brief/types.d.ts.map +1 -1
  12. package/dist/cli/index.js +33 -0
  13. package/dist/discovery/compose.d.ts +28 -0
  14. package/dist/discovery/compose.d.ts.map +1 -0
  15. package/dist/discovery/compose.js +159 -0
  16. package/dist/discovery/contracts.d.ts +211 -0
  17. package/dist/discovery/contracts.d.ts.map +1 -0
  18. package/dist/discovery/contracts.js +555 -0
  19. package/dist/discovery/docs.d.ts +278 -0
  20. package/dist/discovery/docs.d.ts.map +1 -0
  21. package/dist/discovery/docs.js +1182 -0
  22. package/dist/discovery/facts.d.ts +49 -0
  23. package/dist/discovery/facts.d.ts.map +1 -0
  24. package/dist/discovery/facts.js +541 -0
  25. package/dist/discovery/index.d.ts +8 -0
  26. package/dist/discovery/index.d.ts.map +1 -0
  27. package/dist/discovery/index.js +9 -0
  28. package/dist/discovery/orchestrate.d.ts +35 -0
  29. package/dist/discovery/orchestrate.d.ts.map +1 -0
  30. package/dist/discovery/orchestrate.js +32 -0
  31. package/dist/discovery/render.d.ts +36 -0
  32. package/dist/discovery/render.d.ts.map +1 -0
  33. package/dist/discovery/render.js +278 -0
  34. package/dist/discovery/traverse.d.ts +197 -0
  35. package/dist/discovery/traverse.d.ts.map +1 -0
  36. package/dist/discovery/traverse.js +510 -0
  37. package/dist/durable/errors.d.ts +6 -2
  38. package/dist/durable/errors.d.ts.map +1 -1
  39. package/dist/durable/errors.js +9 -3
  40. package/dist/durable/fs-store.d.ts +21 -0
  41. package/dist/durable/fs-store.d.ts.map +1 -1
  42. package/dist/durable/fs-store.js +103 -3
  43. package/dist/durable/prune-check.d.ts +17 -0
  44. package/dist/durable/prune-check.d.ts.map +1 -1
  45. package/dist/durable/prune-check.js +27 -0
  46. package/dist/durable/runtime.d.ts +5 -3
  47. package/dist/durable/runtime.d.ts.map +1 -1
  48. package/dist/durable/runtime.js +23 -6
  49. package/dist/durable/seams.d.ts +4 -0
  50. package/dist/durable/seams.d.ts.map +1 -1
  51. package/dist/durable/testing.js +2 -2
  52. package/dist/ideas/cli.d.ts +33 -0
  53. package/dist/ideas/cli.d.ts.map +1 -0
  54. package/dist/ideas/cli.js +158 -0
  55. package/dist/ideas/format.d.ts +38 -0
  56. package/dist/ideas/format.d.ts.map +1 -0
  57. package/dist/ideas/format.js +194 -0
  58. package/dist/ideas/index.d.ts +6 -0
  59. package/dist/ideas/index.d.ts.map +1 -0
  60. package/dist/ideas/index.js +3 -0
  61. package/dist/ideas/store.d.ts +55 -0
  62. package/dist/ideas/store.d.ts.map +1 -0
  63. package/dist/ideas/store.js +262 -0
  64. package/dist/ideas/types.d.ts +54 -0
  65. package/dist/ideas/types.d.ts.map +1 -0
  66. package/dist/ideas/types.js +26 -0
  67. package/dist/index.d.ts +1 -0
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +2 -0
  70. package/dist/init/scaffold.d.ts +4 -0
  71. package/dist/init/scaffold.d.ts.map +1 -1
  72. package/dist/init/scaffold.js +6 -2
  73. package/dist/managed/index.d.ts +73 -0
  74. package/dist/managed/index.d.ts.map +1 -0
  75. package/dist/managed/index.js +222 -0
  76. package/dist/root/index.d.ts +7 -0
  77. package/dist/root/index.d.ts.map +1 -1
  78. package/dist/root/index.js +13 -1
  79. package/dist/update/cli.d.ts +8 -0
  80. package/dist/update/cli.d.ts.map +1 -0
  81. package/dist/update/cli.js +115 -0
  82. package/dist/update/index.d.ts +78 -0
  83. package/dist/update/index.d.ts.map +1 -0
  84. package/dist/update/index.js +285 -0
  85. package/dist/version.d.ts +1 -1
  86. package/dist/version.js +1 -1
  87. package/package.json +1 -1
  88. package/templates/default-instance/instruction/.cursorrules +6 -0
  89. package/templates/default-instance/instruction/.windsurfrules +6 -0
  90. package/templates/default-instance/instruction/CLAUDE.md +4 -0
  91. package/templates/default-instance/managed/agent.md +20 -0
  92. package/templates/default-instance/managed/bootstrap.md +7 -0
  93. package/templates/default-instance/managed/index-idea.md +5 -0
  94. package/templates/default-instance/managed/routing-idea.md +14 -0
  95. package/templates/default-instance/monolith/AGENT.md +1 -0
  96. package/templates/default-instance/monolith/context/maps/routing-map.md +4 -0
  97. package/templates/default-instance/monolith/context/maps/semantic-map.md +2 -0
  98. package/templates/default-instance/monolith/skills/INDEX.md +4 -0
  99. package/templates/default-instance/monolith/skills/idea-capture/SKILL.md +157 -0
  100. package/templates/default-instance/projectroot/AGENTS.md +4 -0
@@ -0,0 +1,510 @@
1
+ /**
2
+ * Bounded, safe project traversal (DISCOVERY-001B-1, ADR-021).
3
+ *
4
+ * Lists the directory tree of a project and nothing else: it never reads file
5
+ * content, never writes, never runs project code and never touches the network.
6
+ * It is the only code in Discovery that lists directories.
7
+ *
8
+ * What it does:
9
+ * - lists each directory through `opendir` + `Dir#readSync` (never `readdirSync`),
10
+ * one open handle at a time, so a hostile directory cannot be loaded whole before
11
+ * a cap applies; the handle is always closed (`finally`);
12
+ * - never follows a symlink (it is listed as kind `symlink` and counted; its target is
13
+ * never looked at); FIFOs, sockets and devices are listed as `other`, never opened;
14
+ * - excludes the real `<monolithRoot>` (resolved with `resolveMonolithRoot`, not by
15
+ * the literal name `.monolith`), a fixed list of dependency/build directories, nested
16
+ * repositories (a directory holding `.git`) and directories on another file system;
17
+ * - bounds the work and the retained result: directory entries READ (every listing counts,
18
+ * including the one of a directory later found to be unreadable, replaced or opaque),
19
+ * entries per directory, depth, wall-clock time and the UTF-8 bytes of the retained
20
+ * paths; every bound that fires yields `PARTIAL` with a typed diagnostic, never a
21
+ * silent cut. A nested repository is recognised by one `lstat` of `<dir>/.git` BEFORE
22
+ * the directory is listed, so its content is neither read nor counted;
23
+ * - is deterministic for an unchanged tree: names are ordered by UTF-16 code units
24
+ * (never `localeCompare`), breadth-first, and the result is sorted before it is
25
+ * returned. No clock value, absolute path or `readdir` order reaches the result.
26
+ *
27
+ * What it does NOT do (ADR-013, SEC-001B.3 open; TM-C unsupported): it does not prevent
28
+ * and does not reliably detect a process that replaces a directory (e.g. with a symlink)
29
+ * while the walk runs. The window runs from the `lstat` that queues a directory until
30
+ * the walk has listed it, i.e. the breadth-first distance in between. Comparing the
31
+ * identity (`dev`/`ino`) of a directory before and after listing it (`DIR_CHANGED`) may
32
+ * notice SOME replacements; a replacement that is put back before the second `lstat`
33
+ * goes unnoticed, and names read from the substitute can then appear as COMPLETE.
34
+ * Do not run it on a tree an untrusted process is modifying.
35
+ *
36
+ * Root: `projectRoot` must be absolute and is the caller's explicit choice. A symlink as
37
+ * root is accepted and its target is walked (nothing below the root is ever followed, so
38
+ * the boundary is the directory the caller named). A missing, non-directory, unreadable
39
+ * or otherwise unresolvable root throws `ROOT_UNSAFE` (from `resolveMonolithRoot`, before
40
+ * any listing); `ROOT_NOT_DIRECTORY` is the defensive second check. Errors other than a
41
+ * root-containment error from `resolveMonolithRoot` propagate unchanged.
42
+ *
43
+ * Nested MONOLITH instances: only the actual `<monolithRoot>` is excluded. A sub-project
44
+ * that has its own `.monolith` stays part of the inventory (its sources belong to this
45
+ * project); that directory is not recognised by name. Excluding the confirmed internals
46
+ * of nested instances is a decision for DISCOVERY-001B-2.
47
+ *
48
+ * The time budget is checked between entries; a synchronous syscall that hangs in the
49
+ * kernel (e.g. a dead network mount) is not interrupted.
50
+ */
51
+ import { lstatSync, opendirSync, statSync, constants } from 'fs';
52
+ import { join } from 'path';
53
+ import { RootContainmentError, resolveMonolithRoot } from '../root/index.js';
54
+ /** Starting values (ADR-021 Q-10); validated by the 001B-1 benchmark, see the story report. */
55
+ export const DEFAULT_TRAVERSAL_LIMITS = Object.freeze({
56
+ maxEntries: 50_000,
57
+ maxEntriesPerDir: 10_000,
58
+ maxDepth: 32,
59
+ deadlineMs: 30_000,
60
+ // Measured (DISCOVERY-001B-1-F): 50 000 paths of 3.6 KB each retained ~188 MiB of heap;
61
+ // real trees average well under 100 B per path (a few MiB at 50 000 entries).
62
+ maxPathBytes: 16 * 1024 * 1024,
63
+ });
64
+ /** Directories never entered, matched by name at any depth. */
65
+ export const EXCLUDED_DIR_NAMES = [
66
+ 'node_modules',
67
+ '.git',
68
+ 'dist',
69
+ 'build',
70
+ '.next',
71
+ 'out',
72
+ 'coverage',
73
+ '.venv',
74
+ 'venv',
75
+ '__pycache__',
76
+ 'target',
77
+ 'vendor',
78
+ ];
79
+ /** Directories never entered, matched by project-relative path. */
80
+ export const EXCLUDED_DIR_PATHS = ['.claude/worktrees'];
81
+ /** Per code: how many individual paths are listed before only the total is kept. */
82
+ const MAX_DIAGNOSTIC_PATHS = 20;
83
+ const MAX_NAME_BYTES = 255;
84
+ /**
85
+ * Closed list. `affectsCompleteness` codes make the result PARTIAL (something inside
86
+ * the declared scope could not be done). The others report the scope policy.
87
+ * An unknown code is treated as affecting completeness (fail closed).
88
+ */
89
+ const DIAGNOSTIC_AFFECTS_COMPLETENESS = {
90
+ LIMIT_ENTRIES: true,
91
+ LIMIT_DEPTH: true,
92
+ LIMIT_DIR_ENTRIES: true,
93
+ LIMIT_DEADLINE: true,
94
+ LIMIT_PATH_BYTES: true,
95
+ DIR_UNREADABLE: true,
96
+ DIR_VANISHED: true,
97
+ DIR_CHANGED: true,
98
+ DIR_ERROR: true,
99
+ NAME_UNREPRESENTABLE: true,
100
+ ENTRY_UNCLASSIFIED: true,
101
+ EXCLUDED_DIR: false,
102
+ MONOLITH_ROOT_EXCLUDED: false,
103
+ SYMLINK_SKIPPED: false,
104
+ NESTED_REPO_SKIPPED: false,
105
+ MOUNT_SKIPPED: false,
106
+ };
107
+ /**
108
+ * Whether a code is a function of the tree and the parameters alone. A `false` code means a
109
+ * second walk of the same path may return another result (clock speed, a tree being modified,
110
+ * a transient I/O failure), so the result is not `reproducible`. Stable codes include the
111
+ * resource limits that cut a deterministic prefix and permission errors on an unchanged tree.
112
+ */
113
+ const DIAGNOSTIC_IS_STABLE = {
114
+ LIMIT_ENTRIES: true,
115
+ LIMIT_DEPTH: true,
116
+ LIMIT_DIR_ENTRIES: true,
117
+ LIMIT_DEADLINE: false,
118
+ LIMIT_PATH_BYTES: true,
119
+ DIR_UNREADABLE: true,
120
+ DIR_VANISHED: false,
121
+ DIR_CHANGED: false,
122
+ DIR_ERROR: false,
123
+ NAME_UNREPRESENTABLE: true,
124
+ ENTRY_UNCLASSIFIED: false,
125
+ EXCLUDED_DIR: true,
126
+ MONOLITH_ROOT_EXCLUDED: true,
127
+ SYMLINK_SKIPPED: true,
128
+ NESTED_REPO_SKIPPED: true,
129
+ MOUNT_SKIPPED: true,
130
+ };
131
+ /** The traversal cannot start or cannot be trusted; no result exists (FAILED). */
132
+ export class TraversalError extends Error {
133
+ code;
134
+ constructor(code, message, options) {
135
+ super(message, options);
136
+ this.name = 'TraversalError';
137
+ this.code = code;
138
+ }
139
+ }
140
+ const realFs = {
141
+ opendir: (path) => opendirSync(path),
142
+ lstat: (path) => lstatSync(path, { bigint: true }),
143
+ stat: (path) => statSync(path, { bigint: true }),
144
+ };
145
+ // ---------------------------------------------------------------------------
146
+ function resolveLimits(partial) {
147
+ const limits = { ...DEFAULT_TRAVERSAL_LIMITS, ...(partial ?? {}) };
148
+ for (const key of Object.keys(DEFAULT_TRAVERSAL_LIMITS)) {
149
+ const v = limits[key];
150
+ if (typeof v !== 'number' || !Number.isInteger(v) || v < 1) {
151
+ throw new TraversalError('INVALID_LIMITS', `limit "${key}" must be a positive integer (got ${String(v)}).`);
152
+ }
153
+ }
154
+ return limits;
155
+ }
156
+ /**
157
+ * Why a name cannot be represented faithfully, or `null`: U+FFFD (invalid UTF-8 was replaced),
158
+ * NUL, C0/C1 controls, over-long, empty. The reason is a fixed phrase; the name itself never
159
+ * reaches a diagnostic.
160
+ */
161
+ function nameProblem(name) {
162
+ if (name.length === 0)
163
+ return 'empty';
164
+ if (Buffer.byteLength(name, 'utf8') > MAX_NAME_BYTES)
165
+ return `longer than ${MAX_NAME_BYTES} bytes`;
166
+ for (let i = 0; i < name.length; i++) {
167
+ const c = name.charCodeAt(i);
168
+ if (c < 0x20 || c === 0x7f || (c >= 0x80 && c <= 0x9f))
169
+ return 'contains a control character';
170
+ if (c === 0xfffd)
171
+ return 'contains U+FFFD (invalid UTF-8 or a literal replacement character)';
172
+ }
173
+ return null;
174
+ }
175
+ /** UTF-16 code-unit order (the default `<`), not locale order. */
176
+ function compareUnits(a, b) {
177
+ return a < b ? -1 : a > b ? 1 : 0;
178
+ }
179
+ class DiagnosticLog {
180
+ byCode = new Map();
181
+ add(code, message, path) {
182
+ let slot = this.byCode.get(code);
183
+ if (!slot) {
184
+ slot = { total: 0, items: [] };
185
+ this.byCode.set(code, slot);
186
+ }
187
+ slot.total++;
188
+ if (slot.items.length < MAX_DIAGNOSTIC_PATHS) {
189
+ slot.items.push(path === undefined ? { code, message } : { code, path, message });
190
+ }
191
+ }
192
+ has(code) {
193
+ return this.byCode.has(code);
194
+ }
195
+ isStable() {
196
+ for (const code of this.byCode.keys()) {
197
+ if (!DIAGNOSTIC_IS_STABLE[code])
198
+ return false;
199
+ }
200
+ return true;
201
+ }
202
+ affectsCompleteness() {
203
+ for (const code of this.byCode.keys()) {
204
+ if (DIAGNOSTIC_AFFECTS_COMPLETENESS[code] !== false)
205
+ return true;
206
+ }
207
+ return false;
208
+ }
209
+ toSortedList() {
210
+ const out = [];
211
+ for (const [code, slot] of this.byCode) {
212
+ out.push(...slot.items);
213
+ if (slot.total > slot.items.length) {
214
+ out.push({ code, count: slot.total, message: `${slot.total} occurrences in total; the first ${slot.items.length} are listed.` });
215
+ }
216
+ }
217
+ const rank = (d) => (DIAGNOSTIC_AFFECTS_COMPLETENESS[d.code] !== false ? 0 : 1);
218
+ return out.sort((a, b) => rank(a) - rank(b) ||
219
+ compareUnits(a.code, b.code) ||
220
+ compareUnits(a.path ?? '', b.path ?? '') ||
221
+ compareUnits(a.message, b.message));
222
+ }
223
+ }
224
+ /**
225
+ * The only way a file-system error reaches a diagnostic or a thrown message: its `code`, and
226
+ * only when it looks like an errno name. `message`, `stack` and any other property of an
227
+ * error are untrusted (a seam or exotic file system can put a path or control characters in
228
+ * them) and are never copied.
229
+ */
230
+ const SAFE_ERRNO = /^[A-Z][A-Z0-9_]{1,31}$/;
231
+ const UNKNOWN_ERROR = 'UNKNOWN_ERROR';
232
+ function errno(err) {
233
+ let code;
234
+ try {
235
+ code = err?.code;
236
+ }
237
+ catch {
238
+ return UNKNOWN_ERROR;
239
+ }
240
+ return typeof code === 'string' && SAFE_ERRNO.test(code) ? code : UNKNOWN_ERROR;
241
+ }
242
+ /**
243
+ * List one directory with two hard caps and always close the handle. Reading stops at the
244
+ * first entry beyond `maxEntriesPerDir` ('opaque') or beyond `budgetLeft` ('budget'; the
245
+ * directory does not fit in what `maxEntries` leaves). Both outcomes depend only on how many
246
+ * entries the directory has, never on the order they are returned in. When the caps coincide
247
+ * the directory is reported as opaque.
248
+ */
249
+ function listDirectory(fs, abs, maxEntriesPerDir, budgetLeft) {
250
+ let handle;
251
+ try {
252
+ handle = fs.opendir(abs);
253
+ }
254
+ catch (err) {
255
+ return failureOf(err, 0);
256
+ }
257
+ const dirents = [];
258
+ const cap = Math.min(maxEntriesPerDir, budgetLeft);
259
+ let outcome;
260
+ try {
261
+ for (;;) {
262
+ const dirent = handle.readSync();
263
+ if (dirent === null)
264
+ break;
265
+ if (dirents.length >= cap) {
266
+ // One entry more than the cap: stop reading, the directory is not enumerated.
267
+ const opaque = maxEntriesPerDir <= budgetLeft;
268
+ return opaque
269
+ ? { ok: false, read: dirents.length + 1, reason: 'opaque', detail: `more than ${maxEntriesPerDir} entries` }
270
+ : { ok: false, read: dirents.length + 1, reason: 'budget', detail: `more than ${budgetLeft} entries left in the budget` };
271
+ }
272
+ dirents.push({ name: dirent.name, dirent });
273
+ }
274
+ outcome = { ok: true, read: dirents.length, dirents };
275
+ }
276
+ catch (err) {
277
+ outcome = failureOf(err, dirents.length);
278
+ }
279
+ finally {
280
+ try {
281
+ handle.closeSync();
282
+ }
283
+ catch {
284
+ // A failed close of a read-only handle changes nothing we returned.
285
+ }
286
+ }
287
+ return outcome;
288
+ }
289
+ function failureOf(err, read) {
290
+ const code = errno(err);
291
+ if (code === 'EACCES' || code === 'EPERM')
292
+ return { ok: false, read, reason: 'unreadable', detail: `${code}` };
293
+ if (code === 'ENOENT' || code === 'ENOTDIR')
294
+ return { ok: false, read, reason: 'vanished', detail: `${code}` };
295
+ return { ok: false, read, reason: 'error', detail: code };
296
+ }
297
+ /** Whether `<abs>/.git` exists (any type, not followed). One `lstat`, no listing; any failure means "not known to exist". */
298
+ function hasGitEntry(fs, abs) {
299
+ try {
300
+ fs.lstat(join(abs, '.git'));
301
+ return true;
302
+ }
303
+ catch {
304
+ return false;
305
+ }
306
+ }
307
+ /** Throws when the type is not reported and `lstat` fails: the caller must not invent a kind. */
308
+ function direntKind(fs, dirent, abs) {
309
+ if (dirent.isSymbolicLink())
310
+ return 'symlink';
311
+ if (dirent.isDirectory())
312
+ return 'directory';
313
+ if (dirent.isFile())
314
+ return 'file';
315
+ // DT_UNKNOWN: the file system does not report a type in the listing; ask, without following.
316
+ const st = fs.lstat(abs);
317
+ if (st.isSymbolicLink())
318
+ return 'symlink';
319
+ if (st.isDirectory())
320
+ return 'directory';
321
+ if (st.isFile())
322
+ return 'file';
323
+ return 'other';
324
+ }
325
+ /**
326
+ * Walk the project at `projectRoot` and return its structure.
327
+ *
328
+ * `projectRoot` is the explicit, caller-resolved project directory (for the CLI: `cwd`).
329
+ * The instance root is resolved with `resolveMonolithRoot` and excluded. Throws
330
+ * `TraversalError` when the walk cannot start or be trusted; otherwise returns a
331
+ * result that says whether it is `COMPLETE` or `PARTIAL`.
332
+ */
333
+ export function traverseProject(projectRoot, options = {}) {
334
+ const flags = options.platformFlags ?? { noFollow: constants.O_NOFOLLOW, nonBlock: constants.O_NONBLOCK };
335
+ if (typeof flags.noFollow !== 'number' || flags.noFollow === 0 || typeof flags.nonBlock !== 'number' || flags.nonBlock === 0) {
336
+ throw new TraversalError('UNSUPPORTED_PLATFORM', 'this platform lacks O_NOFOLLOW/O_NONBLOCK; Discovery fails closed here (ADR-021).');
337
+ }
338
+ const limits = resolveLimits(options.limits);
339
+ const fs = options.fs ?? realFs;
340
+ const now = options.now ?? (() => Number(process.hrtime.bigint() / 1000000n));
341
+ let monolithRoot;
342
+ try {
343
+ monolithRoot = resolveMonolithRoot(projectRoot).monolithRoot;
344
+ }
345
+ catch (err) {
346
+ if (err instanceof RootContainmentError)
347
+ throw new TraversalError('ROOT_UNSAFE', err.message, { cause: err });
348
+ throw err;
349
+ }
350
+ let rootIdentity;
351
+ try {
352
+ rootIdentity = fs.stat(projectRoot);
353
+ }
354
+ catch (err) {
355
+ throw new TraversalError('ROOT_NOT_DIRECTORY', `project root is not accessible (${errno(err)}).`);
356
+ }
357
+ if (!rootIdentity.isDirectory())
358
+ throw new TraversalError('ROOT_NOT_DIRECTORY', 'project root is not a directory.');
359
+ const startedAt = now();
360
+ const diagnostics = new DiagnosticLog();
361
+ const entries = [];
362
+ const stats = { entries: 0, files: 0, directories: 0, symlinks: 0, other: 0, examined: 0, pathBytes: 0, listedDirectories: 0 };
363
+ let stopped = false;
364
+ let deadlineFired = false;
365
+ const overDeadline = () => {
366
+ if (now() - startedAt > limits.deadlineMs) {
367
+ if (!deadlineFired)
368
+ diagnostics.add('LIMIT_DEADLINE', `time budget of ${limits.deadlineMs} ms exhausted; the walk stopped.`);
369
+ deadlineFired = true;
370
+ stopped = true;
371
+ }
372
+ return stopped;
373
+ };
374
+ const queue = [{ rel: '', depth: 0, identity: rootIdentity }];
375
+ for (let qi = 0; qi < queue.length && !overDeadline(); qi++) {
376
+ const dir = queue[qi];
377
+ const abs = dir.rel === '' ? projectRoot : join(projectRoot, dir.rel);
378
+ const label = dir.rel === '' ? '.' : dir.rel;
379
+ // A nested repository is recognised without listing it, so its content is neither read nor counted.
380
+ if (dir.rel !== '' && hasGitEntry(fs, abs)) {
381
+ diagnostics.add('NESTED_REPO_SKIPPED', 'nested repository or worktree (contains .git); not entered.', label);
382
+ continue;
383
+ }
384
+ const listed = listDirectory(fs, abs, limits.maxEntriesPerDir, limits.maxEntries - stats.examined);
385
+ // Every listing is charged for what it read, whatever becomes of it (kept, unreadable, replaced, opaque).
386
+ stats.examined += listed.read;
387
+ if (stats.examined > limits.maxEntries) {
388
+ diagnostics.add('LIMIT_ENTRIES', `more than ${limits.maxEntries} entries read; the walk stopped.`);
389
+ stopped = true;
390
+ }
391
+ if (!listed.ok) {
392
+ if (listed.reason === 'opaque') {
393
+ diagnostics.add('LIMIT_DIR_ENTRIES', `directory has more than ${limits.maxEntriesPerDir} entries; not enumerated.`, label);
394
+ }
395
+ else if (listed.reason === 'budget') {
396
+ // LIMIT_ENTRIES was recorded above: this directory did not fit in the remaining budget.
397
+ }
398
+ else if (listed.reason === 'unreadable') {
399
+ diagnostics.add('DIR_UNREADABLE', `directory cannot be read (${listed.detail}).`, label);
400
+ }
401
+ else if (listed.reason === 'vanished') {
402
+ diagnostics.add('DIR_VANISHED', `directory disappeared during the walk (${listed.detail}); the tree is being modified.`, label);
403
+ }
404
+ else {
405
+ diagnostics.add('DIR_ERROR', `directory cannot be listed (${listed.detail}).`, label);
406
+ }
407
+ continue;
408
+ }
409
+ // Identity after listing must match the identity before (may notice a replacement; does not prevent one; see header).
410
+ let after;
411
+ try {
412
+ after = dir.rel === '' ? fs.stat(abs) : fs.lstat(abs);
413
+ }
414
+ catch (err) {
415
+ diagnostics.add('DIR_VANISHED', `directory disappeared during the walk (${errno(err)}); the tree is being modified.`, label);
416
+ continue;
417
+ }
418
+ if (after.dev !== dir.identity.dev || after.ino !== dir.identity.ino || (dir.rel !== '' && !after.isDirectory())) {
419
+ diagnostics.add('DIR_CHANGED', 'directory was replaced while it was being listed; its contents are discarded.', label);
420
+ continue;
421
+ }
422
+ stats.listedDirectories++;
423
+ // The probe above normally catches this; the listing is the second look (a .git that appeared meanwhile).
424
+ const hasGit = listed.dirents.some((d) => d.name === '.git');
425
+ if (dir.rel !== '' && hasGit) {
426
+ diagnostics.add('NESTED_REPO_SKIPPED', 'nested repository or worktree (contains .git); not entered.', label);
427
+ continue;
428
+ }
429
+ const sorted = listed.dirents.sort((a, b) => compareUnits(a.name, b.name));
430
+ for (const { name, dirent } of sorted) {
431
+ if (overDeadline())
432
+ break;
433
+ const rel = dir.rel === '' ? name : `${dir.rel}/${name}`;
434
+ const problem = nameProblem(name);
435
+ if (problem !== null) {
436
+ diagnostics.add('NAME_UNREPRESENTABLE', `an entry whose name ${problem} was excluded; its name is not shown.`, label);
437
+ continue;
438
+ }
439
+ if (rel === monolithRoot) {
440
+ diagnostics.add('MONOLITH_ROOT_EXCLUDED', 'the MONOLITH instance root is not part of the inventory.', rel);
441
+ continue;
442
+ }
443
+ let kind;
444
+ try {
445
+ kind = direntKind(fs, dirent, join(projectRoot, rel));
446
+ }
447
+ catch (err) {
448
+ // No type was reported and lstat failed: do not state a type, and do not hide the cause.
449
+ diagnostics.add('ENTRY_UNCLASSIFIED', `entry type could not be determined (${errno(err)}); not listed.`, rel);
450
+ continue;
451
+ }
452
+ if (kind === 'directory' && (EXCLUDED_DIR_NAMES.includes(name) || EXCLUDED_DIR_PATHS.includes(rel))) {
453
+ diagnostics.add('EXCLUDED_DIR', `excluded directory "${name}".`, rel);
454
+ continue;
455
+ }
456
+ const bytes = Buffer.byteLength(rel, 'utf8');
457
+ if (stats.pathBytes + bytes > limits.maxPathBytes) {
458
+ diagnostics.add('LIMIT_PATH_BYTES', `retained paths would exceed ${limits.maxPathBytes} bytes; the walk stopped.`);
459
+ stopped = true;
460
+ break;
461
+ }
462
+ stats.pathBytes += bytes;
463
+ entries.push({ path: rel, kind });
464
+ stats.entries++;
465
+ if (kind === 'file')
466
+ stats.files++;
467
+ else if (kind === 'directory')
468
+ stats.directories++;
469
+ else if (kind === 'symlink') {
470
+ stats.symlinks++;
471
+ diagnostics.add('SYMLINK_SKIPPED', 'symbolic link listed, not followed.', rel);
472
+ }
473
+ else
474
+ stats.other++;
475
+ if (kind !== 'directory')
476
+ continue;
477
+ const depth = dir.depth + 1;
478
+ if (depth >= limits.maxDepth) {
479
+ diagnostics.add('LIMIT_DEPTH', `directory is at the maximum depth of ${limits.maxDepth}; not entered.`, rel);
480
+ continue;
481
+ }
482
+ let identity;
483
+ try {
484
+ identity = fs.lstat(join(projectRoot, rel));
485
+ }
486
+ catch (err) {
487
+ diagnostics.add('DIR_VANISHED', `directory disappeared during the walk (${errno(err)}); the tree is being modified.`, rel);
488
+ continue;
489
+ }
490
+ if (!identity.isDirectory()) {
491
+ diagnostics.add('DIR_CHANGED', 'entry listed as a directory is no longer one; not entered.', rel);
492
+ continue;
493
+ }
494
+ if (identity.dev !== rootIdentity.dev) {
495
+ diagnostics.add('MOUNT_SKIPPED', 'directory is on another file system; not entered.', rel);
496
+ continue;
497
+ }
498
+ queue.push({ rel, depth, identity });
499
+ }
500
+ }
501
+ entries.sort((a, b) => compareUnits(a.path, b.path));
502
+ return {
503
+ completeness: diagnostics.affectsCompleteness() ? 'PARTIAL' : 'COMPLETE',
504
+ reproducible: diagnostics.isStable(),
505
+ limits,
506
+ stats,
507
+ entries,
508
+ diagnostics: diagnostics.toSortedList(),
509
+ };
510
+ }
@@ -156,7 +156,7 @@ export declare class RetentionRefusedError extends DurableError {
156
156
  export type PruneCorruptReason = 'register' | 'gap' | 'unknown-artifact' | 'commit-audit' | 'multiple-commit' | 'history' | 'task-dir-missing' | 'tombstone-without-commit' | 'legacy-tombstone-unmigrated';
157
157
  /**
158
158
  * The persisted prune decision register of a task is corrupt, or the task directory is missing, or it is an
159
- * unmigrated legacy tombstone. Fail closed: nothing is deleted and nobody is cancelled; an operator decides.
159
+ * unmigrated legacy tombstone. Fail closed: the refusal deletes no task data; an operator decides.
160
160
  * Never mapped to `TaskOrphanedError`, `RetentionRefusedError` or a quarantine, and never retryable.
161
161
  * `published` is true when a write the caller made is already visible (the outcome of that write is unknown).
162
162
  */
@@ -166,8 +166,12 @@ export declare class PruneDecisionCorruptError extends DurableError {
166
166
  readonly file: string | null;
167
167
  readonly attempt: number | null;
168
168
  readonly published: boolean;
169
+ /** Why the register was not trusted, when the reason alone does not say (e.g. which datum contradicted a commit). */
170
+ readonly detail: string | null;
169
171
  readonly retryable = false;
170
- constructor(taskId: string, reason: PruneCorruptReason, file?: string | null, attempt?: number | null, published?: boolean);
172
+ constructor(taskId: string, reason: PruneCorruptReason, file?: string | null, attempt?: number | null, published?: boolean,
173
+ /** Why the register was not trusted, when the reason alone does not say (e.g. which datum contradicted a commit). */
174
+ detail?: string | null);
171
175
  }
172
176
  /** The attempt number would exceed `MAX_PRUNE_ATTEMPTS`. A liveness limit: numbers are never reused or reset. */
173
177
  export declare class PruneAttemptLimitError extends DurableError {
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/durable/errors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/durable/errors.ts"],"names":[],"mappings":"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"}
@@ -270,7 +270,7 @@ export class RetentionRefusedError extends DurableError {
270
270
  }
271
271
  /**
272
272
  * The persisted prune decision register of a task is corrupt, or the task directory is missing, or it is an
273
- * unmigrated legacy tombstone. Fail closed: nothing is deleted and nobody is cancelled; an operator decides.
273
+ * unmigrated legacy tombstone. Fail closed: the refusal deletes no task data; an operator decides.
274
274
  * Never mapped to `TaskOrphanedError`, `RetentionRefusedError` or a quarantine, and never retryable.
275
275
  * `published` is true when a write the caller made is already visible (the outcome of that write is unknown).
276
276
  */
@@ -280,14 +280,20 @@ export class PruneDecisionCorruptError extends DurableError {
280
280
  file;
281
281
  attempt;
282
282
  published;
283
+ detail;
283
284
  retryable = false;
284
- constructor(taskId, reason, file = null, attempt = null, published = false) {
285
- super('PRUNE_DECISION_CORRUPT', `the prune decision register of task "${taskId}" cannot be trusted (${reason}${file ? `: ${file}` : ''}); nothing was deleted or cancelled.`);
285
+ constructor(taskId, reason, file = null, attempt = null, published = false,
286
+ /** Why the register was not trusted, when the reason alone does not say (e.g. which datum contradicted a commit). */
287
+ detail = null) {
288
+ super('PRUNE_DECISION_CORRUPT', `the prune decision register of task "${taskId}" cannot be trusted (${reason}${file ? `: ${file}` : ''}${detail ? `; ${detail}` : ''}); ${published
289
+ ? 'this call had already made a write visible and does not take it back (a compaction may also have removed loose copies of the events it packed); another process may have changed the task too.'
290
+ : 'this call removed no task data, but it may have recorded a prune-register entry; another process may have changed the task.'}`);
286
291
  this.taskId = taskId;
287
292
  this.reason = reason;
288
293
  this.file = file;
289
294
  this.attempt = attempt;
290
295
  this.published = published;
296
+ this.detail = detail;
291
297
  this.name = 'PruneDecisionCorruptError';
292
298
  }
293
299
  }
@@ -160,6 +160,27 @@ export declare class FsEventStore implements EventStore {
160
160
  }): Promise<{
161
161
  removedFiles: number;
162
162
  }>;
163
+ /**
164
+ * The events (and covered segment lines) still on disk with `seq <= upTo`, each verified on its own; no gap is an error,
165
+ * because a roll-forward that was interrupted leaves gaps. A segment wins over a loose copy of the same slot (the reader's
166
+ * rule). Anything that cannot be read safely or does not verify throws: the audit then refuses instead of guessing.
167
+ */
168
+ private survivingEvents;
169
+ /**
170
+ * O-1: a committed register is not self-proving (its checksum is unkeyed), so the data still on disk must not contradict
171
+ * it before anything is unlinked. See `committedProblem` for what a partly removed log can and cannot prove. Reads only.
172
+ *
173
+ * I-1: the data is read FIRST and `tombstone.json` AFTER it. The roll-forward publishes the tombstone before its first
174
+ * unlink and nothing ever removes it, so a tombstone that is still absent after the data was read proves that no unlink
175
+ * had begun when the data was read (it was absent at every earlier moment too): a gap in the data is then not a removal
176
+ * but a torn observation or real damage. The loose files are read before the segments are listed (see `survivingEvents`), so a
177
+ * compaction that moves events into a segment meanwhile does not tear the observation. Read the
178
+ * other way round, a concurrent pruner that publishes the tombstone and removes events between the two reads is taken
179
+ * for damage. A gap seen without a tombstone is still looked at again a few times before it is refused (a defence in depth,
180
+ * not what F-1 relies on). No lock: a pruner that races this audit only ever turns the verdict
181
+ * from "the whole log must be there" into "a part may be gone", and the roll-forward still checks the tombstone it finds.
182
+ */
183
+ private auditCommitted;
163
184
  /**
164
185
  * Prune cleanup (class C, section 30.3): only for a verified, consistent `COMMITTED`. Publishes `tombstone.json` from the
165
186
  * commit, then removes the data of the task. It never touches the register, `tombstone.json` or the task directory,
@@ -1 +1 @@
1
- {"version":3,"file":"fs-store.d.ts","sourceRoot":"","sources":["../../src/durable/fs-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fs-store.d.ts","sourceRoot":"","sources":["../../src/durable/fs-store.ts"],"names":[],"mappings":"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"}