@cleocode/core 2026.8.8 → 2026.9.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 (171) hide show
  1. package/dist/conduit/conduit-client.d.ts.map +1 -1
  2. package/dist/conduit/conduit-client.js +10 -2
  3. package/dist/conduit/conduit-client.js.map +1 -1
  4. package/dist/dispatch/mvi-projection.d.ts +38 -0
  5. package/dist/dispatch/mvi-projection.d.ts.map +1 -1
  6. package/dist/dispatch/mvi-projection.js +189 -11
  7. package/dist/dispatch/mvi-projection.js.map +1 -1
  8. package/dist/docs/export-document.js +41 -3
  9. package/dist/docs/export-document.js.map +2 -2
  10. package/dist/doctor/acceptance-drift.d.ts +258 -0
  11. package/dist/doctor/acceptance-drift.d.ts.map +1 -0
  12. package/dist/doctor/acceptance-drift.js +366 -0
  13. package/dist/doctor/acceptance-drift.js.map +1 -0
  14. package/dist/doctor/index.d.ts +4 -0
  15. package/dist/doctor/index.d.ts.map +1 -1
  16. package/dist/doctor/index.js +2 -0
  17. package/dist/doctor/index.js.map +1 -1
  18. package/dist/doctor/legacy-reaper.d.ts +105 -0
  19. package/dist/doctor/legacy-reaper.d.ts.map +1 -0
  20. package/dist/doctor/legacy-reaper.js +151 -0
  21. package/dist/doctor/legacy-reaper.js.map +1 -0
  22. package/dist/doctor/malformed-task-ids.d.ts +111 -0
  23. package/dist/doctor/malformed-task-ids.d.ts.map +1 -0
  24. package/dist/doctor/malformed-task-ids.js +139 -0
  25. package/dist/doctor/malformed-task-ids.js.map +1 -0
  26. package/dist/doctor/nexus-schema-residency.d.ts +115 -0
  27. package/dist/doctor/nexus-schema-residency.d.ts.map +1 -0
  28. package/dist/doctor/nexus-schema-residency.js +178 -0
  29. package/dist/doctor/nexus-schema-residency.js.map +1 -0
  30. package/dist/error-registry.d.ts.map +1 -1
  31. package/dist/error-registry.js +18 -0
  32. package/dist/error-registry.js.map +1 -1
  33. package/dist/internal.d.ts +1 -0
  34. package/dist/internal.d.ts.map +1 -1
  35. package/dist/internal.js +1 -0
  36. package/dist/internal.js.map +1 -1
  37. package/dist/llm/ai-sdk-warnings.d.ts +55 -0
  38. package/dist/llm/ai-sdk-warnings.d.ts.map +1 -0
  39. package/dist/llm/ai-sdk-warnings.js +83 -0
  40. package/dist/llm/ai-sdk-warnings.js.map +1 -0
  41. package/dist/llm/model-runner.d.ts +0 -8
  42. package/dist/llm/model-runner.d.ts.map +1 -1
  43. package/dist/llm/model-runner.js +8 -0
  44. package/dist/llm/model-runner.js.map +1 -1
  45. package/dist/llm/plugin-facade.js +73 -8
  46. package/dist/llm/plugin-facade.js.map +3 -3
  47. package/dist/memory/embedding-queue.d.ts +12 -0
  48. package/dist/memory/embedding-queue.d.ts.map +1 -1
  49. package/dist/memory/embedding-queue.js +39 -5
  50. package/dist/memory/embedding-queue.js.map +1 -1
  51. package/dist/orchestrate/worktree-complete.d.ts.map +1 -1
  52. package/dist/orchestrate/worktree-complete.js +26 -0
  53. package/dist/orchestrate/worktree-complete.js.map +1 -1
  54. package/dist/output.d.ts.map +1 -1
  55. package/dist/output.js +25 -0
  56. package/dist/output.js.map +1 -1
  57. package/dist/release/pr-evidence.d.ts +13 -0
  58. package/dist/release/pr-evidence.d.ts.map +1 -1
  59. package/dist/release/pr-evidence.js +54 -1
  60. package/dist/release/pr-evidence.js.map +1 -1
  61. package/dist/render/session/briefing.d.ts.map +1 -1
  62. package/dist/render/session/briefing.js +9 -0
  63. package/dist/render/session/briefing.js.map +1 -1
  64. package/dist/selfimprove/fix-gen.js +73 -8
  65. package/dist/selfimprove/fix-gen.js.map +3 -3
  66. package/dist/sessions/briefing.d.ts +13 -0
  67. package/dist/sessions/briefing.d.ts.map +1 -1
  68. package/dist/sessions/briefing.js +64 -7
  69. package/dist/sessions/briefing.js.map +1 -1
  70. package/dist/sessions/handoff.d.ts +32 -4
  71. package/dist/sessions/handoff.d.ts.map +1 -1
  72. package/dist/sessions/handoff.js +7 -7
  73. package/dist/sessions/handoff.js.map +1 -1
  74. package/dist/shutdown-deadline.d.ts +144 -0
  75. package/dist/shutdown-deadline.d.ts.map +1 -0
  76. package/dist/shutdown-deadline.js +187 -0
  77. package/dist/shutdown-deadline.js.map +1 -0
  78. package/dist/shutdown.d.ts +5 -2
  79. package/dist/shutdown.d.ts.map +1 -1
  80. package/dist/shutdown.js +19 -14
  81. package/dist/shutdown.js.map +1 -1
  82. package/dist/spawn/branch-lock.d.ts.map +1 -1
  83. package/dist/spawn/branch-lock.js +33 -0
  84. package/dist/spawn/branch-lock.js.map +1 -1
  85. package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
  86. package/dist/store/sqlite-data-accessor.js +14 -0
  87. package/dist/store/sqlite-data-accessor.js.map +1 -1
  88. package/dist/store/tasks-sqlite.d.ts.map +1 -1
  89. package/dist/store/tasks-sqlite.js +16 -1
  90. package/dist/store/tasks-sqlite.js.map +1 -1
  91. package/dist/tasks/ac-immutability.d.ts.map +1 -1
  92. package/dist/tasks/ac-immutability.js +36 -0
  93. package/dist/tasks/ac-immutability.js.map +1 -1
  94. package/dist/tasks/add.d.ts +18 -0
  95. package/dist/tasks/add.d.ts.map +1 -1
  96. package/dist/tasks/add.js +28 -5
  97. package/dist/tasks/add.js.map +1 -1
  98. package/dist/tasks/axis-filters.d.ts +53 -0
  99. package/dist/tasks/axis-filters.d.ts.map +1 -0
  100. package/dist/tasks/axis-filters.js +77 -0
  101. package/dist/tasks/axis-filters.js.map +1 -0
  102. package/dist/tasks/complete.d.ts.map +1 -1
  103. package/dist/tasks/complete.js +10 -1
  104. package/dist/tasks/complete.js.map +1 -1
  105. package/dist/tasks/duplicate-detector.d.ts +67 -14
  106. package/dist/tasks/duplicate-detector.d.ts.map +1 -1
  107. package/dist/tasks/duplicate-detector.js +197 -54
  108. package/dist/tasks/duplicate-detector.js.map +1 -1
  109. package/dist/tasks/evidence.d.ts +139 -0
  110. package/dist/tasks/evidence.d.ts.map +1 -1
  111. package/dist/tasks/evidence.js +294 -25
  112. package/dist/tasks/evidence.js.map +1 -1
  113. package/dist/tasks/find.d.ts.map +1 -1
  114. package/dist/tasks/find.js +9 -2
  115. package/dist/tasks/find.js.map +1 -1
  116. package/dist/tasks/gate-runner.d.ts.map +1 -1
  117. package/dist/tasks/gate-runner.js +25 -4
  118. package/dist/tasks/gate-runner.js.map +1 -1
  119. package/dist/tasks/heavy-tool-env.d.ts +20 -0
  120. package/dist/tasks/heavy-tool-env.d.ts.map +1 -1
  121. package/dist/tasks/heavy-tool-env.js +74 -4
  122. package/dist/tasks/heavy-tool-env.js.map +1 -1
  123. package/dist/tasks/heavy-tool-limit.d.ts +134 -0
  124. package/dist/tasks/heavy-tool-limit.d.ts.map +1 -0
  125. package/dist/tasks/heavy-tool-limit.js +196 -0
  126. package/dist/tasks/heavy-tool-limit.js.map +1 -0
  127. package/dist/tasks/index.d.ts +1 -1
  128. package/dist/tasks/index.d.ts.map +1 -1
  129. package/dist/tasks/index.js +1 -1
  130. package/dist/tasks/index.js.map +1 -1
  131. package/dist/tasks/infer-add-params.d.ts +28 -0
  132. package/dist/tasks/infer-add-params.d.ts.map +1 -1
  133. package/dist/tasks/infer-add-params.js +96 -6
  134. package/dist/tasks/infer-add-params.js.map +1 -1
  135. package/dist/tasks/list.d.ts +30 -1
  136. package/dist/tasks/list.d.ts.map +1 -1
  137. package/dist/tasks/list.js +14 -0
  138. package/dist/tasks/list.js.map +1 -1
  139. package/dist/tasks/ops.d.ts +4 -0
  140. package/dist/tasks/ops.d.ts.map +1 -1
  141. package/dist/tasks/ops.js +2 -0
  142. package/dist/tasks/ops.js.map +1 -1
  143. package/dist/tasks/session-scope.d.ts +51 -4
  144. package/dist/tasks/session-scope.d.ts.map +1 -1
  145. package/dist/tasks/session-scope.js +68 -10
  146. package/dist/tasks/session-scope.js.map +1 -1
  147. package/dist/tasks/tool-cache.d.ts +116 -9
  148. package/dist/tasks/tool-cache.d.ts.map +1 -1
  149. package/dist/tasks/tool-cache.js +127 -16
  150. package/dist/tasks/tool-cache.js.map +1 -1
  151. package/dist/tasks/tool-semaphore.d.ts +91 -0
  152. package/dist/tasks/tool-semaphore.d.ts.map +1 -1
  153. package/dist/tasks/tool-semaphore.js +203 -14
  154. package/dist/tasks/tool-semaphore.js.map +1 -1
  155. package/dist/validation/doctor/checks.d.ts +64 -0
  156. package/dist/validation/doctor/checks.d.ts.map +1 -1
  157. package/dist/validation/doctor/checks.js +249 -0
  158. package/dist/validation/doctor/checks.js.map +1 -1
  159. package/dist/validation/engine-ops.d.ts.map +1 -1
  160. package/dist/validation/engine-ops.js +41 -5
  161. package/dist/validation/engine-ops.js.map +1 -1
  162. package/package.json +13 -13
  163. package/templates/CLEO-INJECTION.md +28 -44
  164. package/dist/backfill/adr-backfill-walker.d.ts +0 -57
  165. package/dist/backfill/adr-backfill-walker.d.ts.map +0 -1
  166. package/dist/backfill/adr-backfill-walker.js +0 -631
  167. package/dist/backfill/adr-backfill-walker.js.map +0 -1
  168. package/dist/tasks/graph-rag.d.ts +0 -49
  169. package/dist/tasks/graph-rag.d.ts.map +0 -1
  170. package/dist/tasks/graph-rag.js +0 -328
  171. package/dist/tasks/graph-rag.js.map +0 -1
@@ -41,12 +41,13 @@
41
41
  * @task T12091
42
42
  * @adr ADR-061
43
43
  */
44
- import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
45
- import { availableParallelism, totalmem } from 'node:os';
44
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
45
+ import { availableParallelism, hostname, totalmem } from 'node:os';
46
46
  import { join } from 'node:path';
47
47
  import lockfile from 'proper-lockfile';
48
48
  import { getCleoHome } from '../paths.js';
49
49
  import { ResourceMonitor } from '../resources/monitor.js';
50
+ import { isHeavyTool } from './heavy-tool-env.js';
50
51
  // ---------------------------------------------------------------------------
51
52
  // Concurrency-limit defaults + override resolution
52
53
  // ---------------------------------------------------------------------------
@@ -153,7 +154,12 @@ export function resolveMaxConcurrent(canonical, cpuCount, totalRamGib) {
153
154
  * and single-threaded, so they keep their static budget.
154
155
  */
155
156
  function isPressureSensitive(canonical) {
156
- return canonical === 'test' || canonical === 'build';
157
+ // Delegates rather than repeating the literal. This was the third
158
+ // independent definition of "heavy"; all three agreed by coincidence, and a
159
+ // fifth heavy tool would have needed three coordinated edits — with a missed
160
+ // one producing a SILENT asymmetry (a tool granted the long deadline and the
161
+ // worker caps but not a semaphore slot, or the reverse).
162
+ return isHeavyTool(canonical);
157
163
  }
158
164
  /**
159
165
  * Scale a static slot budget down under memory pressure (T12001 · choke-point
@@ -212,6 +218,159 @@ function hasConcurrencyOverride(canonical) {
212
218
  export function semaphoreDir(canonical) {
213
219
  return join(getCleoHome(), 'locks', `tool-${canonical}`);
214
220
  }
221
+ /**
222
+ * Path of the sidecar holder record for a slot.
223
+ *
224
+ * Deliberately a SIBLING of the lock rather than a file inside it:
225
+ * `proper-lockfile` removes its lock directory with `rmdir`, which fails if we
226
+ * have put anything inside it.
227
+ *
228
+ * @internal
229
+ * @task T12113 (gh#1222)
230
+ */
231
+ function holderPath(slotPath) {
232
+ return `${slotPath}.holder.json`;
233
+ }
234
+ /**
235
+ * Record who holds a slot. Best-effort: a failure here must never fail an
236
+ * acquire that has already succeeded, because the slot IS held at that point
237
+ * and throwing would leak it.
238
+ *
239
+ * @internal
240
+ * @task T12113 (gh#1222)
241
+ */
242
+ function writeHolder(slotPath, canonical) {
243
+ const holder = {
244
+ pid: process.pid,
245
+ host: hostname(),
246
+ acquiredAt: new Date().toISOString(),
247
+ canonical,
248
+ slot: slotPath,
249
+ };
250
+ try {
251
+ writeFileSync(holderPath(slotPath), JSON.stringify(holder), 'utf-8');
252
+ }
253
+ catch {
254
+ /* best-effort — never fail an acquire that succeeded */
255
+ }
256
+ }
257
+ /**
258
+ * Read a slot's holder record. Returns `null` when absent or unparseable —
259
+ * both mean "we cannot say who holds this", which is treated as alive.
260
+ *
261
+ * @internal
262
+ * @task T12113 (gh#1222)
263
+ */
264
+ export function readHolder(slotPath) {
265
+ try {
266
+ const parsed = JSON.parse(readFileSync(holderPath(slotPath), 'utf-8'));
267
+ if (typeof parsed.pid !== 'number' || typeof parsed.host !== 'string')
268
+ return null;
269
+ return parsed;
270
+ }
271
+ catch {
272
+ return null;
273
+ }
274
+ }
275
+ /**
276
+ * Is a slot's recorded holder still running?
277
+ *
278
+ * Fails SAFE: an unknown holder, a holder on another host, or any error is
279
+ * reported as ALIVE. Reaping a live holder's slot would let two heavy suites
280
+ * run against one bound — the exact oversubscription the semaphore exists to
281
+ * prevent — so uncertainty must never authorise a reap.
282
+ *
283
+ * @param holder - Holder record, or `null` when none could be read.
284
+ * @returns `true` when the slot must be treated as legitimately held.
285
+ *
286
+ * @task T12113 (gh#1222)
287
+ */
288
+ export function isHolderAlive(holder) {
289
+ if (!holder)
290
+ return true; // unknown — assume alive
291
+ if (holder.host !== hostname())
292
+ return true; // pid is not ours to judge
293
+ try {
294
+ process.kill(holder.pid, 0); // signal 0 = existence check, sends nothing
295
+ return true;
296
+ }
297
+ catch (err) {
298
+ // EPERM means the process exists but belongs to another user.
299
+ return err.code === 'EPERM';
300
+ }
301
+ }
302
+ /**
303
+ * Release a slot whose recorded holder is gone.
304
+ *
305
+ * Removes `proper-lockfile`'s lock directory directly — the same thing its own
306
+ * stale recovery does, but decided by process liveness instead of by a 10
307
+ * minute mtime timeout.
308
+ *
309
+ * @param slotPath - Slot lock file path.
310
+ * @returns `true` when an orphaned slot was actually reaped.
311
+ *
312
+ * @task T12113 (gh#1222)
313
+ */
314
+ export function reapSlotIfOrphaned(slotPath) {
315
+ const holder = readHolder(slotPath);
316
+ if (isHolderAlive(holder))
317
+ return false;
318
+ try {
319
+ rmSync(`${slotPath}.lock`, { recursive: true, force: true });
320
+ rmSync(holderPath(slotPath), { force: true });
321
+ return true;
322
+ }
323
+ catch {
324
+ return false;
325
+ }
326
+ }
327
+ /**
328
+ * Enumerate every slot of a canonical tool with its holder and liveness.
329
+ *
330
+ * Backs the operator-facing lock inspection surface requested in gh#1222 —
331
+ * "who is holding this, and is it even alive?" — which previously required
332
+ * reading `~/.local/share/cleo/locks/` by hand.
333
+ *
334
+ * @param canonical - Canonical tool name.
335
+ * @returns One row per existing slot file.
336
+ *
337
+ * @task T12113 (gh#1222)
338
+ */
339
+ export function listSlotHolders(canonical) {
340
+ const dir = semaphoreDir(canonical);
341
+ if (!existsSync(dir))
342
+ return [];
343
+ const rows = [];
344
+ for (let i = 0;; i++) {
345
+ const slotPath = join(dir, `slot-${i}.lock`);
346
+ if (!existsSync(slotPath))
347
+ break;
348
+ const holder = readHolder(slotPath);
349
+ rows.push({
350
+ slot: slotPath,
351
+ held: existsSync(`${slotPath}.lock`),
352
+ holder,
353
+ alive: isHolderAlive(holder),
354
+ });
355
+ }
356
+ return rows;
357
+ }
358
+ /**
359
+ * Reap every orphaned slot of a canonical tool.
360
+ *
361
+ * @param canonical - Canonical tool name.
362
+ * @returns Paths of the slots actually reaped.
363
+ *
364
+ * @task T12113 (gh#1222)
365
+ */
366
+ export function reapOrphanedSlots(canonical) {
367
+ const reaped = [];
368
+ for (const row of listSlotHolders(canonical)) {
369
+ if (row.held && !row.alive && reapSlotIfOrphaned(row.slot))
370
+ reaped.push(row.slot);
371
+ }
372
+ return reaped;
373
+ }
215
374
  function ensureSlotFiles(dir, count) {
216
375
  if (!existsSync(dir)) {
217
376
  mkdirSync(dir, { recursive: true });
@@ -301,12 +460,29 @@ export async function acquireGlobalSlot(canonical, opts = {}) {
301
460
  const path = slots[idx];
302
461
  if (!path)
303
462
  continue;
463
+ let acquired = null;
304
464
  try {
305
- const release = await lockfile.lock(path, {
306
- retries: 0,
307
- stale: staleMs,
308
- realpath: false,
309
- });
465
+ acquired = await lockfile.lock(path, { retries: 0, stale: staleMs, realpath: false });
466
+ }
467
+ catch {
468
+ // gh#1222: the slot is held — but by whom? proper-lockfile decides
469
+ // staleness from mtime, so a process that died without releasing
470
+ // holds the slot for the full staleMs (10 min) and is
471
+ // indistinguishable from a legitimately slow suite. Ask the holder
472
+ // record instead: a dead pid on this host is orphaned NOW. Fails
473
+ // safe — an unknown or remote holder is treated as alive.
474
+ if (reapSlotIfOrphaned(path)) {
475
+ try {
476
+ acquired = await lockfile.lock(path, { retries: 0, stale: staleMs, realpath: false });
477
+ }
478
+ catch {
479
+ acquired = null; // someone else won the race for the reaped slot
480
+ }
481
+ }
482
+ }
483
+ if (acquired) {
484
+ const release = acquired;
485
+ writeHolder(path, canonical);
310
486
  let released = false;
311
487
  return async () => {
312
488
  if (released)
@@ -320,19 +496,32 @@ export async function acquireGlobalSlot(canonical, opts = {}) {
320
496
  // (e.g. via stale recovery). Swallow — the post-condition
321
497
  // is "slot is free", which is true either way.
322
498
  }
499
+ try {
500
+ rmSync(`${path}.holder.json`, { force: true });
501
+ }
502
+ catch {
503
+ /* best-effort — a stale holder record is only ever advisory */
504
+ }
323
505
  };
324
506
  }
325
- catch {
326
- // slot busy; try next
327
- }
328
507
  }
329
508
  // All slots busy — sleep and retry.
330
509
  await sleep(pollMs);
331
510
  }
511
+ // gh#1222: name the holders. "Everything is busy" with no way to see WHO is
512
+ // what made an orphaned slot look like a broken semaphore.
513
+ const holders = listSlotHolders(canonical)
514
+ .filter((r) => r.held)
515
+ .map((r) => {
516
+ const h = r.holder;
517
+ if (!h)
518
+ return `${r.slot}: holder unknown`;
519
+ return `${r.slot}: pid ${h.pid} on ${h.host} since ${h.acquiredAt}${r.alive ? '' : ' (DEAD)'}`;
520
+ });
332
521
  throw new Error(`Timed out after ${timeoutMs}ms waiting for a free '${canonical}' tool slot ` +
333
- `(max ${max} concurrent). Override with CLEO_TOOL_CONCURRENCY_${canonical
334
- .toUpperCase()
335
- .replace(/-/g, '_')}=<n>.`);
522
+ `(max ${max} concurrent).` +
523
+ (holders.length > 0 ? ` Current holders — ${holders.join('; ')}.` : '') +
524
+ ` Override with CLEO_TOOL_CONCURRENCY_${canonical.toUpperCase().replace(/-/g, '_')}=<n>.`);
336
525
  }
337
526
  function sleep(ms) {
338
527
  return new Promise((r) => setTimeout(r, ms));
@@ -1 +1 @@
1
- {"version":3,"file":"tool-semaphore.js","sourceRoot":"","sources":["../../src/tasks/tool-semaphore.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tool-semaphore.js","sourceRoot":"","sources":["../../src/tasks/tool-semaphore.ts"],"names":[],"mappings":"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"}
@@ -55,6 +55,70 @@ export declare function checkCoreFilesNotIgnored(projectRoot?: string): CheckRes
55
55
  * @task T5160
56
56
  */
57
57
  export declare function checkSqliteNotTracked(projectRoot?: string): CheckResult;
58
+ /**
59
+ * Warn when a stash stack is shared by several worktrees.
60
+ *
61
+ * ## The failure this exists to stop (T12161)
62
+ *
63
+ * The stash is a property of the repository, not of the working tree. Every
64
+ * worktree sharing a `.git` sees the same stack, so `git stash pop` — which
65
+ * takes `stash@{0}` when given no argument — pops whatever another session
66
+ * pushed most recently, into YOUR tree, on YOUR branch.
67
+ *
68
+ * Measured 2026-09-12 in this repo: an agent ran `git stash push` on an
69
+ * untracked file (a no-op, so nothing was pushed), then `git stash pop`, and
70
+ * silently received an unrelated entry from a 26-deep stack belonging to
71
+ * another session's branch work. It modified a generated manifest the agent
72
+ * had never touched. It was caught before commit by a diff review, not by any
73
+ * tooling.
74
+ *
75
+ * The stack here is not transient: entries date back months, across branches
76
+ * that are long merged. A single-worktree repo has none of this exposure,
77
+ * which is why the check stays silent there rather than nagging every user
78
+ * about a normal stash.
79
+ *
80
+ * @param projectRoot - repository to inspect; defaults to the resolved root.
81
+ * @returns a warning naming the depth and the top entry, or a pass.
82
+ *
83
+ * @task T12161
84
+ */
85
+ export declare function checkSharedWorktreeStashes(projectRoot?: string): CheckResult;
86
+ /**
87
+ * Warn when a repo-LOCAL identity override is absent from recent history.
88
+ *
89
+ * ## The failure this exists to stop (T12161)
90
+ *
91
+ * `user.name` and `user.email` set at `--local` scope live in `.git/config`,
92
+ * which every worktree shares. One session setting a throwaway identity — for
93
+ * a measurement, a probe, a bisect — silently re-authors every commit made by
94
+ * every other session in every other worktree until someone notices.
95
+ *
96
+ * Measured 2026-09-12 in this repo: `user.name` was left as `compose probe
97
+ * <probe@local>` after a merge-composition experiment, and three commits from
98
+ * a different session on a different branch were authored under it. Nothing
99
+ * warned; it was found by reading `git log` for an unrelated reason.
100
+ *
101
+ * ## Why this reads `--local` and not the effective identity
102
+ *
103
+ * `git config user.email` returns the MERGED value — local, then global, then
104
+ * system. Reading that would flag a first-time contributor whose perfectly
105
+ * correct global identity simply has no commits here yet, which is noise. A
106
+ * repo-local override is different in kind: it is a deliberate act scoped to
107
+ * this repository, it is the only kind that one session can impose on another
108
+ * through the shared `.git`, and when it authored none of recent history the
109
+ * overwhelmingly likely explanation is that somebody else set it for something
110
+ * else. So the remedy is to REMOVE the override and fall back to the
111
+ * committer's own global identity — not to set another value.
112
+ *
113
+ * Gated on a shared `.git` for the same reason as the stash check: a local
114
+ * identity in a single-worktree repo affects only the person who set it.
115
+ *
116
+ * @param projectRoot - repository to inspect; defaults to the resolved root.
117
+ * @returns a warning naming the override, or a pass.
118
+ *
119
+ * @task T12161
120
+ */
121
+ export declare function checkSharedGitIdentity(projectRoot?: string): CheckResult;
58
122
  /**
59
123
  * Check if any legacy output directories still exist.
60
124
  * Delegates detection to the migration/agent-outputs utility.
@@ -1 +1 @@
1
- {"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../../src/validation/doctor/checks.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAqCH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAC;AAE5E,YAAY,EACV,WAAW,EACX,WAAW,GACZ,MAAM,0CAA0C,CAAC;AAMlD,kBAAkB;AAClB,wBAAgB,oBAAoB,CAAC,QAAQ,GAAE,MAAsB,GAAG,WAAW,CAYlF;AASD,kBAAkB;AAClB,wBAAgB,eAAe,CAAC,QAAQ,GAAE,MAAsB,GAAG,WAAW,CAyB7E;AAMD,kBAAkB;AAClB,wBAAgB,sBAAsB,CAAC,QAAQ,GAAE,MAAsB,GAAG,WAAW,CAoCpF;AAoBD,kBAAkB;AAClB,wBAAgB,0BAA0B,IAAI,WAAW,CAkDxD;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CA4DlE;AAMD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAuDpE;AAMD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAiFpE;AA+BD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAsDxE;AAMD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAuD1E;AAMD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAsDvE;AAMD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAwBzE;AAMD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CA6F1E;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAkE3E;AAMD;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CA8E9E;AAMD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAkDxE;AAMD;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,WAAW,CAoDrD;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,CAkC9C;AAMD;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,WAAW,CA4C1E;AAMD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAuBrE;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAClC,aAAa,CAAC,EAAE,MAAM,EACtB,aAAa,GAAE,GAAG,CAAC,MAAM,CAAa,GACrC,WAAW,CAoFb;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mBAAmB,CACvC,eAAe,CAAC,EAAE,MAAM,EACxB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,WAAW,CAAC,CAwCtB;AAUD;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA2DvF;AAMD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,0BAA0B,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA6C3F;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE,CA8BzF;AAMD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAOnE"}
1
+ {"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../../src/validation/doctor/checks.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAsCH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAC;AAE5E,YAAY,EACV,WAAW,EACX,WAAW,GACZ,MAAM,0CAA0C,CAAC;AAMlD,kBAAkB;AAClB,wBAAgB,oBAAoB,CAAC,QAAQ,GAAE,MAAsB,GAAG,WAAW,CAYlF;AASD,kBAAkB;AAClB,wBAAgB,eAAe,CAAC,QAAQ,GAAE,MAAsB,GAAG,WAAW,CAyB7E;AAMD,kBAAkB;AAClB,wBAAgB,sBAAsB,CAAC,QAAQ,GAAE,MAAsB,GAAG,WAAW,CAoCpF;AAoBD,kBAAkB;AAClB,wBAAgB,0BAA0B,IAAI,WAAW,CAkDxD;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CA4DlE;AAMD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAuDpE;AAMD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAiFpE;AA+BD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAsDxE;AAMD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAuD1E;AAMD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAsDvE;AA4BD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,0BAA0B,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAwE5E;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAmGxE;AAMD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAwBzE;AAMD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CA6F1E;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAkE3E;AAMD;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CA8E9E;AAMD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAkDxE;AAMD;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,WAAW,CAoDrD;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,CAkC9C;AAMD;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,WAAW,CA4C1E;AAMD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAuBrE;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAClC,aAAa,CAAC,EAAE,MAAM,EACtB,aAAa,GAAE,GAAG,CAAC,MAAM,CAAa,GACrC,WAAW,CAoFb;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mBAAmB,CACvC,eAAe,CAAC,EAAE,MAAM,EACxB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,WAAW,CAAC,CAwCtB;AAUD;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA2DvF;AAMD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,0BAA0B,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA6C3F;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE,CAiCzF;AAMD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAOnE"}
@@ -11,6 +11,7 @@ import { execFileSync } from 'node:child_process';
11
11
  import { accessSync, constants, existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
12
12
  import { homedir } from 'node:os';
13
13
  import { join } from 'node:path';
14
+ import { listRegisteredWorktrees } from '@cleocode/worktree';
14
15
  import { CORE_PROTECTED_FILES } from '../../constants.js';
15
16
  import { detectLegacyAgentOutputs } from '../../migration/agent-outputs.js';
16
17
  import { getAgentsHome, getCleoHome, getCleoTemplatesTildePath, getProjectRoot, } from '../../paths.js';
@@ -594,6 +595,251 @@ export function checkSqliteNotTracked(projectRoot) {
594
595
  }
595
596
  }
596
597
  // ============================================================================
598
+ // Check: Shared-worktree git hazards (T12161)
599
+ // ============================================================================
600
+ /**
601
+ * Worktrees that share this repository's single `.git` directory.
602
+ *
603
+ * Returns 1 for an ordinary checkout. Anything above 1 means several working
604
+ * trees — in this project, usually several concurrent agent sessions — are
605
+ * backed by ONE object store, ONE config file and ONE stash stack.
606
+ *
607
+ * @param root - repository path to inspect.
608
+ * @returns worktree count, or `null` when git could not answer.
609
+ */
610
+ function sharedWorktreeCount(root) {
611
+ // Routed through `@cleocode/worktree` rather than a raw `git worktree list`
612
+ // per D010 / T9984 — the registry is that package's surface, and it already
613
+ // owns porcelain parsing. `listRegisteredWorktrees` never throws: an
614
+ // unreadable registry yields `[]`. A real repository always has at least one
615
+ // registered worktree, so an empty list means "could not determine", which is
616
+ // `null` here and NOT "zero worktrees" — the difference decides whether the
617
+ // caller warns or stays silent.
618
+ const registered = listRegisteredWorktrees(root);
619
+ return registered.length > 0 ? registered.length : null;
620
+ }
621
+ /**
622
+ * Warn when a stash stack is shared by several worktrees.
623
+ *
624
+ * ## The failure this exists to stop (T12161)
625
+ *
626
+ * The stash is a property of the repository, not of the working tree. Every
627
+ * worktree sharing a `.git` sees the same stack, so `git stash pop` — which
628
+ * takes `stash@{0}` when given no argument — pops whatever another session
629
+ * pushed most recently, into YOUR tree, on YOUR branch.
630
+ *
631
+ * Measured 2026-09-12 in this repo: an agent ran `git stash push` on an
632
+ * untracked file (a no-op, so nothing was pushed), then `git stash pop`, and
633
+ * silently received an unrelated entry from a 26-deep stack belonging to
634
+ * another session's branch work. It modified a generated manifest the agent
635
+ * had never touched. It was caught before commit by a diff review, not by any
636
+ * tooling.
637
+ *
638
+ * The stack here is not transient: entries date back months, across branches
639
+ * that are long merged. A single-worktree repo has none of this exposure,
640
+ * which is why the check stays silent there rather than nagging every user
641
+ * about a normal stash.
642
+ *
643
+ * @param projectRoot - repository to inspect; defaults to the resolved root.
644
+ * @returns a warning naming the depth and the top entry, or a pass.
645
+ *
646
+ * @task T12161
647
+ */
648
+ export function checkSharedWorktreeStashes(projectRoot) {
649
+ const root = getProjectRoot(projectRoot);
650
+ const id = 'shared_worktree_stashes';
651
+ if (!existsSync(join(root, '.git'))) {
652
+ return {
653
+ id,
654
+ category: 'configuration',
655
+ status: 'info',
656
+ message: 'Not a git repository (skipping shared-stash check)',
657
+ details: { isGitRepo: false },
658
+ fix: null,
659
+ };
660
+ }
661
+ const worktrees = sharedWorktreeCount(root);
662
+ let entries;
663
+ try {
664
+ entries = execFileSync('git', ['stash', 'list', '--pretty=%H %gd %gs'], {
665
+ cwd: root,
666
+ encoding: 'utf-8',
667
+ stdio: ['ignore', 'pipe', 'ignore'],
668
+ })
669
+ .split('\n')
670
+ .filter((l) => l.trim().length > 0);
671
+ }
672
+ catch {
673
+ return {
674
+ id,
675
+ category: 'configuration',
676
+ status: 'info',
677
+ message: 'Could not read the stash list (skipping shared-stash check)',
678
+ details: { worktrees },
679
+ fix: null,
680
+ };
681
+ }
682
+ // A stash in a single-worktree repo is ordinary and private. The hazard is
683
+ // specifically that another tree can pop it out from under you.
684
+ if (entries.length === 0 || worktrees === null || worktrees < 2) {
685
+ return {
686
+ id,
687
+ category: 'configuration',
688
+ status: 'passed',
689
+ message: entries.length === 0
690
+ ? 'Stash stack is empty'
691
+ : `${entries.length} stash entr${entries.length === 1 ? 'y' : 'ies'}, single worktree — not shared`,
692
+ details: { stashCount: entries.length, worktrees },
693
+ fix: null,
694
+ };
695
+ }
696
+ return {
697
+ id,
698
+ category: 'configuration',
699
+ status: 'warning',
700
+ message: `${entries.length} stash entries are shared by ${worktrees} worktrees — ` +
701
+ "a bare `git stash pop` here takes another session's work, not yours",
702
+ details: {
703
+ stashCount: entries.length,
704
+ worktrees,
705
+ // SHA first, deliberately. `stash@{n}` is a POSITION, not an identity:
706
+ // dropping any entry renumbers every one below it, so an index cited in a
707
+ // report can name a different stash by the time anyone reads it. Observed
708
+ // 2026-09-12: one stash referred to as `stash@{2}` and then `stash@{1}`
709
+ // inside a single session. The SHA is stable and `git stash show <sha>`
710
+ // accepts it.
711
+ topEntry: entries[0] ?? null,
712
+ },
713
+ fix: 'Never use a bare `git stash pop` in this repo. Run `git stash list`, identify your own entry, and apply it explicitly with `git stash apply stash@{N}`.',
714
+ };
715
+ }
716
+ /**
717
+ * Warn when a repo-LOCAL identity override is absent from recent history.
718
+ *
719
+ * ## The failure this exists to stop (T12161)
720
+ *
721
+ * `user.name` and `user.email` set at `--local` scope live in `.git/config`,
722
+ * which every worktree shares. One session setting a throwaway identity — for
723
+ * a measurement, a probe, a bisect — silently re-authors every commit made by
724
+ * every other session in every other worktree until someone notices.
725
+ *
726
+ * Measured 2026-09-12 in this repo: `user.name` was left as `compose probe
727
+ * <probe@local>` after a merge-composition experiment, and three commits from
728
+ * a different session on a different branch were authored under it. Nothing
729
+ * warned; it was found by reading `git log` for an unrelated reason.
730
+ *
731
+ * ## Why this reads `--local` and not the effective identity
732
+ *
733
+ * `git config user.email` returns the MERGED value — local, then global, then
734
+ * system. Reading that would flag a first-time contributor whose perfectly
735
+ * correct global identity simply has no commits here yet, which is noise. A
736
+ * repo-local override is different in kind: it is a deliberate act scoped to
737
+ * this repository, it is the only kind that one session can impose on another
738
+ * through the shared `.git`, and when it authored none of recent history the
739
+ * overwhelmingly likely explanation is that somebody else set it for something
740
+ * else. So the remedy is to REMOVE the override and fall back to the
741
+ * committer's own global identity — not to set another value.
742
+ *
743
+ * Gated on a shared `.git` for the same reason as the stash check: a local
744
+ * identity in a single-worktree repo affects only the person who set it.
745
+ *
746
+ * @param projectRoot - repository to inspect; defaults to the resolved root.
747
+ * @returns a warning naming the override, or a pass.
748
+ *
749
+ * @task T12161
750
+ */
751
+ export function checkSharedGitIdentity(projectRoot) {
752
+ const root = getProjectRoot(projectRoot);
753
+ const id = 'shared_git_identity';
754
+ if (!existsSync(join(root, '.git'))) {
755
+ return {
756
+ id,
757
+ category: 'configuration',
758
+ status: 'info',
759
+ message: 'Not a git repository (skipping shared-identity check)',
760
+ details: { isGitRepo: false },
761
+ fix: null,
762
+ };
763
+ }
764
+ const worktrees = sharedWorktreeCount(root);
765
+ if (worktrees === null || worktrees < 2) {
766
+ return {
767
+ id,
768
+ category: 'configuration',
769
+ status: 'passed',
770
+ message: 'Single worktree — git identity is not shared',
771
+ details: { worktrees },
772
+ fix: null,
773
+ };
774
+ }
775
+ const gitValue = (args) => {
776
+ try {
777
+ const out = execFileSync('git', [...args], {
778
+ cwd: root,
779
+ encoding: 'utf-8',
780
+ stdio: ['ignore', 'pipe', 'ignore'],
781
+ }).trim();
782
+ return out.length > 0 ? out : null;
783
+ }
784
+ catch {
785
+ return null;
786
+ }
787
+ };
788
+ const localEmail = gitValue(['config', '--local', 'user.email']);
789
+ // No repo-local override: whatever identity is in play came from the
790
+ // committer's own global config and is none of this check's business.
791
+ if (localEmail === null) {
792
+ return {
793
+ id,
794
+ category: 'configuration',
795
+ status: 'passed',
796
+ message: 'No repo-local git identity override — each session uses its own global identity',
797
+ details: { worktrees, localOverride: null },
798
+ fix: null,
799
+ };
800
+ }
801
+ const authors = (gitValue(['log', '-50', '--format=%ae']) ?? '')
802
+ .split('\n')
803
+ .filter((l) => l.trim().length > 0);
804
+ // No history to compare against proves nothing either way.
805
+ if (authors.length === 0) {
806
+ return {
807
+ id,
808
+ category: 'configuration',
809
+ status: 'passed',
810
+ message: 'No commit history to compare the local git identity against',
811
+ details: { worktrees, localOverride: localEmail },
812
+ fix: null,
813
+ };
814
+ }
815
+ if (authors.includes(localEmail)) {
816
+ return {
817
+ id,
818
+ category: 'configuration',
819
+ status: 'passed',
820
+ message: `Repo-local git identity (${localEmail}) appears in recent history`,
821
+ details: { worktrees, localOverride: localEmail, sampled: authors.length },
822
+ fix: null,
823
+ };
824
+ }
825
+ const mostRecent = authors[0] ?? '(unknown)';
826
+ return {
827
+ id,
828
+ category: 'configuration',
829
+ status: 'warning',
830
+ message: `Repo-local git identity "${localEmail}" authored none of the last ${authors.length} ` +
831
+ `commits, and this .git is shared by ${worktrees} worktrees — every session ` +
832
+ 'committing right now is attributed to it',
833
+ details: {
834
+ worktrees,
835
+ localOverride: localEmail,
836
+ sampled: authors.length,
837
+ mostRecentHistoricalAuthor: mostRecent,
838
+ },
839
+ fix: 'If this override is left over from another session, remove it so each session uses its own identity: git config --local --unset user.email && git config --local --unset user.name',
840
+ };
841
+ }
842
+ // ============================================================================
597
843
  // Check: Legacy agent-outputs path
598
844
  // ============================================================================
599
845
  /**
@@ -1439,6 +1685,9 @@ export function runAllGlobalChecks(cleoHome, projectRoot) {
1439
1685
  checkNoLocalSchemas(projectRoot),
1440
1686
  // Orphan worktrees audit (T9043)
1441
1687
  auditOrphanWorktrees(),
1688
+ // Shared-worktree git hazards (T12161)
1689
+ checkSharedWorktreeStashes(projectRoot),
1690
+ checkSharedGitIdentity(projectRoot),
1442
1691
  ];
1443
1692
  }
1444
1693
  // ============================================================================