@cleocode/core 2026.6.14 → 2026.6.15

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 (114) hide show
  1. package/dist/check/pr-gate.d.ts +6 -2
  2. package/dist/check/pr-gate.d.ts.map +1 -1
  3. package/dist/check/pr-gate.js +14 -32
  4. package/dist/check/pr-gate.js.map +1 -1
  5. package/dist/config/config-repair.d.ts +70 -0
  6. package/dist/config/config-repair.d.ts.map +1 -0
  7. package/dist/config/config-repair.js +248 -0
  8. package/dist/config/config-repair.js.map +1 -0
  9. package/dist/config/registry.d.ts.map +1 -1
  10. package/dist/config/registry.js +4 -4
  11. package/dist/config/registry.js.map +1 -1
  12. package/dist/config.d.ts.map +1 -1
  13. package/dist/config.js +11 -10
  14. package/dist/config.js.map +1 -1
  15. package/dist/docs/export-document.js +17 -16
  16. package/dist/docs/export-document.js.map +2 -2
  17. package/dist/gc/cleanup.d.ts +23 -8
  18. package/dist/gc/cleanup.d.ts.map +1 -1
  19. package/dist/gc/cleanup.js +287 -22
  20. package/dist/gc/cleanup.js.map +1 -1
  21. package/dist/llm/cli-ops.d.ts +16 -0
  22. package/dist/llm/cli-ops.d.ts.map +1 -1
  23. package/dist/llm/cli-ops.js +32 -5
  24. package/dist/llm/cli-ops.js.map +1 -1
  25. package/dist/llm/cross-provider-selector.d.ts +249 -0
  26. package/dist/llm/cross-provider-selector.d.ts.map +1 -0
  27. package/dist/llm/cross-provider-selector.js +572 -0
  28. package/dist/llm/cross-provider-selector.js.map +1 -0
  29. package/dist/llm/index.d.ts +2 -0
  30. package/dist/llm/index.d.ts.map +1 -1
  31. package/dist/llm/index.js +1 -0
  32. package/dist/llm/index.js.map +1 -1
  33. package/dist/llm/local-model-fit.d.ts +260 -0
  34. package/dist/llm/local-model-fit.d.ts.map +1 -0
  35. package/dist/llm/local-model-fit.js +563 -0
  36. package/dist/llm/local-model-fit.js.map +1 -0
  37. package/dist/llm/plugin-facade.js +761 -230
  38. package/dist/llm/plugin-facade.js.map +3 -3
  39. package/dist/llm/provider-registry/builtin/ollama.d.ts +18 -0
  40. package/dist/llm/provider-registry/builtin/ollama.d.ts.map +1 -1
  41. package/dist/llm/provider-registry/builtin/ollama.js +20 -2
  42. package/dist/llm/provider-registry/builtin/ollama.js.map +1 -1
  43. package/dist/llm/role-resolver.d.ts.map +1 -1
  44. package/dist/llm/role-resolver.js +45 -10
  45. package/dist/llm/role-resolver.js.map +1 -1
  46. package/dist/llm/transports/codex-responses.d.ts +111 -88
  47. package/dist/llm/transports/codex-responses.d.ts.map +1 -1
  48. package/dist/llm/transports/codex-responses.js +456 -258
  49. package/dist/llm/transports/codex-responses.js.map +1 -1
  50. package/dist/release/index.d.ts +2 -2
  51. package/dist/release/index.d.ts.map +1 -1
  52. package/dist/release/index.js +1 -1
  53. package/dist/release/index.js.map +1 -1
  54. package/dist/release/reconcile.d.ts +97 -0
  55. package/dist/release/reconcile.d.ts.map +1 -1
  56. package/dist/release/reconcile.js +412 -5
  57. package/dist/release/reconcile.js.map +1 -1
  58. package/dist/resources/backend.d.ts +155 -0
  59. package/dist/resources/backend.d.ts.map +1 -0
  60. package/dist/resources/backend.js +23 -0
  61. package/dist/resources/backend.js.map +1 -0
  62. package/dist/resources/linux-backend.d.ts +167 -0
  63. package/dist/resources/linux-backend.d.ts.map +1 -0
  64. package/dist/resources/linux-backend.js +259 -0
  65. package/dist/resources/linux-backend.js.map +1 -0
  66. package/dist/resources/monitor.d.ts +230 -0
  67. package/dist/resources/monitor.d.ts.map +1 -0
  68. package/dist/resources/monitor.js +255 -0
  69. package/dist/resources/monitor.js.map +1 -0
  70. package/dist/resources/spawn-wrapper.d.ts +265 -0
  71. package/dist/resources/spawn-wrapper.d.ts.map +1 -0
  72. package/dist/resources/spawn-wrapper.js +304 -0
  73. package/dist/resources/spawn-wrapper.js.map +1 -0
  74. package/dist/selfimprove/budget.d.ts +11 -2
  75. package/dist/selfimprove/budget.d.ts.map +1 -1
  76. package/dist/selfimprove/budget.js +11 -2
  77. package/dist/selfimprove/budget.js.map +1 -1
  78. package/dist/selfimprove/fix-gen.d.ts +229 -0
  79. package/dist/selfimprove/fix-gen.d.ts.map +1 -0
  80. package/dist/selfimprove/fix-gen.js +266 -0
  81. package/dist/selfimprove/fix-gen.js.map +1 -0
  82. package/dist/selfimprove/run-loop.d.ts +44 -4
  83. package/dist/selfimprove/run-loop.d.ts.map +1 -1
  84. package/dist/selfimprove/run-loop.js +73 -6
  85. package/dist/selfimprove/run-loop.js.map +1 -1
  86. package/dist/sentient/cross-project-hygiene.d.ts +11 -2
  87. package/dist/sentient/cross-project-hygiene.d.ts.map +1 -1
  88. package/dist/sentient/cross-project-hygiene.js +73 -10
  89. package/dist/sentient/cross-project-hygiene.js.map +1 -1
  90. package/dist/sentient/daemon.d.ts.map +1 -1
  91. package/dist/sentient/daemon.js +7 -2
  92. package/dist/sentient/daemon.js.map +1 -1
  93. package/dist/sentient/worktree-dispatch.d.ts.map +1 -1
  94. package/dist/sentient/worktree-dispatch.js +8 -1
  95. package/dist/sentient/worktree-dispatch.js.map +1 -1
  96. package/dist/spawn/branch-lock.d.ts.map +1 -1
  97. package/dist/spawn/branch-lock.js +7 -1
  98. package/dist/spawn/branch-lock.js.map +1 -1
  99. package/dist/store/attachment-repair.d.ts +110 -0
  100. package/dist/store/attachment-repair.d.ts.map +1 -0
  101. package/dist/store/attachment-repair.js +326 -0
  102. package/dist/store/attachment-repair.js.map +1 -0
  103. package/dist/store/attachment-store.d.ts.map +1 -1
  104. package/dist/store/attachment-store.js +24 -7
  105. package/dist/store/attachment-store.js.map +1 -1
  106. package/dist/tasks/evidence.d.ts +34 -2
  107. package/dist/tasks/evidence.d.ts.map +1 -1
  108. package/dist/tasks/evidence.js +293 -35
  109. package/dist/tasks/evidence.js.map +1 -1
  110. package/dist/verification/verify-tools.d.ts.map +1 -1
  111. package/dist/verification/verify-tools.js +5 -6
  112. package/dist/verification/verify-tools.js.map +1 -1
  113. package/package.json +22 -12
  114. package/templates/workflows/release-prepare.yml.tmpl +48 -2
@@ -49,7 +49,11 @@ export interface CleanupResult {
49
49
  removed: number;
50
50
  /** Absolute paths that were removed (or would be removed). */
51
51
  removedPaths: string[];
52
- /** Entries that were skipped (dry-run). */
52
+ /** Number of worktrees quarantined (dirty/unpushed — preserved, not deleted). */
53
+ quarantined: number;
54
+ /** Absolute paths that were quarantined (tar archives placed in quarantine dir). */
55
+ quarantinedPaths: string[];
56
+ /** Entries that were skipped (dry-run or preserved). */
53
57
  skipped: number;
54
58
  /** Errors encountered during removal (non-fatal). */
55
59
  errors: Array<{
@@ -58,6 +62,11 @@ export interface CleanupResult {
58
62
  }>;
59
63
  /** Whether this was a dry run. */
60
64
  dryRun: boolean;
65
+ /**
66
+ * True when pruning was skipped entirely because the preserve set was empty
67
+ * while worktrees exist (fail-closed guard, T11996).
68
+ */
69
+ skippedFailClosed?: boolean;
61
70
  }
62
71
  /**
63
72
  * Options for `pruneOrphanWorktrees`.
@@ -132,18 +141,24 @@ export interface OrphanEntry {
132
141
  * Prune orphaned agent worktree directories.
133
142
  *
134
143
  * Scans `worktreesRoot` (or `worktreesRoot/<projectHash>`) for directories
135
- * whose names are NOT in `activeTaskIds` and removes them. Uses `rmSync`
136
- * directly because the worktrees at this point are only filesystem artefacts
137
- * — the agent has already merged its work via `completeAgentWorktreeViaMerge`.
138
- * Git worktree de-registration is attempted with `git worktree prune` at the
139
- * level of the caller (cleo gc or cleo doctor does not need a git root here;
140
- * individual worktrees have their own `.git` file redirects which become stale
141
- * and are cleaned up by `git worktree prune` in the primary repo).
144
+ * whose names are NOT in `activeTaskIds` and removes them.
145
+ *
146
+ * Safety invariants (T11996):
147
+ * - Fail-closed: if `activeTaskIds` is empty AND worktrees exist, skip pruning
148
+ * entirely and return `skippedFailClosed: true`. This prevents mass-deletion
149
+ * when the task store is unavailable or freshly initialised.
150
+ * - Dirty guard: worktrees with uncommitted changes are quarantined (packed
151
+ * into `.tar.gz` in `<worktreesRoot>/../quarantine/worktrees/`) instead of
152
+ * deleted. The original directory is left on disk.
153
+ * - Unpushed guard: worktrees whose branch has commits not reachable from any
154
+ * remote ref are quarantined, not deleted.
155
+ * - A worktree that is both dirty AND has unpushed commits is quarantined once.
142
156
  *
143
157
  * @param options - See `PruneOrphanWorktreesOptions`.
144
158
  * @returns Cleanup result.
145
159
  *
146
160
  * @task T9043
161
+ * @task T11996
147
162
  */
148
163
  export declare function pruneOrphanWorktrees(options: PruneOrphanWorktreesOptions): CleanupResult;
149
164
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/gc/cleanup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAkBH;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,MAAM,EAqCtC,CAAC;AAEX;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,QAAqB,CAAC;AAM1D;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,qDAAqD;IACrD,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,kCAAkC;IAClC,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;OAGG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;CAClB;AA4BD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,2BAA2B,GAAG,aAAa,CA4ExF;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,0BAA+B,GAAG,aAAa,CAsD3F;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,GAAE,MAAgC,EAC1C,OAAO,GAAE,MAAiB,GACzB,WAAW,EAAE,CA4Bf;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,EAC1B,WAAW,CAAC,EAAE,MAAM,GACnB,WAAW,EAAE,CAkDf"}
1
+ {"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/gc/cleanup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAmBH;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,MAAM,EAqCtC,CAAC;AAEX;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,QAAqB,CAAC;AAM1D;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,iFAAiF;IACjF,WAAW,EAAE,MAAM,CAAC;IACpB,oFAAoF;IACpF,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,qDAAqD;IACrD,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,kCAAkC;IAClC,MAAM,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;OAGG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;CAClB;AAwMD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,2BAA2B,GAAG,aAAa,CAwKxF;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,0BAA+B,GAAG,aAAa,CAsE3F;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,GAAE,MAAgC,EAC1C,OAAO,GAAE,MAAiB,GACzB,WAAW,EAAE,CA4Bf;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,EAC1B,WAAW,CAAC,EAAE,MAAM,GACnB,WAAW,EAAE,CAkDf"}
@@ -22,7 +22,8 @@
22
22
  *
23
23
  * @task T9043
24
24
  */
25
- import { existsSync, readdirSync, rmSync, statSync } from 'node:fs';
25
+ import { execFileSync } from 'node:child_process';
26
+ import { appendFileSync, existsSync, mkdirSync, readdirSync, rmSync, statSync } from 'node:fs';
26
27
  import { tmpdir } from 'node:os';
27
28
  import { join } from 'node:path';
28
29
  // ---------------------------------------------------------------------------
@@ -114,30 +115,200 @@ function formatAge(ms) {
114
115
  // ---------------------------------------------------------------------------
115
116
  // Public API — worktree pruning
116
117
  // ---------------------------------------------------------------------------
118
+ /**
119
+ * Check whether a worktree has uncommitted changes (dirty state).
120
+ *
121
+ * Runs `git status --porcelain` inside the worktree. A non-empty output means
122
+ * there are staged or unstaged changes (including untracked files via `-uall`).
123
+ * Returns `false` when git is unavailable or the directory is not a valid git
124
+ * worktree — treat as clean so we never block cleanup due to a git error.
125
+ *
126
+ * @param worktreePath - Absolute path to the worktree directory.
127
+ * @returns `true` when uncommitted changes are present; `false` otherwise.
128
+ *
129
+ * @task T11996
130
+ * @internal
131
+ */
132
+ function isWorktreeDirty(worktreePath) {
133
+ try {
134
+ const out = execFileSync('git', ['-C', worktreePath, 'status', '--porcelain', '-uall'], {
135
+ encoding: 'utf-8',
136
+ stdio: ['pipe', 'pipe', 'pipe'],
137
+ timeout: 10_000,
138
+ });
139
+ return out.trim().length > 0;
140
+ }
141
+ catch {
142
+ return false;
143
+ }
144
+ }
145
+ /**
146
+ * Check whether a worktree has commits that have not been pushed to any remote.
147
+ *
148
+ * Two cases are detected:
149
+ * (a) Branches with a configured upstream: commits ahead of `@{upstream}`.
150
+ * (b) Branches with NO upstream (never pushed): any commits on the branch that
151
+ * are not reachable from any remote-tracking ref.
152
+ * (c) Detached HEAD: commits not reachable from any remote-tracking ref.
153
+ *
154
+ * Returns `false` when git is unavailable or the worktree has no commits.
155
+ *
156
+ * @param worktreePath - Absolute path to the worktree directory.
157
+ * @returns `true` when unpushed commits exist; `false` otherwise.
158
+ *
159
+ * @task T11996
160
+ * @internal
161
+ */
162
+ function hasUnpushedCommits(worktreePath) {
163
+ // Case (a): branch has a tracking upstream — check ahead count
164
+ try {
165
+ const aheadStr = execFileSync('git', ['-C', worktreePath, 'rev-list', '--count', '@{upstream}..HEAD'], {
166
+ encoding: 'utf-8',
167
+ stdio: ['pipe', 'pipe', 'pipe'],
168
+ timeout: 10_000,
169
+ }).trim();
170
+ const aheadCount = Number.parseInt(aheadStr, 10);
171
+ if (!Number.isNaN(aheadCount) && aheadCount > 0)
172
+ return true;
173
+ // Upstream exists and no unpushed commits
174
+ return false;
175
+ }
176
+ catch {
177
+ // No upstream configured — fall through to case (b)/(c)
178
+ }
179
+ // Case (b)/(c): no upstream — check if HEAD is reachable from any remote ref
180
+ try {
181
+ // List all remote-tracking refs
182
+ const remoteRefsOut = execFileSync('git', ['-C', worktreePath, 'for-each-ref', '--format=%(refname)', 'refs/remotes/'], {
183
+ encoding: 'utf-8',
184
+ stdio: ['pipe', 'pipe', 'pipe'],
185
+ timeout: 10_000,
186
+ }).trim();
187
+ const remoteRefs = remoteRefsOut.split('\n').filter(Boolean);
188
+ if (remoteRefs.length === 0) {
189
+ // No remotes at all — any commit is effectively "unpushed"
190
+ try {
191
+ const headOut = execFileSync('git', ['-C', worktreePath, 'rev-parse', 'HEAD'], {
192
+ encoding: 'utf-8',
193
+ stdio: ['pipe', 'pipe', 'pipe'],
194
+ timeout: 5_000,
195
+ }).trim();
196
+ return headOut.length > 0;
197
+ }
198
+ catch {
199
+ return false;
200
+ }
201
+ }
202
+ // Check whether HEAD is reachable from the union of all remote refs
203
+ const args = ['-C', worktreePath, 'rev-list', '--count', 'HEAD', '--not', ...remoteRefs];
204
+ const countOut = execFileSync('git', args, {
205
+ encoding: 'utf-8',
206
+ stdio: ['pipe', 'pipe', 'pipe'],
207
+ timeout: 15_000,
208
+ }).trim();
209
+ const count = Number.parseInt(countOut, 10);
210
+ return !Number.isNaN(count) && count > 0;
211
+ }
212
+ catch {
213
+ return false;
214
+ }
215
+ }
216
+ /**
217
+ * Quarantine a dirty or unpushed worktree by packing it into a `.tar.gz`
218
+ * archive under `<worktreesRoot>/../quarantine/worktrees/`. The original
219
+ * directory is left intact.
220
+ *
221
+ * Writes an audit JSONL entry to `<worktreesRoot>/../quarantine/audit.jsonl`.
222
+ *
223
+ * @param worktreePath - Absolute path to the worktree directory to archive.
224
+ * @param taskId - Task ID for the entry name.
225
+ * @param quarantineDir - Absolute path to the quarantine root directory.
226
+ * @param reason - Human-readable reason (e.g. `'dirty'`, `'unpushed'`).
227
+ * @returns Absolute path to the created archive, or `null` on failure.
228
+ *
229
+ * @task T11996
230
+ * @internal
231
+ */
232
+ function quarantineWorktreeDir(worktreePath, taskId, quarantineDir, reason) {
233
+ try {
234
+ mkdirSync(quarantineDir, { recursive: true });
235
+ const ts = new Date().toISOString().replace(/[:.]/g, '-');
236
+ const archiveName = `${taskId}-${ts}.tar.gz`;
237
+ const archivePath = join(quarantineDir, archiveName);
238
+ // Use tar with --exclude to capture untracked AND ignored files.
239
+ // We deliberately do NOT exclude anything here: the quarantine must be a
240
+ // complete snapshot including .env, build artifacts, etc. (T11996 AC).
241
+ execFileSync('tar', [
242
+ '-czf',
243
+ archivePath,
244
+ // Dereference symlinks so the archive is self-contained.
245
+ '--dereference',
246
+ // Use the parent directory as CWD so the archive root is `<taskId>/`.
247
+ '-C',
248
+ join(worktreePath, '..'),
249
+ taskId,
250
+ ], {
251
+ stdio: ['pipe', 'pipe', 'pipe'],
252
+ timeout: 120_000,
253
+ });
254
+ // Write audit entry
255
+ const auditPath = join(quarantineDir, 'audit.jsonl');
256
+ const entry = JSON.stringify({
257
+ ts: new Date().toISOString(),
258
+ action: 'quarantine',
259
+ worktreePath,
260
+ taskId,
261
+ archivePath,
262
+ reason,
263
+ agentId: process.env['CLEO_AGENT_ID'] ?? 'cleo',
264
+ });
265
+ appendFileSync(auditPath, `${entry}\n`, { encoding: 'utf-8' });
266
+ return archivePath;
267
+ }
268
+ catch {
269
+ return null;
270
+ }
271
+ }
117
272
  /**
118
273
  * Prune orphaned agent worktree directories.
119
274
  *
120
275
  * Scans `worktreesRoot` (or `worktreesRoot/<projectHash>`) for directories
121
- * whose names are NOT in `activeTaskIds` and removes them. Uses `rmSync`
122
- * directly because the worktrees at this point are only filesystem artefacts
123
- * — the agent has already merged its work via `completeAgentWorktreeViaMerge`.
124
- * Git worktree de-registration is attempted with `git worktree prune` at the
125
- * level of the caller (cleo gc or cleo doctor does not need a git root here;
126
- * individual worktrees have their own `.git` file redirects which become stale
127
- * and are cleaned up by `git worktree prune` in the primary repo).
276
+ * whose names are NOT in `activeTaskIds` and removes them.
277
+ *
278
+ * Safety invariants (T11996):
279
+ * - Fail-closed: if `activeTaskIds` is empty AND worktrees exist, skip pruning
280
+ * entirely and return `skippedFailClosed: true`. This prevents mass-deletion
281
+ * when the task store is unavailable or freshly initialised.
282
+ * - Dirty guard: worktrees with uncommitted changes are quarantined (packed
283
+ * into `.tar.gz` in `<worktreesRoot>/../quarantine/worktrees/`) instead of
284
+ * deleted. The original directory is left on disk.
285
+ * - Unpushed guard: worktrees whose branch has commits not reachable from any
286
+ * remote ref are quarantined, not deleted.
287
+ * - A worktree that is both dirty AND has unpushed commits is quarantined once.
128
288
  *
129
289
  * @param options - See `PruneOrphanWorktreesOptions`.
130
290
  * @returns Cleanup result.
131
291
  *
132
292
  * @task T9043
293
+ * @task T11996
133
294
  */
134
295
  export function pruneOrphanWorktrees(options) {
135
296
  const { worktreesRoot, projectHash, activeTaskIds, dryRun = false } = options;
136
297
  const removed = [];
298
+ const quarantined = [];
137
299
  const errors = [];
138
300
  let skipped = 0;
301
+ let skippedFailClosed = false;
139
302
  if (!existsSync(worktreesRoot)) {
140
- return { removed: 0, removedPaths: [], skipped, errors, dryRun };
303
+ return {
304
+ removed: 0,
305
+ removedPaths: [],
306
+ quarantined: 0,
307
+ quarantinedPaths: [],
308
+ skipped,
309
+ errors,
310
+ dryRun,
311
+ };
141
312
  }
142
313
  // Determine which per-project directories to scan.
143
314
  let projectDirs;
@@ -151,7 +322,15 @@ export function pruneOrphanWorktrees(options) {
151
322
  entries = readdirSync(worktreesRoot);
152
323
  }
153
324
  catch {
154
- return { removed: 0, removedPaths: [], skipped, errors, dryRun };
325
+ return {
326
+ removed: 0,
327
+ removedPaths: [],
328
+ quarantined: 0,
329
+ quarantinedPaths: [],
330
+ skipped: 0,
331
+ errors,
332
+ dryRun,
333
+ };
155
334
  }
156
335
  projectDirs = entries
157
336
  .map((e) => join(worktreesRoot, e))
@@ -172,6 +351,41 @@ export function pruneOrphanWorktrees(options) {
172
351
  catch {
173
352
  continue;
174
353
  }
354
+ // T11996 Fail-closed: if preserve set is empty AND worktrees exist, skip
355
+ // this project entirely to prevent mass-deletion when the task store is
356
+ // unreadable or the DB is freshly initialised. Write an audit warning.
357
+ const existingWorktrees = taskEntries.filter((e) => {
358
+ try {
359
+ return statSync(join(projectDir, e)).isDirectory();
360
+ }
361
+ catch {
362
+ return false;
363
+ }
364
+ });
365
+ if (activeTaskIds.size === 0 && existingWorktrees.length > 0) {
366
+ // Write a structured audit warning to the quarantine audit log so the
367
+ // operator can investigate. ZERO desktop output per binding amendment 6.
368
+ try {
369
+ const quarantineDir = join(worktreesRoot, '..', 'quarantine', 'worktrees');
370
+ mkdirSync(quarantineDir, { recursive: true });
371
+ const auditPath = join(quarantineDir, '..', 'audit.jsonl');
372
+ const entry = JSON.stringify({
373
+ ts: new Date().toISOString(),
374
+ action: 'prune-skip-fail-closed',
375
+ projectDir,
376
+ existingWorktreeCount: existingWorktrees.length,
377
+ reason: 'preserve set empty while worktrees exist — skipping to prevent mass-deletion (T11996 fail-closed)',
378
+ agentId: process.env['CLEO_AGENT_ID'] ?? 'cleo',
379
+ });
380
+ appendFileSync(auditPath, `${entry}\n`, { encoding: 'utf-8' });
381
+ }
382
+ catch {
383
+ // audit is best-effort
384
+ }
385
+ skipped += existingWorktrees.length;
386
+ skippedFailClosed = true;
387
+ continue;
388
+ }
175
389
  for (const taskId of taskEntries) {
176
390
  if (activeTaskIds.has(taskId)) {
177
391
  skipped++;
@@ -188,24 +402,59 @@ export function pruneOrphanWorktrees(options) {
188
402
  skipped++;
189
403
  continue;
190
404
  }
191
- if (dryRun) {
192
- removed.push(worktreePath);
405
+ // T11996: Check dirty/unpushed state before any destructive action.
406
+ // Evaluate dirty first; only run unpushed check if clean (short-circuit).
407
+ const dirty = isWorktreeDirty(worktreePath);
408
+ const unpushed = dirty ? false : hasUnpushedCommits(worktreePath);
409
+ const shouldQuarantine = dirty || unpushed;
410
+ const quarantineReason = dirty ? 'dirty' : 'unpushed';
411
+ if (shouldQuarantine) {
412
+ if (dryRun) {
413
+ quarantined.push(worktreePath);
414
+ }
415
+ else {
416
+ const quarantineBase = join(worktreesRoot, '..', 'quarantine', 'worktrees');
417
+ const archivePath = quarantineWorktreeDir(worktreePath, taskId, quarantineBase, quarantineReason);
418
+ if (archivePath !== null) {
419
+ quarantined.push(worktreePath);
420
+ }
421
+ else {
422
+ errors.push({
423
+ path: worktreePath,
424
+ reason: 'quarantine tar failed — worktree preserved (T11996)',
425
+ });
426
+ }
427
+ }
193
428
  }
194
429
  else {
195
- try {
196
- rmSync(worktreePath, { recursive: true, force: true });
430
+ if (dryRun) {
197
431
  removed.push(worktreePath);
198
432
  }
199
- catch (err) {
200
- errors.push({
201
- path: worktreePath,
202
- reason: err instanceof Error ? err.message : String(err),
203
- });
433
+ else {
434
+ try {
435
+ rmSync(worktreePath, { recursive: true, force: true });
436
+ removed.push(worktreePath);
437
+ }
438
+ catch (err) {
439
+ errors.push({
440
+ path: worktreePath,
441
+ reason: err instanceof Error ? err.message : String(err),
442
+ });
443
+ }
204
444
  }
205
445
  }
206
446
  }
207
447
  }
208
- return { removed: removed.length, removedPaths: removed, skipped, errors, dryRun };
448
+ return {
449
+ removed: removed.length,
450
+ removedPaths: removed,
451
+ quarantined: quarantined.length,
452
+ quarantinedPaths: quarantined,
453
+ skipped,
454
+ errors,
455
+ dryRun,
456
+ ...(skippedFailClosed ? { skippedFailClosed: true } : {}),
457
+ };
209
458
  }
210
459
  // ---------------------------------------------------------------------------
211
460
  // Public API — temp dir pruning
@@ -234,7 +483,15 @@ export function pruneOrphanTempDirs(options = {}) {
234
483
  entries = readdirSync(tempDir, { withFileTypes: true });
235
484
  }
236
485
  catch {
237
- return { removed: 0, removedPaths: [], skipped, errors, dryRun };
486
+ return {
487
+ removed: 0,
488
+ removedPaths: [],
489
+ quarantined: 0,
490
+ quarantinedPaths: [],
491
+ skipped,
492
+ errors,
493
+ dryRun,
494
+ };
238
495
  }
239
496
  for (const entry of entries) {
240
497
  if (!entry.isDirectory())
@@ -273,7 +530,15 @@ export function pruneOrphanTempDirs(options = {}) {
273
530
  }
274
531
  }
275
532
  }
276
- return { removed: removed.length, removedPaths: removed, skipped, errors, dryRun };
533
+ return {
534
+ removed: removed.length,
535
+ removedPaths: removed,
536
+ quarantined: 0,
537
+ quarantinedPaths: [],
538
+ skipped,
539
+ errors,
540
+ dryRun,
541
+ };
277
542
  }
278
543
  // ---------------------------------------------------------------------------
279
544
  // Public API — audit (read-only, for cleo doctor)
@@ -1 +1 @@
1
- {"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/gc/cleanup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,8EAA8E;AAC9E,uCAAuC;AACvC,EAAE;AACF,6CAA6C;AAC7C,0EAA0E;AAC1E,yCAAyC;AACzC,0CAA0C;AAC1C,EAAE;AACF,yEAAyE;AACzE,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAsB;IACnD,iCAAiC;IACjC,uBAAuB,EAAE,8BAA8B;IACvD,cAAc,EAAE,2CAA2C;IAC3D,YAAY,EAAE,yCAAyC;IACvD,uDAAuD;IACvD,gBAAgB;IAChB,gBAAgB;IAChB,YAAY;IACZ,sBAAsB;IACtB,sBAAsB;IACtB,sBAAsB;IACtB,sBAAsB;IACtB,wBAAwB;IACxB,UAAU;IACV,qBAAqB;IACrB,wBAAwB;IACxB,oBAAoB;IACpB,sBAAsB;IACtB,sBAAsB;IACtB,wBAAwB;IACxB,iBAAiB;IACjB,gBAAgB;IAChB,oBAAoB;IACpB,oBAAoB;IACpB,uBAAuB;IACvB,aAAa;IACb,mBAAmB;IACnB,YAAY;IACZ,sBAAsB;IACtB,YAAY;IACZ,wBAAwB;IACxB,wBAAwB;IACxB,mBAAmB;IACnB,mBAAmB;IACnB,oBAAoB;IACpB,mBAAmB;CACX,CAAC;AAEX;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,UAAU;AAgGrE,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E;;;;;GAKG;AACH,SAAS,SAAS,CAAC,EAAU;IAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;IAEpC,IAAI,IAAI,GAAG,CAAC;QAAE,OAAO,GAAG,IAAI,KAAK,KAAK,GAAG,EAAE,GAAG,CAAC;IAC/C,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,GAAG,KAAK,KAAK,OAAO,GAAG,EAAE,GAAG,CAAC;IACnD,IAAI,OAAO,GAAG,CAAC;QAAE,OAAO,GAAG,OAAO,GAAG,CAAC;IACtC,OAAO,GAAG,OAAO,GAAG,CAAC;AACvB,CAAC;AAED,8EAA8E;AAC9E,gCAAgC;AAChC,8EAA8E;AAE9E;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAoC;IACvE,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAE9E,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,MAAM,GAA4C,EAAE,CAAC;IAC3D,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IACnE,CAAC;IAED,mDAAmD;IACnD,IAAI,WAAqB,CAAC;IAC1B,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;QACnD,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACzD,CAAC;SAAM,CAAC;QACN,IAAI,OAAiB,CAAC;QACtB,IAAI,CAAC;YACH,OAAO,GAAG,WAAW,CAAC,aAAa,CAAC,CAAC;QACvC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QACnE,CAAC;QACD,WAAW,GAAG,OAAO;aAClB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;aAClC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;YACZ,IAAI,CAAC;gBACH,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;YACnC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC,CAAC,CAAC;IACP,CAAC;IAED,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,IAAI,WAAqB,CAAC;QAC1B,IAAI,CAAC;YACH,WAAW,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;QACxC,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QAED,KAAK,MAAM,MAAM,IAAI,WAAW,EAAE,CAAC;YACjC,IAAI,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC9B,OAAO,EAAE,CAAC;gBACV,SAAS;YACX,CAAC;YAED,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YAC9C,IAAI,CAAC;gBACH,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;oBAC1C,OAAO,EAAE,CAAC;oBACV,SAAS;gBACX,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,EAAE,CAAC;gBACV,SAAS;YACX,CAAC;YAED,IAAI,MAAM,EAAE,CAAC;gBACX,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC;oBACH,MAAM,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;oBACvD,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBAC7B,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,CAAC,IAAI,CAAC;wBACV,IAAI,EAAE,YAAY;wBAClB,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;qBACzD,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AACrF,CAAC;AAED,8EAA8E;AAC9E,gCAAgC;AAChC,8EAA8E;AAE9E;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAsC,EAAE;IAC1E,MAAM,EAAE,QAAQ,GAAG,uBAAuB,EAAE,OAAO,GAAG,MAAM,EAAE,EAAE,MAAM,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAE3F,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,MAAM,GAA4C,EAAE,CAAC;IAC3D,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEvB,IAAI,OAAyB,CAAC;IAC9B,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAqB,CAAC;IAC9E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IACnE,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;YAAE,SAAS;QAEnC,MAAM,aAAa,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;QACzF,IAAI,CAAC,aAAa;YAAE,SAAS;QAE7B,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAE3C,2DAA2D;QAC3D,IAAI,KAAa,CAAC;QAClB,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC9B,KAAK,GAAG,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;YACV,SAAS;QACX,CAAC;QAED,IAAI,KAAK,GAAG,QAAQ,EAAE,CAAC;YACrB,OAAO,EAAE,CAAC;YACV,SAAS;QACX,CAAC;QAED,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC;gBACH,MAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;gBACnD,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACzB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,QAAQ;oBACd,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;iBACzD,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AACrF,CAAC;AAED,8EAA8E;AAC9E,kDAAkD;AAClD,8EAA8E;AAE9E;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,kBAAkB,CAChC,WAAmB,uBAAuB,EAC1C,UAAkB,MAAM,EAAE;IAE1B,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEvB,IAAI,OAAyB,CAAC;IAC9B,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAqB,CAAC;IAC9E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;YAAE,SAAS;QACnC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAAE,SAAS;QAExE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC9B,MAAM,KAAK,GAAG,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC;YAC/B,IAAI,KAAK,IAAI,QAAQ,EAAE,CAAC;gBACtB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACtE,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,kBAAkB;QACpB,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AACnD,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CACjC,aAAqB,EACrB,aAA0B,EAC1B,WAAoB;IAEpB,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEvB,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC;QAAE,OAAO,OAAO,CAAC;IAE/C,IAAI,WAAqB,CAAC;IAC1B,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;QACnD,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACzD,CAAC;SAAM,CAAC;QACN,IAAI,CAAC;YACH,WAAW,GAAG,WAAW,CAAC,aAAa,CAAC;iBACrC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;iBAClC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;gBACZ,IAAI,CAAC;oBACH,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;gBACnC,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,KAAK,CAAC;gBACf,CAAC;YACH,CAAC,CAAC,CAAC;QACP,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,OAAO,CAAC;QACjB,CAAC;IACH,CAAC;IAED,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,IAAI,WAAqB,CAAC;QAC1B,IAAI,CAAC;YACH,WAAW,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;QACxC,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QAED,KAAK,MAAM,MAAM,IAAI,WAAW,EAAE,CAAC;YACjC,IAAI,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAE,SAAS;YAExC,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YAC9C,IAAI,CAAC;gBACH,MAAM,EAAE,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;gBAClC,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE;oBAAE,SAAS;gBAChC,MAAM,KAAK,GAAG,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC;gBAC/B,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC1E,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO;YACT,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC9D,CAAC"}
1
+ {"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/gc/cleanup.ts"],"names":[],"mappings":"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"}
@@ -19,6 +19,22 @@
19
19
  import type { LlmAddParams, LlmAddResult, LlmAuxiliaryStatusParams, LlmAuxiliaryStatusResult, LlmListParams, LlmListResult, LlmProfileParams, LlmProfileResult, LlmRemoveParams, LlmRemoveResult, LlmSystemsOfUseParams, LlmSystemsOfUseResult, LlmTestParams, LlmTestResult, LlmUseParams, LlmUseResult, LlmWhoamiParams, LlmWhoamiResult } from '@cleocode/contracts';
20
20
  import { type EngineResult } from '@cleocode/contracts';
21
21
  import { resolveAuxiliaryFallbackChain } from './auxiliary-fallback.js';
22
+ /**
23
+ * Redact every occurrence of a secret in free text (S-11).
24
+ *
25
+ * Used before DEBUG-logging a provider error body: Anthropic 4xx payloads can
26
+ * reflect request headers (including the bearer token) back in human-readable
27
+ * form, so the body must never reach a log stream with the live secret in it.
28
+ * Replaces each occurrence with the standard last-4 preview. Empty/short
29
+ * secrets (< 8 chars) redact nothing — they cannot meaningfully leak and a
30
+ * short needle would shred unrelated text.
31
+ *
32
+ * @param text - Raw text that may contain the secret.
33
+ * @param secret - The live credential to scrub.
34
+ * @returns The text with every occurrence of the secret replaced.
35
+ * @task T11968
36
+ */
37
+ export declare function redactSecret(text: string, secret: string | null): string;
22
38
  /**
23
39
  * `llm.add` — upsert a credential into the multi-credential pool.
24
40
  *
@@ -1 +1 @@
1
- {"version":3,"file":"cli-ops.d.ts","sourceRoot":"","sources":["../../src/llm/cli-ops.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,wBAAwB,EACxB,wBAAwB,EACxB,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,eAAe,EAEf,qBAAqB,EACrB,qBAAqB,EACrB,aAAa,EACb,aAAa,EACb,YAAY,EACZ,YAAY,EAEZ,eAAe,EACf,eAAe,EAGhB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,KAAK,YAAY,EAIlB,MAAM,qBAAqB,CAAC;AAO7B,OAAO,EAGL,6BAA6B,EAC9B,MAAM,yBAAyB,CAAC;AAuHjC;;;;GAIG;AACH,wBAAsB,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAwBtF;AAED;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAWzF;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC,CAc/F;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CA4BtF;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAqDzC;AAED;;;;;;;;;GASG;AACH,wBAAsB,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CA4FzF;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC,CAgC/F;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,YAAY,CAAC,qBAAqB,CAAC,CAAC,CAO9C;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,wBAAwB,GAC/B,OAAO,CAAC,YAAY,CAAC,wBAAwB,CAAC,CAAC,CAoBjD;AAGD,OAAO,EAAE,6BAA6B,EAAE,CAAC"}
1
+ {"version":3,"file":"cli-ops.d.ts","sourceRoot":"","sources":["../../src/llm/cli-ops.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,wBAAwB,EACxB,wBAAwB,EACxB,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,eAAe,EAEf,qBAAqB,EACrB,qBAAqB,EACrB,aAAa,EACb,aAAa,EACb,YAAY,EACZ,YAAY,EAEZ,eAAe,EACf,eAAe,EAGhB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,KAAK,YAAY,EAIlB,MAAM,qBAAqB,CAAC;AAQ7B,OAAO,EAGL,6BAA6B,EAC9B,MAAM,yBAAyB,CAAC;AAuCjC;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAGxE;AAoFD;;;;GAIG;AACH,wBAAsB,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAwBtF;AAED;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAWzF;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC,CAc/F;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CA4BtF;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAqDzC;AAED;;;;;;;;;GASG;AACH,wBAAsB,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAoGzF;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC,CAgC/F;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,YAAY,CAAC,qBAAqB,CAAC,CAAC,CAO9C;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,wBAAwB,GAC/B,OAAO,CAAC,YAAY,CAAC,wBAAwB,CAAC,CAAC,CAoBjD;AAGD,OAAO,EAAE,6BAA6B,EAAE,CAAC"}
@@ -18,6 +18,7 @@
18
18
  */
19
19
  import { engineError, engineSuccess, WHOAMI_ROLE_IDS, } from '@cleocode/contracts';
20
20
  import { setConfigValue } from '../config.js';
21
+ import { getLogger } from '../logger.js';
21
22
  // S-13 (CWE-209): wrap any user-facing error string in the project-wide
22
23
  // `redactContent` helper so a stack trace or fetch error that incidentally
23
24
  // contains a credential substring is automatically scrubbed before it
@@ -30,6 +31,7 @@ import { addCredential, getCredentialByLabel, listCredentials, removeCredential,
30
31
  import { IMPLICIT_FALLBACK_MODEL, resolveLLMForRole } from './role-resolver.js';
31
32
  import { tokenPreview } from './sealed-credential.js';
32
33
  import { listSystemsOfUse } from './system-of-use-registry.js';
34
+ const logger = getLogger('llm-cli-ops');
33
35
  // ---------------------------------------------------------------------------
34
36
  // Constants
35
37
  // ---------------------------------------------------------------------------
@@ -50,6 +52,26 @@ const ALL_ROLES = WHOAMI_ROLE_IDS;
50
52
  // ---------------------------------------------------------------------------
51
53
  // Redaction helpers
52
54
  // ---------------------------------------------------------------------------
55
+ /**
56
+ * Redact every occurrence of a secret in free text (S-11).
57
+ *
58
+ * Used before DEBUG-logging a provider error body: Anthropic 4xx payloads can
59
+ * reflect request headers (including the bearer token) back in human-readable
60
+ * form, so the body must never reach a log stream with the live secret in it.
61
+ * Replaces each occurrence with the standard last-4 preview. Empty/short
62
+ * secrets (< 8 chars) redact nothing — they cannot meaningfully leak and a
63
+ * short needle would shred unrelated text.
64
+ *
65
+ * @param text - Raw text that may contain the secret.
66
+ * @param secret - The live credential to scrub.
67
+ * @returns The text with every occurrence of the secret replaced.
68
+ * @task T11968
69
+ */
70
+ export function redactSecret(text, secret) {
71
+ if (!secret || secret.length < 8 || !text)
72
+ return text;
73
+ return text.split(secret).join(`…${secret.slice(-4)}`);
74
+ }
53
75
  /**
54
76
  * Return a redacted preview of a token tagged by auth scheme (S-11).
55
77
  *
@@ -351,14 +373,19 @@ export async function llmTest(params) {
351
373
  try {
352
374
  const response = await fetch(url, { method: 'POST', headers, body });
353
375
  if (!response.ok) {
354
- // S-11: NEVER echo the response body in the error envelope. Some
376
+ // S-11: NEVER echo the response body in the error ENVELOPE. Some
355
377
  // provider 4xx responses include reflected request headers (e.g.
356
378
  // Anthropic's error payload can carry `x-api-key` substring matches
357
379
  // back in human-readable form), and a sloppy log pipeline could
358
- // surface that to an audit log. Surface only the HTTP status —
359
- // operators who need the body can re-run with `CLEO_LOG_LEVEL=debug`
360
- // and inspect the underlying fetch trace.
361
- return engineError('E_PROVIDER_PING_FAILED', `${provider} returned HTTP ${response.status} (body suppressed for credential safety; rerun with CLEO_LOG_LEVEL=debug to inspect via raw fetch trace)`);
380
+ // surface that to an audit log. Surface only the HTTP status in the
381
+ // envelope — and emit the body to the DEBUG log with the in-scope
382
+ // credential redacted, so the failure is actually diagnosable
383
+ // (T11958/DHQ-075 repro follow-through: the previous message promised
384
+ // a "raw fetch trace" that did not exist).
385
+ const bodyText = await response.text().catch(() => '');
386
+ logger.debug({ provider, status: response.status, body: redactSecret(bodyText, token).slice(0, 1024) }, 'llm.test provider ping failed');
387
+ return engineError('E_PROVIDER_PING_FAILED', `${provider} returned HTTP ${response.status} (body suppressed for credential safety; ` +
388
+ `rerun with CLEO_LOG_LEVEL=debug to log the redacted response body)`);
362
389
  }
363
390
  const parsed = (await response.json());
364
391
  providerResponseId = typeof parsed.id === 'string' ? parsed.id : null;