@cleocode/core 2026.9.4 → 2026.9.6

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 (35) hide show
  1. package/dist/docs/export-document.js.map +1 -1
  2. package/dist/llm/plugin-facade.js.map +1 -1
  3. package/dist/release/plan.d.ts +1 -6
  4. package/dist/release/plan.d.ts.map +1 -1
  5. package/dist/release/plan.js +1 -8
  6. package/dist/release/plan.js.map +1 -1
  7. package/dist/release/pr-evidence.d.ts +3 -2
  8. package/dist/release/pr-evidence.d.ts.map +1 -1
  9. package/dist/release/pr-evidence.js +24 -5
  10. package/dist/release/pr-evidence.js.map +1 -1
  11. package/dist/release/reconcile.d.ts +19 -1
  12. package/dist/release/reconcile.d.ts.map +1 -1
  13. package/dist/release/reconcile.js +110 -6
  14. package/dist/release/reconcile.js.map +1 -1
  15. package/dist/release/release-manifest.d.ts.map +1 -1
  16. package/dist/release/release-manifest.js +1 -3
  17. package/dist/release/release-manifest.js.map +1 -1
  18. package/dist/release/version.d.ts +48 -0
  19. package/dist/release/version.d.ts.map +1 -0
  20. package/dist/release/version.js +50 -0
  21. package/dist/release/version.js.map +1 -0
  22. package/dist/selfimprove/fix-gen.js.map +1 -1
  23. package/dist/tasks/evidence.d.ts +36 -0
  24. package/dist/tasks/evidence.d.ts.map +1 -1
  25. package/dist/tasks/evidence.js +109 -57
  26. package/dist/tasks/evidence.js.map +1 -1
  27. package/dist/tasks/heavy-tool-limit.d.ts +119 -0
  28. package/dist/tasks/heavy-tool-limit.d.ts.map +1 -1
  29. package/dist/tasks/heavy-tool-limit.js +205 -3
  30. package/dist/tasks/heavy-tool-limit.js.map +1 -1
  31. package/dist/tasks/tool-cache.d.ts +19 -39
  32. package/dist/tasks/tool-cache.d.ts.map +1 -1
  33. package/dist/tasks/tool-cache.js +145 -29
  34. package/dist/tasks/tool-cache.js.map +1 -1
  35. package/package.json +13 -13
@@ -248,6 +248,42 @@ export type AtomValidation = {
248
248
  * @task T12107
249
249
  * @adr ADR-051 §3
250
250
  */
251
+ /**
252
+ * The two roots an evidence atom may be about, named so an arm cannot inherit
253
+ * the wrong one.
254
+ *
255
+ * gh#1365 was fixed once by threading a single `executionRoot` parameter, and
256
+ * the fix reached two of the switch's arms. The reason a single parameter could
257
+ * not close it is that **"root" is one word for two things**: the tree the
258
+ * evidence is ABOUT, and the store CLEO keeps its own records in. A parameter
259
+ * called `root` relocates that ambiguity into a signature rather than removing
260
+ * it, so the next arm silently picks whichever the author had in mind.
261
+ *
262
+ * With both fields named, every arm DECLARES what it is about by which field it
263
+ * reads. `decision:` reading {@link storeRoot} is self-documenting rather than
264
+ * an exception needing a comment; `pr:` reading both is obviously correct
265
+ * rather than obviously odd; and a new arm cannot inherit a default, because
266
+ * there is no default.
267
+ *
268
+ * The rule, stated once: **use the root that matches what the atom is about.**
269
+ * Evidence about the repository under test → {@link executionRoot}. Evidence
270
+ * about CLEO's own records → {@link storeRoot}.
271
+ *
272
+ * @task T12238 (gh#1365)
273
+ */
274
+ export interface EvidenceRoots {
275
+ /**
276
+ * Where CLEO keeps its own state — `.cleo/`, the BRAIN db, project context,
277
+ * the evidence caches. NOT necessarily a git repository.
278
+ */
279
+ readonly storeRoot: string;
280
+ /**
281
+ * The repository the evidence is about. Differs from {@link storeRoot}
282
+ * whenever the CLEO root is a parent of, or a worktree sibling of, the git
283
+ * checkout — which is this fleet's normal multi-project layout.
284
+ */
285
+ readonly executionRoot: string;
286
+ }
251
287
  export declare function validateAtom(parsed: ParsedAtom, projectRoot: string,
252
288
  /** T9178: When provided, validates commit is on task/<taskId> branch. */
253
289
  taskId?: string,
@@ -1 +1 @@
1
- {"version":3,"file":"evidence.d.ts","sourceRoot":"","sources":["../../src/tasks/evidence.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"evidence.d.ts","sourceRoot":"","sources":["../../src/tasks/evidence.ts"],"names":[],"mappings":"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"}
@@ -28,7 +28,7 @@ import { EvidenceParseError, ExitCode, GATE_EVIDENCE_REQUIREMENTS, parseEvidence
28
28
  import { CleoError } from '../errors.js';
29
29
  import { pushWarning } from '../output.js';
30
30
  import { getEffectiveHead } from '../worktree/effective-head.js';
31
- import { describeMemoryLimit } from './heavy-tool-limit.js';
31
+ import { DISABLE_ENV, describeMemoryLimit } from './heavy-tool-limit.js';
32
32
  import { computeCommitRevalidationKey, readCommitRevalidationEntry, writeCommitRevalidationEntry, } from './revalidation-cache.js';
33
33
  import { resolveSpawnTimeoutMs, runToolCached } from './tool-cache.js';
34
34
  import { CANONICAL_TOOLS, listValidToolNames, resolveToolCommand, } from './tool-resolver.js';
@@ -132,41 +132,30 @@ export function parseEvidence(raw) {
132
132
  throw err;
133
133
  }
134
134
  }
135
- /**
136
- * Validate a single parsed atom against the filesystem / git / tools.
137
- *
138
- * @param parsed - Parsed atom from {@link parseEvidence}
139
- * @param projectRoot - Absolute path to project root (for resolving files, git)
140
- * @param taskId - Optional CLEO task ID. When provided, enables branch-scope
141
- * check (T9178), content-intersect check (T9245), worktree-aware HEAD
142
- * resolution (T-WT-3), and git-show file fallback for branch-only files
143
- * (T11959).
144
- * @param siblingCommitSha - Optional sha of a sibling `commit:` atom from the
145
- * same evidence string. When provided, `files:` paths are resolved against
146
- * that commit's tree FIRST (T12107 / gh#1195) before falling back to the
147
- * worktree and git refs — covers a merged commit whose files are not yet
148
- * present in the local checkout.
149
- * @returns Validation outcome with canonicalised form on success
150
- *
151
- * @task T832
152
- * @task T11959
153
- * @task T12107
154
- * @adr ADR-051 §3
155
- */
156
135
  export async function validateAtom(parsed, projectRoot,
157
136
  /** T9178: When provided, validates commit is on task/<taskId> branch. */
158
137
  taskId,
159
138
  /** T12107: sha of a sibling `commit:` atom in the same evidence string. */
160
139
  siblingCommitSha) {
140
+ // gh#1365: resolve the tree under test ONCE, here, and pass it down as a
141
+ // required parameter. Resolving inside each validator would centralise the
142
+ // logic but still let two of them resolve independently and drift — which is
143
+ // exactly how gh#1419 happened (a revalidation key derived from one root
144
+ // while the validation answered about another). A required parameter makes
145
+ // that divergence unrepresentable rather than merely discouraged.
146
+ const roots = {
147
+ storeRoot: projectRoot,
148
+ executionRoot: resolveEvidenceExecutionRoot(projectRoot),
149
+ };
161
150
  switch (parsed.kind) {
162
151
  case 'commit':
163
- return validateCommit(parsed.sha, projectRoot, taskId);
152
+ return validateCommit(parsed.sha, roots, taskId);
164
153
  case 'files':
165
- return validateFiles(parsed.paths, projectRoot, taskId, siblingCommitSha);
154
+ return validateFiles(parsed.paths, roots, taskId, siblingCommitSha);
166
155
  case 'test-run':
167
- return validateTestRun(parsed.path, projectRoot);
156
+ return validateTestRun(parsed.path, roots);
168
157
  case 'tool':
169
- return validateTool(parsed.tool, projectRoot);
158
+ return validateTool(parsed.tool, roots);
170
159
  case 'url':
171
160
  return validateUrl(parsed.url);
172
161
  case 'note':
@@ -174,11 +163,17 @@ siblingCommitSha) {
174
163
  case 'loc-drop':
175
164
  return validateLocDrop(parsed.fromLines, parsed.toLines);
176
165
  case 'callsite-coverage':
177
- return validateCallsiteCoverage(parsed.symbolName, parsed.relativeSourcePath, projectRoot);
166
+ // gh#1365 (T12238): `rg` searches the SOURCE tree. Resolved from the
167
+ // store root it searched the wrong directory and reported a symbol
168
+ // UNCOVERED when it was covered — a false negative, which fails closed
169
+ // and looks like diligence, so it would have been chased as a real gap.
170
+ return validateCallsiteCoverage(parsed.symbolName, parsed.relativeSourcePath, roots);
178
171
  case 'decision':
179
- return validateDecision(parsed.decisionId, projectRoot);
172
+ // storeRoot is CORRECT here and must stay: a decision lives in the BRAIN
173
+ // db, which is CLEO's own record, not the repository's.
174
+ return validateDecision(parsed.decisionId, roots);
180
175
  case 'pr':
181
- return validatePrAtom(parsed.prNumber, projectRoot);
176
+ return validatePrAtom(parsed.prNumber, roots);
182
177
  case 'satisfies': {
183
178
  // ADR-079-r2: 5-check validator pipeline shipped by T10507.
184
179
  // Delegates to the dedicated validator module to keep the dispatch
@@ -192,7 +187,9 @@ siblingCommitSha) {
192
187
  targetAcId: parsed.targetAcId,
193
188
  targetAcAlias: parsed.targetAcAlias,
194
189
  versionPin: parsed.versionPin,
195
- }, taskId, projectRoot);
190
+ }, taskId,
191
+ // A task/AC lookup is CLEO's own record — storeRoot.
192
+ roots.storeRoot);
196
193
  if (!result.ok) {
197
194
  return { ok: false, reason: result.reason, codeName: result.codeName };
198
195
  }
@@ -327,7 +324,8 @@ async function findReachableIntegrationBranch(sha, branches, projectRoot) {
327
324
  }
328
325
  return null;
329
326
  }
330
- async function validateCommit(sha, projectRoot, taskId) {
327
+ async function validateCommit(sha, roots, taskId) {
328
+ const { storeRoot: projectRoot, executionRoot } = roots;
331
329
  if (!/^[0-9a-f]{7,40}$/i.test(sha)) {
332
330
  return {
333
331
  ok: false,
@@ -335,7 +333,7 @@ async function validateCommit(sha, projectRoot, taskId) {
335
333
  codeName: 'E_EVIDENCE_INVALID',
336
334
  };
337
335
  }
338
- const exists = await runCommand('git', ['cat-file', '-e', `${sha}^{commit}`], projectRoot);
336
+ const exists = await runCommand('git', ['cat-file', '-e', `${sha}^{commit}`], executionRoot);
339
337
  if (exists.exitCode !== 0) {
340
338
  return {
341
339
  ok: false,
@@ -346,7 +344,7 @@ async function validateCommit(sha, projectRoot, taskId) {
346
344
  // T-WT-3: resolve effective HEAD — uses task/<taskId> branch when it exists,
347
345
  // falls back to "HEAD" when taskId is absent or the branch does not yet exist.
348
346
  // This is env-var-independent: it does not rely on CLEO_WORKTREE_ROOT / ALS.
349
- const effectiveHead = await getEffectiveHead(projectRoot, taskId);
347
+ const effectiveHead = await getEffectiveHead(executionRoot, taskId);
350
348
  // T12028 / gh#1116: resolve integration branches for reachability fallbacks.
351
349
  // Loaded once and reused by both the effective-head fallback and the
352
350
  // branch-scope fallback below. Resolution follows the same 3-tier precedence
@@ -369,7 +367,7 @@ async function validateCommit(sha, projectRoot, taskId) {
369
367
  // that merge through a non-main branch can use commits on that branch
370
368
  // as evidence without synthetic task-branch scaffolding.
371
369
  const reachableIntegrationBranch = taskId
372
- ? await findReachableIntegrationBranch(sha, integrationBranches, projectRoot)
370
+ ? await findReachableIntegrationBranch(sha, integrationBranches, executionRoot)
373
371
  : null;
374
372
  if (reachableIntegrationBranch === null) {
375
373
  const branchList = integrationBranches.join(', ');
@@ -398,7 +396,7 @@ async function validateCommit(sha, projectRoot, taskId) {
398
396
  // commit (early-init edge case handled by the HEAD ancestry check above).
399
397
  if (taskId) {
400
398
  const branchRef = `task/${taskId}`;
401
- const branchExists = await runCommand('git', ['rev-parse', '--verify', branchRef], projectRoot);
399
+ const branchExists = await runCommand('git', ['rev-parse', '--verify', branchRef], executionRoot);
402
400
  if (branchExists.exitCode === 0) {
403
401
  const onBranch = await runCommand('git', ['merge-base', '--is-ancestor', sha, branchRef], projectRoot);
404
402
  if (onBranch.exitCode !== 0) {
@@ -1028,7 +1026,8 @@ async function gitShowFileContentAtCommit(relPath, sha, projectRoot) {
1028
1026
  * @task T11959
1029
1027
  * @task T12107
1030
1028
  */
1031
- async function validateFiles(paths, projectRoot, taskId, commitSha) {
1029
+ async function validateFiles(paths, roots, taskId, commitSha) {
1030
+ const { storeRoot: projectRoot, executionRoot } = roots;
1032
1031
  if (paths.length === 0) {
1033
1032
  return {
1034
1033
  ok: false,
@@ -1038,13 +1037,19 @@ async function validateFiles(paths, projectRoot, taskId, commitSha) {
1038
1037
  }
1039
1038
  const files = [];
1040
1039
  for (const p of paths) {
1041
- const abs = isAbsolute(p) ? p : resolvePath(projectRoot, p);
1040
+ // gh#1365: the file belongs to the repo under test. Resolving it against
1041
+ // the CLEO store root reported "File removed since verify" for a file that
1042
+ // was present, 5,176 bytes, in the project — a false negative that then
1043
+ // surfaced as E_EVIDENCE_STALE. Execution root first, store root second so
1044
+ // an absolute or store-relative path keeps working.
1045
+ const fromExecution = isAbsolute(p) ? p : resolvePath(executionRoot, p);
1046
+ const abs = existsSync(fromExecution) ? fromExecution : resolvePath(projectRoot, p);
1042
1047
  let content = null;
1043
1048
  // T12107 (gh#1195): the sibling commit is the evidence anchor — check its
1044
1049
  // tree FIRST. A file merged remotely but not yet present locally validates
1045
1050
  // here without waiting for a fast-forward.
1046
1051
  if (commitSha) {
1047
- content = await gitShowFileContentAtCommit(p, commitSha, projectRoot);
1052
+ content = await gitShowFileContentAtCommit(p, commitSha, executionRoot);
1048
1053
  }
1049
1054
  if (content === null && existsSync(abs)) {
1050
1055
  // Happy path — file exists on disk.
@@ -1061,7 +1066,7 @@ async function validateFiles(paths, projectRoot, taskId, commitSha) {
1061
1066
  if (content === null && taskId) {
1062
1067
  // T11959: Git-show fallback for branch-only files (worktree context).
1063
1068
  // The file exists on the task branch but not yet at the canonical root.
1064
- content = await gitShowFileContent(p, taskId, projectRoot);
1069
+ content = await gitShowFileContent(p, taskId, executionRoot);
1065
1070
  }
1066
1071
  if (content === null) {
1067
1072
  // Honest failure: enumerate every location that was checked so the
@@ -1069,7 +1074,9 @@ async function validateFiles(paths, projectRoot, taskId, commitSha) {
1069
1074
  const looked = [];
1070
1075
  if (commitSha)
1071
1076
  looked.push(`commit ${commitSha} tree`);
1072
- looked.push(`filesystem at ${projectRoot}`);
1077
+ looked.push(executionRoot === projectRoot
1078
+ ? `filesystem at ${projectRoot}`
1079
+ : `filesystem at ${executionRoot} and ${projectRoot}`);
1073
1080
  if (taskId)
1074
1081
  looked.push(`git refs task/${taskId}, main, HEAD`);
1075
1082
  return {
@@ -1147,13 +1154,14 @@ cwd = process.cwd()) {
1147
1154
  return toplevel;
1148
1155
  return projectRoot;
1149
1156
  }
1150
- async function validateTestRun(path, projectRoot) {
1157
+ async function validateTestRun(path, roots) {
1158
+ const { storeRoot: projectRoot, executionRoot } = roots;
1151
1159
  // gh#1226: a relative test-run path names a report the caller just wrote,
1152
1160
  // in the caller's tree. Resolving it against the shared store root made a
1153
1161
  // report written in a worktree report "file does not exist". Try the
1154
1162
  // execution root first, then fall back to the store root so an absolute or
1155
- // store-relative path keeps working.
1156
- const executionRoot = resolveEvidenceExecutionRoot(projectRoot);
1163
+ // store-relative path keeps working. gh#1365: the root arrives as a
1164
+ // parameter now; it is NOT re-resolved here.
1157
1165
  let abs;
1158
1166
  if (isAbsolute(path)) {
1159
1167
  abs = path;
@@ -1233,7 +1241,8 @@ async function validateTestRun(path, projectRoot) {
1233
1241
  },
1234
1242
  };
1235
1243
  }
1236
- async function validateTool(tool, projectRoot) {
1244
+ async function validateTool(tool, roots) {
1245
+ const { storeRoot: projectRoot, executionRoot } = roots;
1237
1246
  const resolution = resolveToolCommand(tool, projectRoot);
1238
1247
  // T12083: the project has no such toolchain. This is a fact about the
1239
1248
  // project, not a failure of the work — a plain JavaScript project cannot
@@ -1262,8 +1271,8 @@ async function validateTool(tool, projectRoot) {
1262
1271
  };
1263
1272
  }
1264
1273
  // gh#1220/#1226/#1230: spawn in — and fingerprint against — the tree the
1265
- // operator actually invoked from, not the shared store root.
1266
- const executionRoot = resolveEvidenceExecutionRoot(projectRoot);
1274
+ // operator actually invoked from, not the shared store root. gh#1365: the
1275
+ // root arrives as a parameter now; it is NOT re-resolved here.
1267
1276
  const result = await runToolCached(resolution.command, projectRoot, { executionRoot });
1268
1277
  // T12025: wall-clock child-process deadline exceeded — the tool was
1269
1278
  // terminated and the lock released. Signal retry; do NOT record a partially
@@ -1318,13 +1327,38 @@ async function validateTool(tool, projectRoot) {
1318
1327
  codeName: 'E_EVIDENCE_TOOL_KILLED',
1319
1328
  };
1320
1329
  }
1330
+ // gh#1397: CLEO wraps `test` and `build` in a systemd scope of its own
1331
+ // making (T12116). When that wrapper cannot start, `systemd-run` exits 1
1332
+ // WITHOUT ever running the tool — and 1 is also what a suite with a failing
1333
+ // test exits with, so the branch below reported "your tests failed" for a
1334
+ // harness that never ran. Five occurrences of gh#1396 were diagnosed as a
1335
+ // flaky suite for exactly this reason.
1336
+ //
1337
+ // The code this returns is not new: `E_EVIDENCE_TOOL_UNAVAILABLE` has always
1338
+ // been the right answer. What was missing was a route into it, because the
1339
+ // existing guard keys on `exitCode === null` and `systemd-run` itself starts
1340
+ // perfectly well before failing.
1341
+ if (result.harnessFailure !== null) {
1342
+ return {
1343
+ ok: false,
1344
+ reason: `Tool "${tool}" did NOT run. CLEO's own memory-confinement wrapper failed to ` +
1345
+ `start it in ${result.executionRoot}: ${result.harnessFailure} ` +
1346
+ `This is a CLEO harness failure, not a verdict on the tool — the suite never ` +
1347
+ `executed, so this says nothing about whether it passes. Nothing was cached. ` +
1348
+ `Set ${DISABLE_ENV}=1 to run the tool unconfined and get a real result.`,
1349
+ codeName: 'E_EVIDENCE_TOOL_UNAVAILABLE',
1350
+ };
1351
+ }
1321
1352
  if (result.exitCode === null) {
1322
1353
  return {
1323
1354
  ok: false,
1324
1355
  reason: `Tool "${tool}" → ${resolution.command.cmd} ${resolution.command.args.join(' ')} ` +
1325
1356
  `could not be executed in ${result.executionRoot} — the process never started ` +
1326
1357
  `(binary missing, not executable, or spawn error). No signal was delivered, so ` +
1327
- `it did not run and get killed.`,
1358
+ `it did not run and get killed.` +
1359
+ // gh#1397: `spawnCmd` used to discard Node's error object, so this
1360
+ // message could only list the three possibilities. It now names which.
1361
+ (result.stderrTail ? ` Reason: ${result.stderrTail}` : ''),
1328
1362
  codeName: 'E_EVIDENCE_TOOL_UNAVAILABLE',
1329
1363
  };
1330
1364
  }
@@ -1482,7 +1516,10 @@ export const CALLSITE_COVERAGE_LABEL = 'callsite-coverage';
1482
1516
  *
1483
1517
  * @task T1605
1484
1518
  */
1485
- async function validateCallsiteCoverage(symbolName, relativeSourcePath, projectRoot) {
1519
+ async function validateCallsiteCoverage(symbolName, relativeSourcePath, roots) {
1520
+ // gh#1365 (T12238): `rg` runs over the SOURCE tree, so this is evidence ABOUT
1521
+ // the repository — executionRoot, not the store.
1522
+ const projectRoot = roots.executionRoot;
1486
1523
  if (!symbolName || typeof symbolName !== 'string') {
1487
1524
  return {
1488
1525
  ok: false,
@@ -1583,7 +1620,11 @@ async function validateCallsiteCoverage(symbolName, relativeSourcePath, projectR
1583
1620
  * @task T1875
1584
1621
  * @epic T1824
1585
1622
  */
1586
- async function validateDecision(decisionId, projectRoot) {
1623
+ async function validateDecision(decisionId, roots) {
1624
+ // A decision lives in the BRAIN db — CLEO's OWN record, not the repository's.
1625
+ // storeRoot is correct here; threading the execution root would point this at
1626
+ // the wrong database (gh#1365 / T12238).
1627
+ const projectRoot = roots.storeRoot;
1587
1628
  if (!decisionId || typeof decisionId !== 'string') {
1588
1629
  return {
1589
1630
  ok: false,
@@ -1662,7 +1703,7 @@ async function validateDecision(decisionId, projectRoot) {
1662
1703
  *
1663
1704
  * @task T9764
1664
1705
  */
1665
- async function validatePrAtom(prNumber, projectRoot) {
1706
+ async function validatePrAtom(prNumber, roots) {
1666
1707
  // Dynamic import keeps the verification module free of a static dependency
1667
1708
  // on the release subtree, mirroring the pattern used by validateDecision.
1668
1709
  const { resolvePrEvidenceAtom } = await import('../release/pr-evidence.js');
@@ -1672,8 +1713,15 @@ async function validatePrAtom(prNumber, projectRoot) {
1672
1713
  // one from agents/variable-substitution) is best-effort and non-throwing; on
1673
1714
  // a missing/malformed file `loaded` is false → pass null → cleocode default.
1674
1715
  const { loadProjectContext } = await import('../agents/variable-substitution.js');
1675
- const ctx = loadProjectContext(projectRoot);
1676
- const result = await resolvePrEvidenceAtom(prNumber, projectRoot, {
1716
+ // `.cleo/project-context.json` is CLEO's own config — storeRoot.
1717
+ const ctx = loadProjectContext(roots.storeRoot);
1718
+ // gh#1365 (T12238): `pr:` is the only atom that shells out to a tool doing its
1719
+ // OWN repo discovery. `gh` walks up from its cwd looking for a git repo; given
1720
+ // the store root in a layout where the checkout is a subdirectory, it finds
1721
+ // none before the mount point and fails with "not a git repository". No
1722
+ // resolver threaded inside CLEO can reach that — only its cwd can. So this
1723
+ // atom needs BOTH roots, and a swap would be as wrong as the original.
1724
+ const result = await resolvePrEvidenceAtom(prNumber, roots, {
1677
1725
  projectContext: ctx.loaded ? ctx.context : null,
1678
1726
  });
1679
1727
  if (!result.ok) {
@@ -1954,7 +2002,10 @@ export async function revalidateEvidence(evidence, projectRoot, gate, taskId, op
1954
2002
  // (commitSha, headSha), both immutable git facts, so a hit is exactly
1955
2003
  // as sound as re-running the git spawns. See revalidation-cache.ts.
1956
2004
  const startedAt = Date.now();
1957
- const cached = await revalidateCommitAtom(atom.sha, projectRoot);
2005
+ const cached = await revalidateCommitAtom(atom.sha, {
2006
+ storeRoot: projectRoot,
2007
+ executionRoot: resolveEvidenceExecutionRoot(projectRoot),
2008
+ });
1958
2009
  if (!cached.check.ok)
1959
2010
  failed.push({ atom, reason: cached.check.reason });
1960
2011
  options?.onProgress?.(`commit:${atom.sha.slice(0, 7)} ${cached.check.ok ? 'ok' : 'FAILED'}` +
@@ -2085,11 +2136,12 @@ export async function revalidateEvidence(evidence, projectRoot, gate, taskId, op
2085
2136
  * @internal
2086
2137
  * @task T12102 (gh#1196)
2087
2138
  */
2088
- async function revalidateCommitAtom(sha, projectRoot) {
2089
- const headResult = await runCommand('git', ['rev-parse', 'HEAD'], projectRoot);
2139
+ async function revalidateCommitAtom(sha, roots) {
2140
+ const { storeRoot: projectRoot, executionRoot } = roots;
2141
+ const headResult = await runCommand('git', ['rev-parse', 'HEAD'], executionRoot);
2090
2142
  const head = headResult.exitCode === 0 ? headResult.stdout.trim() : null;
2091
2143
  if (!head) {
2092
- return { check: await validateCommit(sha, projectRoot), fromCache: false };
2144
+ return { check: await validateCommit(sha, roots), fromCache: false };
2093
2145
  }
2094
2146
  const key = computeCommitRevalidationKey(sha, head);
2095
2147
  const hit = readCommitRevalidationEntry(projectRoot, key);
@@ -2099,7 +2151,7 @@ async function revalidateCommitAtom(sha, projectRoot) {
2099
2151
  fromCache: true,
2100
2152
  };
2101
2153
  }
2102
- const check = await validateCommit(sha, projectRoot);
2154
+ const check = await validateCommit(sha, roots);
2103
2155
  if (check.ok && check.atom.kind === 'commit') {
2104
2156
  try {
2105
2157
  writeCommitRevalidationEntry(projectRoot, {