@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.
- package/dist/conduit/conduit-client.d.ts.map +1 -1
- package/dist/conduit/conduit-client.js +10 -2
- package/dist/conduit/conduit-client.js.map +1 -1
- package/dist/dispatch/mvi-projection.d.ts +38 -0
- package/dist/dispatch/mvi-projection.d.ts.map +1 -1
- package/dist/dispatch/mvi-projection.js +189 -11
- package/dist/dispatch/mvi-projection.js.map +1 -1
- package/dist/docs/export-document.js +41 -3
- package/dist/docs/export-document.js.map +2 -2
- package/dist/doctor/acceptance-drift.d.ts +258 -0
- package/dist/doctor/acceptance-drift.d.ts.map +1 -0
- package/dist/doctor/acceptance-drift.js +366 -0
- package/dist/doctor/acceptance-drift.js.map +1 -0
- package/dist/doctor/index.d.ts +4 -0
- package/dist/doctor/index.d.ts.map +1 -1
- package/dist/doctor/index.js +2 -0
- package/dist/doctor/index.js.map +1 -1
- package/dist/doctor/legacy-reaper.d.ts +105 -0
- package/dist/doctor/legacy-reaper.d.ts.map +1 -0
- package/dist/doctor/legacy-reaper.js +151 -0
- package/dist/doctor/legacy-reaper.js.map +1 -0
- package/dist/doctor/malformed-task-ids.d.ts +111 -0
- package/dist/doctor/malformed-task-ids.d.ts.map +1 -0
- package/dist/doctor/malformed-task-ids.js +139 -0
- package/dist/doctor/malformed-task-ids.js.map +1 -0
- package/dist/doctor/nexus-schema-residency.d.ts +115 -0
- package/dist/doctor/nexus-schema-residency.d.ts.map +1 -0
- package/dist/doctor/nexus-schema-residency.js +178 -0
- package/dist/doctor/nexus-schema-residency.js.map +1 -0
- package/dist/error-registry.d.ts.map +1 -1
- package/dist/error-registry.js +18 -0
- package/dist/error-registry.js.map +1 -1
- package/dist/internal.d.ts +1 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +1 -0
- package/dist/internal.js.map +1 -1
- package/dist/llm/ai-sdk-warnings.d.ts +55 -0
- package/dist/llm/ai-sdk-warnings.d.ts.map +1 -0
- package/dist/llm/ai-sdk-warnings.js +83 -0
- package/dist/llm/ai-sdk-warnings.js.map +1 -0
- package/dist/llm/model-runner.d.ts +0 -8
- package/dist/llm/model-runner.d.ts.map +1 -1
- package/dist/llm/model-runner.js +8 -0
- package/dist/llm/model-runner.js.map +1 -1
- package/dist/llm/plugin-facade.js +73 -8
- package/dist/llm/plugin-facade.js.map +3 -3
- package/dist/memory/embedding-queue.d.ts +12 -0
- package/dist/memory/embedding-queue.d.ts.map +1 -1
- package/dist/memory/embedding-queue.js +39 -5
- package/dist/memory/embedding-queue.js.map +1 -1
- package/dist/orchestrate/worktree-complete.d.ts.map +1 -1
- package/dist/orchestrate/worktree-complete.js +26 -0
- package/dist/orchestrate/worktree-complete.js.map +1 -1
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +25 -0
- package/dist/output.js.map +1 -1
- package/dist/release/pr-evidence.d.ts +13 -0
- package/dist/release/pr-evidence.d.ts.map +1 -1
- package/dist/release/pr-evidence.js +54 -1
- package/dist/release/pr-evidence.js.map +1 -1
- package/dist/render/session/briefing.d.ts.map +1 -1
- package/dist/render/session/briefing.js +9 -0
- package/dist/render/session/briefing.js.map +1 -1
- package/dist/selfimprove/fix-gen.js +73 -8
- package/dist/selfimprove/fix-gen.js.map +3 -3
- package/dist/sessions/briefing.d.ts +13 -0
- package/dist/sessions/briefing.d.ts.map +1 -1
- package/dist/sessions/briefing.js +64 -7
- package/dist/sessions/briefing.js.map +1 -1
- package/dist/sessions/handoff.d.ts +32 -4
- package/dist/sessions/handoff.d.ts.map +1 -1
- package/dist/sessions/handoff.js +7 -7
- package/dist/sessions/handoff.js.map +1 -1
- package/dist/shutdown-deadline.d.ts +144 -0
- package/dist/shutdown-deadline.d.ts.map +1 -0
- package/dist/shutdown-deadline.js +187 -0
- package/dist/shutdown-deadline.js.map +1 -0
- package/dist/shutdown.d.ts +5 -2
- package/dist/shutdown.d.ts.map +1 -1
- package/dist/shutdown.js +19 -14
- package/dist/shutdown.js.map +1 -1
- package/dist/spawn/branch-lock.d.ts.map +1 -1
- package/dist/spawn/branch-lock.js +33 -0
- package/dist/spawn/branch-lock.js.map +1 -1
- package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
- package/dist/store/sqlite-data-accessor.js +14 -0
- package/dist/store/sqlite-data-accessor.js.map +1 -1
- package/dist/store/tasks-sqlite.d.ts.map +1 -1
- package/dist/store/tasks-sqlite.js +16 -1
- package/dist/store/tasks-sqlite.js.map +1 -1
- package/dist/tasks/ac-immutability.d.ts.map +1 -1
- package/dist/tasks/ac-immutability.js +36 -0
- package/dist/tasks/ac-immutability.js.map +1 -1
- package/dist/tasks/add.d.ts +18 -0
- package/dist/tasks/add.d.ts.map +1 -1
- package/dist/tasks/add.js +28 -5
- package/dist/tasks/add.js.map +1 -1
- package/dist/tasks/axis-filters.d.ts +53 -0
- package/dist/tasks/axis-filters.d.ts.map +1 -0
- package/dist/tasks/axis-filters.js +77 -0
- package/dist/tasks/axis-filters.js.map +1 -0
- package/dist/tasks/complete.d.ts.map +1 -1
- package/dist/tasks/complete.js +10 -1
- package/dist/tasks/complete.js.map +1 -1
- package/dist/tasks/duplicate-detector.d.ts +67 -14
- package/dist/tasks/duplicate-detector.d.ts.map +1 -1
- package/dist/tasks/duplicate-detector.js +197 -54
- package/dist/tasks/duplicate-detector.js.map +1 -1
- package/dist/tasks/evidence.d.ts +139 -0
- package/dist/tasks/evidence.d.ts.map +1 -1
- package/dist/tasks/evidence.js +294 -25
- package/dist/tasks/evidence.js.map +1 -1
- package/dist/tasks/find.d.ts.map +1 -1
- package/dist/tasks/find.js +9 -2
- package/dist/tasks/find.js.map +1 -1
- package/dist/tasks/gate-runner.d.ts.map +1 -1
- package/dist/tasks/gate-runner.js +25 -4
- package/dist/tasks/gate-runner.js.map +1 -1
- package/dist/tasks/heavy-tool-env.d.ts +20 -0
- package/dist/tasks/heavy-tool-env.d.ts.map +1 -1
- package/dist/tasks/heavy-tool-env.js +74 -4
- package/dist/tasks/heavy-tool-env.js.map +1 -1
- package/dist/tasks/heavy-tool-limit.d.ts +134 -0
- package/dist/tasks/heavy-tool-limit.d.ts.map +1 -0
- package/dist/tasks/heavy-tool-limit.js +196 -0
- package/dist/tasks/heavy-tool-limit.js.map +1 -0
- package/dist/tasks/index.d.ts +1 -1
- package/dist/tasks/index.d.ts.map +1 -1
- package/dist/tasks/index.js +1 -1
- package/dist/tasks/index.js.map +1 -1
- package/dist/tasks/infer-add-params.d.ts +28 -0
- package/dist/tasks/infer-add-params.d.ts.map +1 -1
- package/dist/tasks/infer-add-params.js +96 -6
- package/dist/tasks/infer-add-params.js.map +1 -1
- package/dist/tasks/list.d.ts +30 -1
- package/dist/tasks/list.d.ts.map +1 -1
- package/dist/tasks/list.js +14 -0
- package/dist/tasks/list.js.map +1 -1
- package/dist/tasks/ops.d.ts +4 -0
- package/dist/tasks/ops.d.ts.map +1 -1
- package/dist/tasks/ops.js +2 -0
- package/dist/tasks/ops.js.map +1 -1
- package/dist/tasks/session-scope.d.ts +51 -4
- package/dist/tasks/session-scope.d.ts.map +1 -1
- package/dist/tasks/session-scope.js +68 -10
- package/dist/tasks/session-scope.js.map +1 -1
- package/dist/tasks/tool-cache.d.ts +116 -9
- package/dist/tasks/tool-cache.d.ts.map +1 -1
- package/dist/tasks/tool-cache.js +127 -16
- package/dist/tasks/tool-cache.js.map +1 -1
- package/dist/tasks/tool-semaphore.d.ts +91 -0
- package/dist/tasks/tool-semaphore.d.ts.map +1 -1
- package/dist/tasks/tool-semaphore.js +203 -14
- package/dist/tasks/tool-semaphore.js.map +1 -1
- package/dist/validation/doctor/checks.d.ts +64 -0
- package/dist/validation/doctor/checks.d.ts.map +1 -1
- package/dist/validation/doctor/checks.js +249 -0
- package/dist/validation/doctor/checks.js.map +1 -1
- package/dist/validation/engine-ops.d.ts.map +1 -1
- package/dist/validation/engine-ops.js +41 -5
- package/dist/validation/engine-ops.js.map +1 -1
- package/package.json +13 -13
- package/templates/CLEO-INJECTION.md +28 -44
- package/dist/backfill/adr-backfill-walker.d.ts +0 -57
- package/dist/backfill/adr-backfill-walker.d.ts.map +0 -1
- package/dist/backfill/adr-backfill-walker.js +0 -631
- package/dist/backfill/adr-backfill-walker.js.map +0 -1
- package/dist/tasks/graph-rag.d.ts +0 -49
- package/dist/tasks/graph-rag.d.ts.map +0 -1
- package/dist/tasks/graph-rag.js +0 -328
- 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
|
-
|
|
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
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
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)
|
|
334
|
-
|
|
335
|
-
|
|
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;
|
|
1
|
+
{"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../../src/validation/doctor/checks.ts"],"names":[],"mappings":"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"}
|
|
@@ -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
|
// ============================================================================
|