@cleocode/core 2026.10.18 → 2026.10.19
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/build-provenance.json +2 -2
- package/dist/check/pr-gate.js +1 -1
- package/dist/check/pr-gate.js.map +1 -1
- package/dist/cloud/nexus-vault.d.ts +4 -3
- package/dist/cloud/nexus-vault.d.ts.map +1 -1
- package/dist/cloud/nexus-vault.js +62 -22
- package/dist/cloud/nexus-vault.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +11 -0
- package/dist/config.js.map +1 -1
- package/dist/docs/conduit-history-backfill.d.ts +210 -0
- package/dist/docs/conduit-history-backfill.d.ts.map +1 -0
- package/dist/docs/conduit-history-backfill.js +451 -0
- package/dist/docs/conduit-history-backfill.js.map +1 -0
- package/dist/docs/docs-ops.d.ts +33 -0
- package/dist/docs/docs-ops.d.ts.map +1 -1
- package/dist/docs/docs-ops.js +72 -0
- package/dist/docs/docs-ops.js.map +1 -1
- package/dist/docs/docs-update.d.ts.map +1 -1
- package/dist/docs/docs-update.js +71 -0
- package/dist/docs/docs-update.js.map +1 -1
- package/dist/docs/doctor.d.ts +18 -4
- package/dist/docs/doctor.d.ts.map +1 -1
- package/dist/docs/doctor.js +124 -3
- package/dist/docs/doctor.js.map +1 -1
- package/dist/docs/section-merge.d.ts +70 -9
- package/dist/docs/section-merge.d.ts.map +1 -1
- package/dist/docs/section-merge.js +167 -10
- package/dist/docs/section-merge.js.map +1 -1
- package/dist/docs/section-write-path.d.ts.map +1 -1
- package/dist/docs/section-write-path.js +23 -8
- package/dist/docs/section-write-path.js.map +1 -1
- package/dist/gateway-client/generated/types.gen.d.ts +4 -0
- package/dist/gateway-client/generated/types.gen.d.ts.map +1 -1
- package/dist/go/driver.d.ts +29 -145
- package/dist/go/driver.d.ts.map +1 -1
- package/dist/go/driver.js +75 -168
- package/dist/go/driver.js.map +1 -1
- package/dist/go/index.d.ts +1 -1
- package/dist/go/index.d.ts.map +1 -1
- package/dist/go/index.js +1 -1
- package/dist/go/index.js.map +1 -1
- package/dist/goal/close.d.ts +1 -1
- package/dist/goal/close.js +2 -2
- package/dist/goal/close.js.map +1 -1
- package/dist/goal/draft.d.ts +10 -3
- package/dist/goal/draft.d.ts.map +1 -1
- package/dist/goal/draft.js +14 -9
- package/dist/goal/draft.js.map +1 -1
- package/dist/goal/index.d.ts +9 -12
- package/dist/goal/index.d.ts.map +1 -1
- package/dist/goal/index.js +9 -12
- package/dist/goal/index.js.map +1 -1
- package/dist/goal/runtime.d.ts +126 -0
- package/dist/goal/runtime.d.ts.map +1 -0
- package/dist/goal/runtime.js +289 -0
- package/dist/goal/runtime.js.map +1 -0
- package/dist/goal/status.d.ts +39 -0
- package/dist/goal/status.d.ts.map +1 -0
- package/dist/goal/status.js +101 -0
- package/dist/goal/status.js.map +1 -0
- package/dist/hooks/project-runner.d.ts +8 -3
- package/dist/hooks/project-runner.d.ts.map +1 -1
- package/dist/hooks/project-runner.js +104 -14
- package/dist/hooks/project-runner.js.map +1 -1
- package/dist/hooks/project-state.js +1 -1
- package/dist/hooks/project-state.js.map +1 -1
- package/dist/internal.d.ts +7 -3
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +5 -3
- package/dist/internal.js.map +1 -1
- package/dist/lifecycle/engine-ops.d.ts.map +1 -1
- package/dist/lifecycle/engine-ops.js +9 -6
- package/dist/lifecycle/engine-ops.js.map +1 -1
- package/dist/memory/retrieval/observe.d.ts.map +1 -1
- package/dist/memory/retrieval/observe.js +4 -8
- package/dist/memory/retrieval/observe.js.map +1 -1
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +4 -1
- package/dist/paths.js.map +1 -1
- package/dist/playbooks/cantbook-profile.d.ts +3 -3
- package/dist/playbooks/cantbook-profile.js +3 -3
- package/dist/playbooks/pi-runner-wiring.d.ts +3 -3
- package/dist/playbooks/pi-runner-wiring.js +3 -3
- package/dist/release/ci-evidence.d.ts +28 -0
- package/dist/release/ci-evidence.d.ts.map +1 -1
- package/dist/release/ci-evidence.js +76 -20
- package/dist/release/ci-evidence.js.map +1 -1
- package/dist/release/open.d.ts +11 -0
- package/dist/release/open.d.ts.map +1 -1
- package/dist/release/open.js +49 -10
- package/dist/release/open.js.map +1 -1
- package/dist/release/preflight-skip.d.ts +50 -0
- package/dist/release/preflight-skip.d.ts.map +1 -1
- package/dist/release/preflight-skip.js +151 -34
- package/dist/release/preflight-skip.js.map +1 -1
- package/dist/release/reconcile.d.ts.map +1 -1
- package/dist/release/reconcile.js +6 -3
- package/dist/release/reconcile.js.map +1 -1
- package/dist/scaffold/ensure-config.d.ts +1 -1
- package/dist/scaffold/ensure-config.d.ts.map +1 -1
- package/dist/scaffold/ensure-config.js +2 -0
- package/dist/scaffold/ensure-config.js.map +1 -1
- package/dist/security/index.d.ts +1 -1
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +1 -1
- package/dist/security/index.js.map +1 -1
- package/dist/security/override-cap-setting.d.ts +180 -0
- package/dist/security/override-cap-setting.d.ts.map +1 -0
- package/dist/security/override-cap-setting.js +657 -0
- package/dist/security/override-cap-setting.js.map +1 -0
- package/dist/security/override-cap.d.ts +20 -29
- package/dist/security/override-cap.d.ts.map +1 -1
- package/dist/security/override-cap.js +47 -71
- package/dist/security/override-cap.js.map +1 -1
- package/dist/security/owner-override-auth.d.ts +58 -0
- package/dist/security/owner-override-auth.d.ts.map +1 -1
- package/dist/security/owner-override-auth.js +82 -1
- package/dist/security/owner-override-auth.js.map +1 -1
- package/dist/security/owner-override-authority.d.ts +67 -0
- package/dist/security/owner-override-authority.d.ts.map +1 -0
- package/dist/security/owner-override-authority.js +100 -0
- package/dist/security/owner-override-authority.js.map +1 -0
- package/dist/sessions/handoff.d.ts.map +1 -1
- package/dist/sessions/handoff.js +4 -5
- package/dist/sessions/handoff.js.map +1 -1
- package/dist/sessions/index.d.ts.map +1 -1
- package/dist/sessions/index.js +22 -25
- package/dist/sessions/index.js.map +1 -1
- package/dist/store/conduit-doc-history.d.ts +39 -7
- package/dist/store/conduit-doc-history.d.ts.map +1 -1
- package/dist/store/conduit-doc-history.js +62 -12
- package/dist/store/conduit-doc-history.js.map +1 -1
- package/dist/store/data-safety-central.d.ts.map +1 -1
- package/dist/store/data-safety-central.js +3 -2
- package/dist/store/data-safety-central.js.map +1 -1
- package/dist/store/json.d.ts.map +1 -1
- package/dist/store/json.js +7 -7
- package/dist/store/json.js.map +1 -1
- package/dist/store/portable-bundle-scan.d.ts +23 -1
- package/dist/store/portable-bundle-scan.d.ts.map +1 -1
- package/dist/store/portable-bundle-scan.js +85 -3
- package/dist/store/portable-bundle-scan.js.map +1 -1
- package/dist/store/portable-bundle.d.ts.map +1 -1
- package/dist/store/portable-bundle.js +6 -1
- package/dist/store/portable-bundle.js.map +1 -1
- package/dist/store/row-identity-registry.d.ts +5 -3
- package/dist/store/row-identity-registry.d.ts.map +1 -1
- package/dist/store/row-identity-registry.js +54 -38
- package/dist/store/row-identity-registry.js.map +1 -1
- package/dist/store/schema/cleo-project/conduit.d.ts.map +1 -1
- package/dist/store/schema/cleo-project/conduit.js +4 -3
- package/dist/store/schema/cleo-project/conduit.js.map +1 -1
- package/dist/store/schema/cleo-project/runtime.d.ts +32 -0
- package/dist/store/schema/cleo-project/runtime.d.ts.map +1 -1
- package/dist/store/schema/cleo-project/runtime.js +7 -3
- package/dist/store/schema/cleo-project/runtime.js.map +1 -1
- package/dist/store/session-store.d.ts +45 -0
- package/dist/store/session-store.d.ts.map +1 -1
- package/dist/store/session-store.js +96 -1
- package/dist/store/session-store.js.map +1 -1
- package/dist/store/sqlite.d.ts +2 -0
- package/dist/store/sqlite.d.ts.map +1 -1
- package/dist/store/sqlite.js +12 -0
- package/dist/store/sqlite.js.map +1 -1
- package/dist/store/sync/merge/rules.d.ts.map +1 -1
- package/dist/store/sync/merge/rules.js +0 -16
- package/dist/store/sync/merge/rules.js.map +1 -1
- package/dist/store/sync/sealer.d.ts.map +1 -1
- package/dist/store/sync/sealer.js +27 -1
- package/dist/store/sync/sealer.js.map +1 -1
- package/dist/store/sync/sequencing.d.ts +3 -1
- package/dist/store/sync/sequencing.d.ts.map +1 -1
- package/dist/store/sync/sequencing.js +5 -3
- package/dist/store/sync/sequencing.js.map +1 -1
- package/dist/store/sync/timestamp-canon.d.ts.map +1 -1
- package/dist/store/sync/timestamp-canon.js +4 -0
- package/dist/store/sync/timestamp-canon.js.map +1 -1
- package/dist/store/table-classification.d.ts.map +1 -1
- package/dist/store/table-classification.js +12 -8
- package/dist/store/table-classification.js.map +1 -1
- package/dist/store/twin-collapse.d.ts +21 -0
- package/dist/store/twin-collapse.d.ts.map +1 -1
- package/dist/store/twin-collapse.js +235 -18
- package/dist/store/twin-collapse.js.map +1 -1
- package/dist/system/health.d.ts +17 -0
- package/dist/system/health.d.ts.map +1 -1
- package/dist/system/health.js +96 -0
- package/dist/system/health.js.map +1 -1
- package/dist/tasks/affected-packages.d.ts +67 -2
- package/dist/tasks/affected-packages.d.ts.map +1 -1
- package/dist/tasks/affected-packages.js +149 -21
- package/dist/tasks/affected-packages.js.map +1 -1
- package/dist/tasks/affected-scope.d.ts.map +1 -1
- package/dist/tasks/affected-scope.js +91 -5
- package/dist/tasks/affected-scope.js.map +1 -1
- package/dist/tasks/changeset-plan.d.ts +33 -0
- package/dist/tasks/changeset-plan.d.ts.map +1 -0
- package/dist/tasks/changeset-plan.js +152 -0
- package/dist/tasks/changeset-plan.js.map +1 -0
- package/dist/tasks/complete.d.ts.map +1 -1
- package/dist/tasks/complete.js +9 -1
- package/dist/tasks/complete.js.map +1 -1
- package/dist/tasks/done-plan.d.ts.map +1 -1
- package/dist/tasks/done-plan.js +28 -14
- package/dist/tasks/done-plan.js.map +1 -1
- package/dist/tasks/done-record.d.ts.map +1 -1
- package/dist/tasks/done-record.js +5 -1
- package/dist/tasks/done-record.js.map +1 -1
- package/dist/tasks/evidence.d.ts.map +1 -1
- package/dist/tasks/evidence.js +149 -18
- package/dist/tasks/evidence.js.map +1 -1
- package/dist/tasks/gate-runner.d.ts.map +1 -1
- package/dist/tasks/gate-runner.js +76 -4
- package/dist/tasks/gate-runner.js.map +1 -1
- package/dist/tasks/qa-run-binding.d.ts +18 -0
- package/dist/tasks/qa-run-binding.d.ts.map +1 -1
- package/dist/tasks/qa-run-binding.js +41 -1
- package/dist/tasks/qa-run-binding.js.map +1 -1
- package/dist/tasks/test-run-binding.d.ts +62 -0
- package/dist/tasks/test-run-binding.d.ts.map +1 -1
- package/dist/tasks/test-run-binding.js +126 -21
- package/dist/tasks/test-run-binding.js.map +1 -1
- package/dist/tasks/tool-resolver.d.ts +7 -0
- package/dist/tasks/tool-resolver.d.ts.map +1 -1
- package/dist/tasks/tool-resolver.js +3 -1
- package/dist/tasks/tool-resolver.js.map +1 -1
- package/dist/validation/engine-ops.d.ts.map +1 -1
- package/dist/validation/engine-ops.js +24 -29
- package/dist/validation/engine-ops.js.map +1 -1
- package/migrations/drizzle-cleo-project/20261016120000_t12535-playbook-row-uids/migration.sql +24 -0
- package/package.json +13 -13
- package/schemas/project-context.schema.json +5 -0
- package/templates/CLEO-INJECTION.md +1 -1
- package/templates/CLEO-REFERENCE.md +42 -1
- package/templates/cleo-gitignore +3 -0
- package/templates/git-hooks/legacy-hashes.json +1 -0
- package/templates/git-hooks/pre-push +35 -7
- package/templates/workflows/release-prepare.yml.tmpl +82 -4
- package/dist/goal/advance-with-persist.d.ts +0 -80
- package/dist/goal/advance-with-persist.d.ts.map +0 -1
- package/dist/goal/advance-with-persist.js +0 -105
- package/dist/goal/advance-with-persist.js.map +0 -1
- package/dist/goal/arm.d.ts +0 -61
- package/dist/goal/arm.d.ts.map +0 -1
- package/dist/goal/arm.js +0 -65
- package/dist/goal/arm.js.map +0 -1
- package/dist/goal/continuation.d.ts +0 -66
- package/dist/goal/continuation.d.ts.map +0 -1
- package/dist/goal/continuation.js +0 -111
- package/dist/goal/continuation.js.map +0 -1
- package/dist/goal/judge.d.ts +0 -113
- package/dist/goal/judge.d.ts.map +0 -1
- package/dist/goal/judge.js +0 -193
- package/dist/goal/judge.js.map +0 -1
- package/dist/goal/loop.d.ts +0 -75
- package/dist/goal/loop.d.ts.map +0 -1
- package/dist/goal/loop.js +0 -132
- package/dist/goal/loop.js.map +0 -1
package/dist/tasks/evidence.js
CHANGED
|
@@ -34,9 +34,9 @@ import { getEffectiveHead } from '../worktree/effective-head.js';
|
|
|
34
34
|
import { loadRecordedProjectRoots, rebaseLegacyEvidencePath } from './evidence-paths.js';
|
|
35
35
|
import { HEAVY_HEAP_ENV, HEAVY_WORKERS_ENV, isHeavyTool } from './heavy-tool-env.js';
|
|
36
36
|
import { DISABLE_ENV, describeMemoryLimit } from './heavy-tool-limit.js';
|
|
37
|
-
import { qaRunUnionGapReason } from './qa-run-binding.js';
|
|
37
|
+
import { qaRunUnionGapReason, typecheckCoverageGap } from './qa-run-binding.js';
|
|
38
38
|
import { computeCommitRevalidationKey, readCommitRevalidationEntry, writeCommitRevalidationEntry, } from './revalidation-cache.js';
|
|
39
|
-
import { bindTestRunReport, coveredTestFiles, TEST_RUN_MAX_RECORDED_FILES, } from './test-run-binding.js';
|
|
39
|
+
import { bindTestRunReport, configSchemaCompositionGap, coveredTestFiles, TEST_RUN_MAX_RECORDED_FILES, } from './test-run-binding.js';
|
|
40
40
|
import { captureHead, captureTree, resolveSpawnTimeoutMs, runToolCached, } from './tool-cache.js';
|
|
41
41
|
import { CANONICAL_TOOLS, canonicalToolName, listValidToolNames, resolveToolCommand, } from './tool-resolver.js';
|
|
42
42
|
import { detectStaticVacuity, probeTscFileCount, VACUOUS_TOOL_FIX } from './tool-vacuity.js';
|
|
@@ -213,7 +213,7 @@ siblingCommitSha, context) {
|
|
|
213
213
|
case 'qa-run':
|
|
214
214
|
return validateQaRun(parsed.path, roots, taskId ?? context?.task.id);
|
|
215
215
|
case 'tool':
|
|
216
|
-
return validateTool(parsed.tool, roots, context);
|
|
216
|
+
return validateTool(parsed.tool, roots, context, siblingCommitSha);
|
|
217
217
|
case 'url':
|
|
218
218
|
return validateUrl(parsed.url);
|
|
219
219
|
case 'note':
|
|
@@ -1371,6 +1371,7 @@ async function runAffectedTests(tool, run, roots, taskId) {
|
|
|
1371
1371
|
affectedPackages: run.packages,
|
|
1372
1372
|
affectedProjects: run.projects,
|
|
1373
1373
|
...(run.testFiles ? { affectedTestFiles: run.testFiles } : {}),
|
|
1374
|
+
...(run.configPaths ? { configPaths: run.configPaths } : {}),
|
|
1374
1375
|
...(run.untested.length > 0 ? { untestedPackages: run.untested } : {}),
|
|
1375
1376
|
...toolRunAtomFields(result),
|
|
1376
1377
|
},
|
|
@@ -1663,12 +1664,16 @@ async function validateTestRun(path, roots, taskId) {
|
|
|
1663
1664
|
const identity = treeHash && headSha ? { treeHash, headSha } : null;
|
|
1664
1665
|
let untestedPackages = [];
|
|
1665
1666
|
let runHeadSha;
|
|
1667
|
+
let configPaths = [];
|
|
1668
|
+
let typecheckDirs = [];
|
|
1666
1669
|
if (identity) {
|
|
1667
1670
|
const binding = bindTestRunReport(parsed, abs, bindRoot, testFiles);
|
|
1668
1671
|
if (!binding.ok)
|
|
1669
1672
|
return { ok: false, reason: binding.reason, codeName: binding.codeName };
|
|
1670
1673
|
untestedPackages = binding.untestedPackages;
|
|
1671
1674
|
runHeadSha = binding.runHeadSha;
|
|
1675
|
+
configPaths = binding.configPaths ?? [];
|
|
1676
|
+
typecheckDirs = binding.typecheckDirs ?? [];
|
|
1672
1677
|
}
|
|
1673
1678
|
return {
|
|
1674
1679
|
ok: true,
|
|
@@ -1692,6 +1697,8 @@ async function validateTestRun(path, roots, taskId) {
|
|
|
1692
1697
|
}
|
|
1693
1698
|
: {}),
|
|
1694
1699
|
...(untestedPackages.length > 0 ? { untestedPackages } : {}),
|
|
1700
|
+
...(configPaths.length > 0 ? { configPaths } : {}),
|
|
1701
|
+
...(typecheckDirs.length > 0 ? { typecheckDirs } : {}),
|
|
1695
1702
|
...(capture.runtimeExcluded.length > 0
|
|
1696
1703
|
? { runtimeExcluded: [...capture.runtimeExcluded] }
|
|
1697
1704
|
: {}),
|
|
@@ -1784,6 +1791,7 @@ async function validateQaRun(path, roots, taskId) {
|
|
|
1784
1791
|
? { uncoveredPackages: gaps.uncoveredPackages }
|
|
1785
1792
|
: {}),
|
|
1786
1793
|
...(gaps?.nonCodeChange ? { nonCodeChange: true } : {}),
|
|
1794
|
+
...(gaps?.configPaths ? { configPaths: gaps.configPaths } : {}),
|
|
1787
1795
|
},
|
|
1788
1796
|
};
|
|
1789
1797
|
}
|
|
@@ -1814,31 +1822,107 @@ async function typedGateInputs(storeRoot, taskId, bindRoot) {
|
|
|
1814
1822
|
return [];
|
|
1815
1823
|
}
|
|
1816
1824
|
}
|
|
1825
|
+
/** Run git in `cwd`, returning trimmed stdout, or null on failure. */
|
|
1826
|
+
function gitOutput(cwd, args) {
|
|
1827
|
+
try {
|
|
1828
|
+
return execFileSync('git', args, {
|
|
1829
|
+
cwd,
|
|
1830
|
+
encoding: 'utf-8',
|
|
1831
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
1832
|
+
}).trim();
|
|
1833
|
+
}
|
|
1834
|
+
catch {
|
|
1835
|
+
return null;
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
/**
|
|
1839
|
+
* The task's own merged change at `sha` (T13781, review of #2302): `sha` must
|
|
1840
|
+
* be the merge commit of a `pr:` atom, or one of the `commit:` atoms, recorded
|
|
1841
|
+
* on the task's `implemented` gate. A PR's change is its changed paths, read at
|
|
1842
|
+
* its merge; the commits' change is the union of their own diffs, read at the
|
|
1843
|
+
* newest. Any other commit is refused, however its diff looks.
|
|
1844
|
+
*/
|
|
1845
|
+
function taskOwnChange(root, context, sha) {
|
|
1846
|
+
const implemented = context?.task.verification?.evidence?.implemented?.atoms ?? [];
|
|
1847
|
+
const pr = implemented.find((a) => a.kind === 'pr' && a.mergeCommitSha === sha && (a.changedPaths?.length ?? 0) > 0);
|
|
1848
|
+
if (pr)
|
|
1849
|
+
return { ok: true, files: [...(pr.changedPaths ?? [])].sort(), read: sha };
|
|
1850
|
+
const commits = implemented.flatMap((a) => (a.kind === 'commit' ? [a.sha] : []));
|
|
1851
|
+
if (!commits.includes(sha))
|
|
1852
|
+
return {
|
|
1853
|
+
ok: false,
|
|
1854
|
+
reason: `tool:config-schema judges a merged change only at the task's own commit: ${sha.slice(0, 12)} ` +
|
|
1855
|
+
"is neither a commit: nor a pr: merge recorded on this task's implemented gate. Record " +
|
|
1856
|
+
'implemented first, then name one of its commit:/pr: atoms with tool:config-schema.',
|
|
1857
|
+
};
|
|
1858
|
+
const files = new Set();
|
|
1859
|
+
for (const commit of commits) {
|
|
1860
|
+
const diff = gitOutput(root, ['diff', '--name-only', '--no-renames', `${commit}^1`, commit]);
|
|
1861
|
+
if (diff === null)
|
|
1862
|
+
return {
|
|
1863
|
+
ok: false,
|
|
1864
|
+
reason: `tool:config-schema cannot read the change of ${commit.slice(0, 12)} in ${root}.`,
|
|
1865
|
+
};
|
|
1866
|
+
for (const path of diff.split('\n').filter(Boolean))
|
|
1867
|
+
files.add(path);
|
|
1868
|
+
}
|
|
1869
|
+
const newest = gitOutput(root, ['rev-list', '-1', '--date-order', ...commits]);
|
|
1870
|
+
if (!newest)
|
|
1871
|
+
return { ok: false, reason: `tool:config-schema cannot order the task's commits in ${root}.` };
|
|
1872
|
+
return { ok: true, files: [...files].sort(), read: newest };
|
|
1873
|
+
}
|
|
1817
1874
|
/**
|
|
1818
1875
|
* `tool:config-schema` (T13758): CLEO validates each changed CLEO-owned config
|
|
1819
|
-
* file against its CLEO schema
|
|
1820
|
-
*
|
|
1876
|
+
* file against its CLEO schema, pinned to the tree like a qa-run receipt.
|
|
1877
|
+
*
|
|
1878
|
+
* On a change that also touches other paths (T13778) it validates the config
|
|
1879
|
+
* files and records the rest as `otherPaths`; the gate then requires another
|
|
1880
|
+
* result for them (`checkTaskEvidenceContext`). With no change against the
|
|
1881
|
+
* default branch (already merged, T13781) it judges the merge commit(s) of the
|
|
1882
|
+
* write's `pr:` atoms, else its `commit:` atom, reading each file at that
|
|
1883
|
+
* commit, and records `configSchemaCommit` instead of a tree pin.
|
|
1821
1884
|
*/
|
|
1822
|
-
async function validateConfigSchema(roots, context) {
|
|
1823
|
-
const { cleoConfigSchemaFor,
|
|
1885
|
+
async function validateConfigSchema(roots, context, siblingCommitSha) {
|
|
1886
|
+
const { cleoConfigSchemaFor, scopedChangedPaths } = await import('./affected-packages.js');
|
|
1824
1887
|
const root = context?.task.id
|
|
1825
1888
|
? (await import('./change-set.js')).resolveChangeSetRoot(roots.storeRoot, context.task.id).root
|
|
1826
1889
|
: roots.executionRoot;
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1890
|
+
let changed = scopedChangedPaths(root)?.paths ?? [];
|
|
1891
|
+
// T13781: a merged change is judged at the commit(s) the write names, and
|
|
1892
|
+
// only when they are the task's OWN change (review of #2302): the change is
|
|
1893
|
+
// what the task merged, never an arbitrary commit's diff.
|
|
1894
|
+
const prs = (context?.artifactPrs ?? []).filter((p) => (p.changedPaths?.length ?? 0) > 0);
|
|
1895
|
+
let anchors = [];
|
|
1896
|
+
let commitOf = (_path) => undefined;
|
|
1897
|
+
if (changed.length === 0 && prs.length > 0) {
|
|
1898
|
+
// pr: atoms of this write: the gate refuses one not linked to the task.
|
|
1899
|
+
anchors = prs.map((p) => p.mergeCommitSha);
|
|
1900
|
+
changed = [...new Set(prs.flatMap((p) => p.changedPaths ?? []))].sort();
|
|
1901
|
+
commitOf = (path) => prMergeCommitForPath(prs, path);
|
|
1902
|
+
}
|
|
1903
|
+
else if (changed.length === 0 && siblingCommitSha) {
|
|
1904
|
+
const own = taskOwnChange(root, context, siblingCommitSha);
|
|
1905
|
+
if (!own.ok)
|
|
1906
|
+
return { ok: false, codeName: 'E_EVIDENCE_INSUFFICIENT', reason: own.reason };
|
|
1907
|
+
anchors = [own.read];
|
|
1908
|
+
changed = own.files;
|
|
1909
|
+
commitOf = () => own.read;
|
|
1910
|
+
}
|
|
1911
|
+
const config = changed.filter((p) => cleoConfigSchemaFor(p) !== null);
|
|
1912
|
+
if (config.length === 0) {
|
|
1830
1913
|
return {
|
|
1831
1914
|
ok: false,
|
|
1832
1915
|
codeName: 'E_EVIDENCE_INSUFFICIENT',
|
|
1833
1916
|
reason: changed.length === 0
|
|
1834
|
-
? 'tool:config-schema needs a change to judge: no change against the default branch was found.'
|
|
1835
|
-
|
|
1917
|
+
? 'tool:config-schema needs a change to judge: no change against the default branch was found. ' +
|
|
1918
|
+
'For an already-merged change, name it in the same write: --evidence "commit:<sha>;tool:config-schema" or "pr:<n>;tool:config-schema".'
|
|
1919
|
+
: `tool:config-schema validates CLEO config (.cleo/project-context.json, .cleo/config.json); this change touches none (${changed.slice(0, 5).join(', ')}).`,
|
|
1836
1920
|
};
|
|
1837
1921
|
}
|
|
1838
1922
|
const { resolveSchemaPath } = await import('../schema-management.js');
|
|
1839
1923
|
const { checkSchema } = await import('../json-schema-validator.js');
|
|
1840
1924
|
const failures = [];
|
|
1841
|
-
for (const path of
|
|
1925
|
+
for (const path of config) {
|
|
1842
1926
|
const schemaName = cleoConfigSchemaFor(path);
|
|
1843
1927
|
const schemaPath = resolveSchemaPath(schemaName);
|
|
1844
1928
|
if (!schemaPath)
|
|
@@ -1849,7 +1933,15 @@ async function validateConfigSchema(roots, context) {
|
|
|
1849
1933
|
};
|
|
1850
1934
|
let data;
|
|
1851
1935
|
try {
|
|
1852
|
-
|
|
1936
|
+
const at = anchors.length > 0 ? commitOf(path) : undefined;
|
|
1937
|
+
const text = at
|
|
1938
|
+
? gitOutput(root, ['show', `${at}:${path}`])
|
|
1939
|
+
: await readFile(resolvePath(root, path), 'utf-8');
|
|
1940
|
+
if (text === null) {
|
|
1941
|
+
failures.push(`${path}: not readable at ${at?.slice(0, 12)}`);
|
|
1942
|
+
continue;
|
|
1943
|
+
}
|
|
1944
|
+
data = JSON.parse(text);
|
|
1853
1945
|
}
|
|
1854
1946
|
catch (err) {
|
|
1855
1947
|
failures.push(`${path}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -1865,6 +1957,20 @@ async function validateConfigSchema(roots, context) {
|
|
|
1865
1957
|
codeName: 'E_EVIDENCE_TOOL_FAILED',
|
|
1866
1958
|
reason: `tool:config-schema: CLEO's schema check failed:\n - ${failures.join('\n - ')}`,
|
|
1867
1959
|
};
|
|
1960
|
+
const otherPaths = changed.filter((p) => cleoConfigSchemaFor(p) === null);
|
|
1961
|
+
const rest = otherPaths.length > 0 ? { otherPaths } : {};
|
|
1962
|
+
if (anchors.length > 0)
|
|
1963
|
+
return {
|
|
1964
|
+
ok: true,
|
|
1965
|
+
atom: {
|
|
1966
|
+
kind: 'tool',
|
|
1967
|
+
tool: 'config-schema',
|
|
1968
|
+
exitCode: 0,
|
|
1969
|
+
configSchema: config,
|
|
1970
|
+
configSchemaCommit: anchors.at(-1),
|
|
1971
|
+
...rest,
|
|
1972
|
+
},
|
|
1973
|
+
};
|
|
1868
1974
|
const treeHash = (await captureTree(root)).tree;
|
|
1869
1975
|
if (!treeHash)
|
|
1870
1976
|
return {
|
|
@@ -1874,12 +1980,19 @@ async function validateConfigSchema(roots, context) {
|
|
|
1874
1980
|
};
|
|
1875
1981
|
return {
|
|
1876
1982
|
ok: true,
|
|
1877
|
-
atom: {
|
|
1983
|
+
atom: {
|
|
1984
|
+
kind: 'tool',
|
|
1985
|
+
tool: 'config-schema',
|
|
1986
|
+
exitCode: 0,
|
|
1987
|
+
configSchema: config,
|
|
1988
|
+
treeHash,
|
|
1989
|
+
...rest,
|
|
1990
|
+
},
|
|
1878
1991
|
};
|
|
1879
1992
|
}
|
|
1880
|
-
async function validateTool(tool, roots, context) {
|
|
1993
|
+
async function validateTool(tool, roots, context, siblingCommitSha) {
|
|
1881
1994
|
if (tool === 'config-schema')
|
|
1882
|
-
return validateConfigSchema(roots, context);
|
|
1995
|
+
return validateConfigSchema(roots, context, siblingCommitSha);
|
|
1883
1996
|
// T13745: no test reads a non-code-only change (docs, editor settings), so
|
|
1884
1997
|
// the gate is satisfied by absence, recorded with the paths, never by a
|
|
1885
1998
|
// suite. Pinned to the tree like a test-run: once the tree moves (code
|
|
@@ -1944,7 +2057,12 @@ async function validateTool(tool, roots, context) {
|
|
|
1944
2057
|
const { storeRoot: projectRoot, executionRoot } = roots;
|
|
1945
2058
|
// T12633: project-context lives in the store; package.json scripts and
|
|
1946
2059
|
// tsconfig describe the code under test, so they are read where it runs.
|
|
1947
|
-
|
|
2060
|
+
// T13779: a change that edits project-context.json is judged by the default branch's commands.
|
|
2061
|
+
const { evidenceProjectContext } = await import('./affected-packages.js');
|
|
2062
|
+
const resolution = resolveToolCommand(tool, projectRoot, {
|
|
2063
|
+
executionRoot,
|
|
2064
|
+
projectContext: evidenceProjectContext(projectRoot, executionRoot),
|
|
2065
|
+
});
|
|
1948
2066
|
// T12083: the project has no such toolchain. This is a fact about the
|
|
1949
2067
|
// project, not a failure of the work — a plain JavaScript project cannot
|
|
1950
2068
|
// typecheck, and demanding it means no task in that project can ever be
|
|
@@ -2761,6 +2879,19 @@ export function checkTaskEvidenceContext(context, gate, atoms) {
|
|
|
2761
2879
|
(atom.kind === 'tool' && (!atom.notApplicable || atom.nonCodeChange === true)))) {
|
|
2762
2880
|
return `Code task ${context.task.id} requires an actual verification result for ${gate}; absence of a toolchain is not a passing result.`;
|
|
2763
2881
|
}
|
|
2882
|
+
// T13778: CLEO config and the rest of a change are each covered by their own result.
|
|
2883
|
+
if (gate === 'testsPassed' || gate === 'qaPassed') {
|
|
2884
|
+
const gap = configSchemaCompositionGap(atoms);
|
|
2885
|
+
if (gap !== null)
|
|
2886
|
+
return gap;
|
|
2887
|
+
}
|
|
2888
|
+
// T13783: generated-client dependents a test-run left to a typecheck need one.
|
|
2889
|
+
if (gate === 'testsPassed' && !atoms.some((atom) => atom.kind === 'ci')) {
|
|
2890
|
+
const dirs = atoms.flatMap((atom) => atom.kind === 'test-run' ? (atom.typecheckDirs ?? []) : []);
|
|
2891
|
+
const gap = typecheckCoverageGap(atoms, dirs);
|
|
2892
|
+
if (gap !== null)
|
|
2893
|
+
return gap;
|
|
2894
|
+
}
|
|
2764
2895
|
// T13427: qa-run receipts stand for qaPassed only as a pair — a typecheck
|
|
2765
2896
|
// and a lint, each by receipt or by a tool: atom (a not-applicable tool:
|
|
2766
2897
|
// records a toolchain the project lacks). Merged CI stands alone.
|