@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.
- package/dist/docs/export-document.js.map +1 -1
- package/dist/llm/plugin-facade.js.map +1 -1
- package/dist/release/plan.d.ts +1 -6
- package/dist/release/plan.d.ts.map +1 -1
- package/dist/release/plan.js +1 -8
- package/dist/release/plan.js.map +1 -1
- package/dist/release/pr-evidence.d.ts +3 -2
- package/dist/release/pr-evidence.d.ts.map +1 -1
- package/dist/release/pr-evidence.js +24 -5
- package/dist/release/pr-evidence.js.map +1 -1
- package/dist/release/reconcile.d.ts +19 -1
- package/dist/release/reconcile.d.ts.map +1 -1
- package/dist/release/reconcile.js +110 -6
- package/dist/release/reconcile.js.map +1 -1
- package/dist/release/release-manifest.d.ts.map +1 -1
- package/dist/release/release-manifest.js +1 -3
- package/dist/release/release-manifest.js.map +1 -1
- package/dist/release/version.d.ts +48 -0
- package/dist/release/version.d.ts.map +1 -0
- package/dist/release/version.js +50 -0
- package/dist/release/version.js.map +1 -0
- package/dist/selfimprove/fix-gen.js.map +1 -1
- package/dist/tasks/evidence.d.ts +36 -0
- package/dist/tasks/evidence.d.ts.map +1 -1
- package/dist/tasks/evidence.js +109 -57
- package/dist/tasks/evidence.js.map +1 -1
- package/dist/tasks/heavy-tool-limit.d.ts +119 -0
- package/dist/tasks/heavy-tool-limit.d.ts.map +1 -1
- package/dist/tasks/heavy-tool-limit.js +205 -3
- package/dist/tasks/heavy-tool-limit.js.map +1 -1
- package/dist/tasks/tool-cache.d.ts +19 -39
- package/dist/tasks/tool-cache.d.ts.map +1 -1
- package/dist/tasks/tool-cache.js +145 -29
- package/dist/tasks/tool-cache.js.map +1 -1
- package/package.json +13 -13
package/dist/tasks/evidence.d.ts
CHANGED
|
@@ -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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"}
|
package/dist/tasks/evidence.js
CHANGED
|
@@ -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,
|
|
152
|
+
return validateCommit(parsed.sha, roots, taskId);
|
|
164
153
|
case 'files':
|
|
165
|
-
return validateFiles(parsed.paths,
|
|
154
|
+
return validateFiles(parsed.paths, roots, taskId, siblingCommitSha);
|
|
166
155
|
case 'test-run':
|
|
167
|
-
return validateTestRun(parsed.path,
|
|
156
|
+
return validateTestRun(parsed.path, roots);
|
|
168
157
|
case 'tool':
|
|
169
|
-
return validateTool(parsed.tool,
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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}`],
|
|
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(
|
|
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,
|
|
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],
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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(
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
1676
|
-
const
|
|
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,
|
|
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,
|
|
2089
|
-
const
|
|
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,
|
|
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,
|
|
2154
|
+
const check = await validateCommit(sha, roots);
|
|
2103
2155
|
if (check.ok && check.atom.kind === 'commit') {
|
|
2104
2156
|
try {
|
|
2105
2157
|
writeCommitRevalidationEntry(projectRoot, {
|