@cleocode/core 2026.10.25 → 2026.10.26

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 (198) hide show
  1. package/dist/build-provenance.json +2 -2
  2. package/dist/dispatch/contracts/output-contracts.d.ts +13 -0
  3. package/dist/dispatch/contracts/output-contracts.d.ts.map +1 -1
  4. package/dist/dispatch/contracts/output-contracts.js +29 -0
  5. package/dist/dispatch/contracts/output-contracts.js.map +1 -1
  6. package/dist/docs/docs-ops.d.ts +8 -0
  7. package/dist/docs/docs-ops.d.ts.map +1 -1
  8. package/dist/docs/docs-ops.js +24 -1
  9. package/dist/docs/docs-ops.js.map +1 -1
  10. package/dist/docs/docs-update.d.ts +8 -5
  11. package/dist/docs/docs-update.d.ts.map +1 -1
  12. package/dist/docs/docs-update.js +16 -5
  13. package/dist/docs/docs-update.js.map +1 -1
  14. package/dist/gateway-client/generated/types.gen.d.ts +27 -0
  15. package/dist/gateway-client/generated/types.gen.d.ts.map +1 -1
  16. package/dist/hooks/handlers/watchdog-hooks.d.ts.map +1 -1
  17. package/dist/hooks/handlers/watchdog-hooks.js +5 -0
  18. package/dist/hooks/handlers/watchdog-hooks.js.map +1 -1
  19. package/dist/internal.d.ts +3 -2
  20. package/dist/internal.d.ts.map +1 -1
  21. package/dist/internal.js +5 -2
  22. package/dist/internal.js.map +1 -1
  23. package/dist/lifecycle/verification/satisfies-validator.d.ts.map +1 -1
  24. package/dist/lifecycle/verification/satisfies-validator.js +22 -10
  25. package/dist/lifecycle/verification/satisfies-validator.js.map +1 -1
  26. package/dist/memory/brain-writer-thread.d.ts +30 -0
  27. package/dist/memory/brain-writer-thread.d.ts.map +1 -1
  28. package/dist/memory/brain-writer-thread.js +46 -1
  29. package/dist/memory/brain-writer-thread.js.map +1 -1
  30. package/dist/memory/brain-writer-worker.js +13 -2
  31. package/dist/memory/brain-writer-worker.js.map +1 -1
  32. package/dist/memory/embedding-backfill.d.ts +12 -0
  33. package/dist/memory/embedding-backfill.d.ts.map +1 -1
  34. package/dist/memory/embedding-backfill.js +51 -31
  35. package/dist/memory/embedding-backfill.js.map +1 -1
  36. package/dist/orchestrate/include-deps.d.ts +58 -0
  37. package/dist/orchestrate/include-deps.d.ts.map +1 -0
  38. package/dist/orchestrate/include-deps.js +138 -0
  39. package/dist/orchestrate/include-deps.js.map +1 -0
  40. package/dist/orchestrate/spawn-ops.d.ts +14 -33
  41. package/dist/orchestrate/spawn-ops.d.ts.map +1 -1
  42. package/dist/orchestrate/spawn-ops.js +49 -61
  43. package/dist/orchestrate/spawn-ops.js.map +1 -1
  44. package/dist/orchestrate/worktree-complete.d.ts +15 -1
  45. package/dist/orchestrate/worktree-complete.d.ts.map +1 -1
  46. package/dist/orchestrate/worktree-complete.js +36 -3
  47. package/dist/orchestrate/worktree-complete.js.map +1 -1
  48. package/dist/release/ci-evidence.d.ts +142 -4
  49. package/dist/release/ci-evidence.d.ts.map +1 -1
  50. package/dist/release/ci-evidence.js +298 -48
  51. package/dist/release/ci-evidence.js.map +1 -1
  52. package/dist/release/open.d.ts +25 -1
  53. package/dist/release/open.d.ts.map +1 -1
  54. package/dist/release/open.js +63 -11
  55. package/dist/release/open.js.map +1 -1
  56. package/dist/resources/admission-ledger.d.ts +83 -11
  57. package/dist/resources/admission-ledger.d.ts.map +1 -1
  58. package/dist/resources/admission-ledger.js +138 -39
  59. package/dist/resources/admission-ledger.js.map +1 -1
  60. package/dist/resources/governor.js +1 -1
  61. package/dist/resources/governor.js.map +1 -1
  62. package/dist/resources/hook-footprint.d.ts +24 -0
  63. package/dist/resources/hook-footprint.d.ts.map +1 -1
  64. package/dist/resources/hook-footprint.js +38 -1
  65. package/dist/resources/hook-footprint.js.map +1 -1
  66. package/dist/resources/run-class.d.ts +38 -5
  67. package/dist/resources/run-class.d.ts.map +1 -1
  68. package/dist/resources/run-class.js +60 -11
  69. package/dist/resources/run-class.js.map +1 -1
  70. package/dist/resources/run-governed.d.ts +13 -3
  71. package/dist/resources/run-governed.d.ts.map +1 -1
  72. package/dist/resources/run-governed.js +42 -9
  73. package/dist/resources/run-governed.js.map +1 -1
  74. package/dist/resources/slot-holder.d.ts +3 -3
  75. package/dist/resources/slot-holder.js +3 -3
  76. package/dist/resources/tool-groups.d.ts +11 -7
  77. package/dist/resources/tool-groups.d.ts.map +1 -1
  78. package/dist/resources/tool-groups.js +24 -13
  79. package/dist/resources/tool-groups.js.map +1 -1
  80. package/dist/spawn/branch-integration.d.ts +281 -0
  81. package/dist/spawn/branch-integration.d.ts.map +1 -0
  82. package/dist/spawn/branch-integration.js +715 -0
  83. package/dist/spawn/branch-integration.js.map +1 -0
  84. package/dist/spawn/branch-lock.d.ts +32 -270
  85. package/dist/spawn/branch-lock.d.ts.map +1 -1
  86. package/dist/spawn/branch-lock.js +59 -770
  87. package/dist/spawn/branch-lock.js.map +1 -1
  88. package/dist/spawn/index.d.ts +3 -1
  89. package/dist/spawn/index.d.ts.map +1 -1
  90. package/dist/spawn/index.js +5 -1
  91. package/dist/spawn/index.js.map +1 -1
  92. package/dist/store/exodus/recovery.d.ts.map +1 -1
  93. package/dist/store/exodus/recovery.js +9 -4
  94. package/dist/store/exodus/recovery.js.map +1 -1
  95. package/dist/system/health.d.ts.map +1 -1
  96. package/dist/system/health.js +3 -1
  97. package/dist/system/health.js.map +1 -1
  98. package/dist/tasks/ac-coverage-gate.d.ts +18 -2
  99. package/dist/tasks/ac-coverage-gate.d.ts.map +1 -1
  100. package/dist/tasks/ac-coverage-gate.js +40 -6
  101. package/dist/tasks/ac-coverage-gate.js.map +1 -1
  102. package/dist/tasks/ac-table.d.ts.map +1 -1
  103. package/dist/tasks/ac-table.js +3 -10
  104. package/dist/tasks/ac-table.js.map +1 -1
  105. package/dist/tasks/affected-packages.d.ts.map +1 -1
  106. package/dist/tasks/affected-packages.js +54 -10
  107. package/dist/tasks/affected-packages.js.map +1 -1
  108. package/dist/tasks/affected-scope.d.ts +10 -1
  109. package/dist/tasks/affected-scope.d.ts.map +1 -1
  110. package/dist/tasks/affected-scope.js +13 -3
  111. package/dist/tasks/affected-scope.js.map +1 -1
  112. package/dist/tasks/change-set.d.ts +9 -6
  113. package/dist/tasks/change-set.d.ts.map +1 -1
  114. package/dist/tasks/change-set.js +75 -97
  115. package/dist/tasks/change-set.js.map +1 -1
  116. package/dist/tasks/command-line.d.ts.map +1 -1
  117. package/dist/tasks/command-line.js +6 -2
  118. package/dist/tasks/command-line.js.map +1 -1
  119. package/dist/tasks/complete.d.ts.map +1 -1
  120. package/dist/tasks/complete.js +7 -2
  121. package/dist/tasks/complete.js.map +1 -1
  122. package/dist/tasks/done-plan.d.ts.map +1 -1
  123. package/dist/tasks/done-plan.js +111 -29
  124. package/dist/tasks/done-plan.js.map +1 -1
  125. package/dist/tasks/done-record.d.ts +14 -0
  126. package/dist/tasks/done-record.d.ts.map +1 -1
  127. package/dist/tasks/done-record.js +17 -10
  128. package/dist/tasks/done-record.js.map +1 -1
  129. package/dist/tasks/evidence-tree.d.ts +33 -0
  130. package/dist/tasks/evidence-tree.d.ts.map +1 -0
  131. package/dist/tasks/evidence-tree.js +132 -0
  132. package/dist/tasks/evidence-tree.js.map +1 -0
  133. package/dist/tasks/evidence.d.ts +42 -6
  134. package/dist/tasks/evidence.d.ts.map +1 -1
  135. package/dist/tasks/evidence.js +175 -79
  136. package/dist/tasks/evidence.js.map +1 -1
  137. package/dist/tasks/gate-preview.d.ts.map +1 -1
  138. package/dist/tasks/gate-preview.js +3 -2
  139. package/dist/tasks/gate-preview.js.map +1 -1
  140. package/dist/tasks/gate-runner.d.ts +11 -3
  141. package/dist/tasks/gate-runner.d.ts.map +1 -1
  142. package/dist/tasks/gate-runner.js +156 -37
  143. package/dist/tasks/gate-runner.js.map +1 -1
  144. package/dist/tasks/gate-staleness.d.ts +58 -0
  145. package/dist/tasks/gate-staleness.d.ts.map +1 -0
  146. package/dist/tasks/gate-staleness.js +78 -0
  147. package/dist/tasks/gate-staleness.js.map +1 -0
  148. package/dist/tasks/heavy-tool-env.d.ts +26 -1
  149. package/dist/tasks/heavy-tool-env.d.ts.map +1 -1
  150. package/dist/tasks/heavy-tool-env.js +92 -5
  151. package/dist/tasks/heavy-tool-env.js.map +1 -1
  152. package/dist/tasks/heavy-tool-limit.d.ts +24 -0
  153. package/dist/tasks/heavy-tool-limit.d.ts.map +1 -1
  154. package/dist/tasks/heavy-tool-limit.js +44 -1
  155. package/dist/tasks/heavy-tool-limit.js.map +1 -1
  156. package/dist/tasks/show.d.ts.map +1 -1
  157. package/dist/tasks/show.js +43 -0
  158. package/dist/tasks/show.js.map +1 -1
  159. package/dist/tasks/test-run-binding.d.ts +48 -3
  160. package/dist/tasks/test-run-binding.d.ts.map +1 -1
  161. package/dist/tasks/test-run-binding.js +111 -3
  162. package/dist/tasks/test-run-binding.js.map +1 -1
  163. package/dist/tasks/tool-cache.d.ts +58 -7
  164. package/dist/tasks/tool-cache.d.ts.map +1 -1
  165. package/dist/tasks/tool-cache.js +216 -16
  166. package/dist/tasks/tool-cache.js.map +1 -1
  167. package/dist/tasks/tool-resolver.d.ts +13 -0
  168. package/dist/tasks/tool-resolver.d.ts.map +1 -1
  169. package/dist/tasks/tool-resolver.js +34 -0
  170. package/dist/tasks/tool-resolver.js.map +1 -1
  171. package/dist/tasks/tool-runner-guard.d.ts +6 -0
  172. package/dist/tasks/tool-runner-guard.d.ts.map +1 -1
  173. package/dist/tasks/tool-runner-guard.js.map +1 -1
  174. package/dist/tasks/tool-semaphore.js +1 -1
  175. package/dist/tasks/tool-semaphore.js.map +1 -1
  176. package/dist/tasks/verification-policy.d.ts +26 -3
  177. package/dist/tasks/verification-policy.d.ts.map +1 -1
  178. package/dist/tasks/verification-policy.js +76 -11
  179. package/dist/tasks/verification-policy.js.map +1 -1
  180. package/dist/validation/doctor/checks.d.ts +12 -0
  181. package/dist/validation/doctor/checks.d.ts.map +1 -1
  182. package/dist/validation/doctor/checks.js +33 -0
  183. package/dist/validation/doctor/checks.js.map +1 -1
  184. package/dist/validation/engine-ops.d.ts +6 -0
  185. package/dist/validation/engine-ops.d.ts.map +1 -1
  186. package/dist/validation/engine-ops.js +51 -1
  187. package/dist/validation/engine-ops.js.map +1 -1
  188. package/dist/worktree/force-unlock.js +2 -2
  189. package/dist/worktree/force-unlock.js.map +1 -1
  190. package/dist/worktree/list.d.ts +7 -7
  191. package/dist/worktree/list.d.ts.map +1 -1
  192. package/dist/worktree/list.js +11 -56
  193. package/dist/worktree/list.js.map +1 -1
  194. package/dist/worktree/prune.d.ts +2 -2
  195. package/dist/worktree/prune.d.ts.map +1 -1
  196. package/dist/worktree/prune.js +4 -4
  197. package/dist/worktree/prune.js.map +1 -1
  198. package/package.json +13 -13
@@ -1 +1 @@
1
- {"version":3,"file":"gate-runner.d.ts","sourceRoot":"","sources":["../../src/tasks/gate-runner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gate-runner.d.ts","sourceRoot":"","sources":["../../src/tasks/gate-runner.ts"],"names":[],"mappings":"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"}
@@ -33,7 +33,7 @@ import { isDeepStrictEqual } from 'node:util';
33
33
  import { acceptanceGateResultSchema, acceptanceGateSchema, testCountReportSchema, testCountSummarySchema, } from '@cleocode/contracts/acceptance-gate-schema.js';
34
34
  import { findOnPath } from '@cleocode/paths';
35
35
  import { resolveOriginDefault } from '../git/base-ref.js';
36
- import { discoveryEnv, gitToplevel, resolveDeclaredEvidenceGitRoot } from '../git/work-tree.js';
36
+ import { discoveryEnv } from '../git/work-tree.js';
37
37
  import { getProjectRoot } from '../paths.js';
38
38
  import { captureProjectScope, worktreeScope } from '../project-scope.js';
39
39
  import { truncateString } from '../render/helpers.js';
@@ -44,6 +44,7 @@ import { registerTeardownAbort } from '../teardown-signal.js';
44
44
  import { acItemToText, acTextHash } from './ac-table.js';
45
45
  import { splitCommandLine } from './command-line.js';
46
46
  import { resolveCanonicalProjectRoot } from './evidence.js';
47
+ import { resolveEvidenceTree } from './evidence-tree.js';
47
48
  import { buildGateCacheEntryBody, captureGateCacheState, describeGateCacheMiss, evidenceCacheKeyPath, gateCacheEntryPath, readGateCacheEntry, sealGateCacheEntry, } from './gate-result-cache.js';
48
49
  import { planHeavyToolEnv, vitestWorkerCeiling } from './heavy-tool-env.js';
49
50
  import { resolveSpawnTimeoutMs } from './tool-cache.js';
@@ -239,7 +240,7 @@ export async function captureGateInputsHash(task, gate, execution, env = process
239
240
  * @task T13693
240
241
  */
241
242
  export async function captureGateInputs(task, gate, execution, env = process.env) {
242
- const tree = resolveTypedGateRoot(resolve(execution.identity.projectRoot));
243
+ const tree = resolveTypedGateRoot(resolve(execution.identity.projectRoot), undefined, undefined, task.id);
243
244
  const invocation = executableInvocation(gate, tree, { ...env });
244
245
  const artifacts = await snapshotGateInputs(task, gate, invocation, execution, tree);
245
246
  return {
@@ -271,18 +272,26 @@ export async function captureGateInputs(task, gate, execution, env = process.env
271
272
  * or `evidence.gitRoot`) is consulted first, as `resolveEvidenceExecutionRoot`
272
273
  * does for evidence tools. Without it, a run whose cwd had been moved to the
273
274
  * store root keyed the gate cache to the primary checkout's HEAD even when the
274
- * caller named its worktree. A declared tree is honoured only when it is this
275
- * project's checkout or one of its linked worktrees, like the cwd.
275
+ * caller named its worktree.
276
+ *
277
+ * T14058: the tree comes from {@link resolveEvidenceTree}, the resolver
278
+ * change-set binding uses, so typed gates and a bound test-run never measure
279
+ * different checkouts: the invocation's linked worktree of the declared
280
+ * repository wins, and with `taskId` the task's `task/<id>` worktree is chosen
281
+ * from the main checkout. Only this project's checkout or one of its linked
282
+ * worktrees is accepted; any other candidate is skipped.
276
283
  *
277
284
  * @param projectRoot - CLEO store root (the typed gate's authority).
278
285
  * @param cwd - Invocation directory. Defaults to `process.cwd()`.
279
286
  * @param env - Where the evidence declaration is read. Defaults to `process.env`.
287
+ * @param taskId - Task whose `task/<id>` worktree may be the tree; null skips that tier.
280
288
  * @returns The realpath of the tree typed gates execute in.
281
289
  * @task T12625
282
290
  * @task T13649
291
+ * @task T14058
283
292
  */
284
293
  export function resolveTypedGateRoot(projectRoot, cwd = process.cwd(), // CWD-OK: the invocation tree is the subject (gh#1220)
285
- env = process.env) {
294
+ env = process.env, taskId = null) {
286
295
  const real = (p) => {
287
296
  try {
288
297
  return realpathSync(p);
@@ -292,15 +301,9 @@ env = process.env) {
292
301
  }
293
302
  };
294
303
  const root = real(projectRoot);
295
- const ofThisProject = (top) => top !== null && real(top) !== root && real(resolveCanonicalProjectRoot(top)) === root
296
- ? real(top)
297
- : null;
298
- const declared = resolveDeclaredEvidenceGitRoot(projectRoot, env);
299
- const declaredTop = declared ? gitToplevel(declared.path) : null;
300
- // A declaration naming the store root itself is honoured as such.
301
- if (declaredTop !== null && real(declaredTop) === root)
302
- return projectRoot;
303
- return ofThisProject(declaredTop) ?? ofThisProject(gitToplevel(cwd)) ?? projectRoot;
304
+ const ofThisProject = (top) => real(top) === root || real(resolveCanonicalProjectRoot(top)) === root;
305
+ const tree = real(resolveEvidenceTree(projectRoot, taskId, cwd, env, ofThisProject).root);
306
+ return tree === root ? projectRoot : tree;
304
307
  }
305
308
  /**
306
309
  * Admission for a batch run without a caller-owned lifetime.
@@ -354,7 +357,7 @@ export async function runGates(gates, options = {}) {
354
357
  if (!Number.isSafeInteger(maxOutputBytes) || maxOutputBytes < 1)
355
358
  throw new RangeError('Gate capture byte limit must be a positive safe integer');
356
359
  // T12625: execute and fingerprint in the caller's worktree of this project.
357
- const treeRoot = resolveTypedGateRoot(projectRoot);
360
+ const treeRoot = resolveTypedGateRoot(projectRoot, undefined, undefined, options.taskId ?? null);
358
361
  const snapshot = structuredClone(gates);
359
362
  const controller = new AbortController();
360
363
  const deregister = registerTeardownAbort(controller);
@@ -619,7 +622,7 @@ export async function runTaskGates(task, criteria, options) {
619
622
  assertCriterionProjection(snapshot, rows);
620
623
  const env = { ...(options.env ?? process.env) };
621
624
  const verificationId = randomUUID();
622
- const tree = resolveTypedGateRoot(root);
625
+ const tree = resolveTypedGateRoot(root, undefined, undefined, snapshot.id);
623
626
  return worktreeScope.run(scope, async () => {
624
627
  const results = [];
625
628
  for (const [index, gate] of (snapshot.acceptance ?? []).entries()) {
@@ -669,6 +672,7 @@ export async function runTaskGates(task, criteria, options) {
669
672
  : (await runGates([gate], {
670
673
  ...options,
671
674
  projectRoot: root,
675
+ taskId: snapshot.id,
672
676
  env,
673
677
  execution,
674
678
  ...(options.cache && options.cache !== 'off'
@@ -986,6 +990,8 @@ function typedRevalidationScope(task, criteria, results, options, requirePassing
986
990
  results,
987
991
  execution,
988
992
  root,
993
+ // No task id: completion judges a stored result in the invocation's own
994
+ // tree, so completing from main before the merge stays refused (T12625).
989
995
  tree: resolveTypedGateRoot(root, cwd),
990
996
  env: { ...(options.env ?? process.env) },
991
997
  requirePassing,
@@ -1668,6 +1674,71 @@ function matchingBrace(text, start) {
1668
1674
  }
1669
1675
  return -1;
1670
1676
  }
1677
+ /** Top-level keys that mark a JSON object as an attempted test-count report. */
1678
+ const COUNT_REPORT_KEYS = ['numTotalTests', 'numPassedTests', 'numFailedTests', 'testResults'];
1679
+ /**
1680
+ * Why a parsed candidate was refused: its first schema issue, by field path
1681
+ * (T14060). A report that parsed but failed validation used to be dropped
1682
+ * silently, so the author was told no report existed at all.
1683
+ */
1684
+ function firstSchemaIssue(error) {
1685
+ const issue = error.issues[0];
1686
+ if (issue === undefined)
1687
+ return 'invalid';
1688
+ return issue.path.length > 0
1689
+ ? `${issue.path.map(String).join('.')}: ${issue.message}`
1690
+ : issue.message;
1691
+ }
1692
+ /** Whether `value` is a JSON object carrying any {@link COUNT_REPORT_KEYS}. */
1693
+ function looksLikeCountReport(value) {
1694
+ return (typeof value === 'object' &&
1695
+ value !== null &&
1696
+ COUNT_REPORT_KEYS.some((key) => Object.hasOwn(value, key)));
1697
+ }
1698
+ /**
1699
+ * Counts from node:test TAP output (`node --test --test-reporter=tap`, also
1700
+ * via `tsx --test`), which ships no JSON reporter (T14051). The run's LAST
1701
+ * top-level plan (`1..N` at column 0) must be followed by its `# tests N`,
1702
+ * `# pass N` and `# fail N` summary; `# cancelled N` counts as failed. Test
1703
+ * console output is re-emitted as indented or `# ` comment lines before that
1704
+ * plan, so it cannot forge the summary.
1705
+ *
1706
+ * @param stdout - The run's captured stdout.
1707
+ * @returns Counts, a refusal reason, or null when the output is not TAP.
1708
+ * @task T14051
1709
+ */
1710
+ function tapTestCounts(stdout) {
1711
+ const lines = stdout.split(/\r?\n/);
1712
+ if (!lines.some((line) => /^TAP version \d+$/.test(line.trim())))
1713
+ return null;
1714
+ if (lines.some((line) => /^\s*Bail out!/.test(line)))
1715
+ return { refusal: 'its TAP output contains "Bail out!"' };
1716
+ const plan = lines.findLastIndex((line) => /^1\.\.\d+(?:\s|$)/.test(line));
1717
+ if (plan === -1)
1718
+ return { refusal: 'its TAP output has no top-level 1..N plan' };
1719
+ const summary = new Map();
1720
+ for (const line of lines.slice(plan + 1)) {
1721
+ const match = line.match(/^# (tests|pass|fail|cancelled) (\d+)$/);
1722
+ if (match)
1723
+ summary.set(match[1], Number(match[2]));
1724
+ }
1725
+ const tests = summary.get('tests');
1726
+ const pass = summary.get('pass');
1727
+ const fail = summary.get('fail');
1728
+ if (tests === undefined || pass === undefined || fail === undefined)
1729
+ return {
1730
+ refusal: 'its TAP output has no "# tests", "# pass" and "# fail" summary after the plan',
1731
+ };
1732
+ if (tests === 0 || /^1\.\.0(?:\s|$)/.test(lines[plan]))
1733
+ return { refusal: 'its TAP output reports zero tests' };
1734
+ const failed = fail + (summary.get('cancelled') ?? 0);
1735
+ return {
1736
+ numPassedTests: pass,
1737
+ numFailedTests: failed,
1738
+ numTotalTests: tests,
1739
+ success: failed === 0,
1740
+ };
1741
+ }
1671
1742
  /**
1672
1743
  * Structured test counts emitted by THIS gate's own process, or `null`.
1673
1744
  *
@@ -1686,32 +1757,59 @@ function matchingBrace(text, start) {
1686
1757
  * code, at any time. Only the bytes this invocation emitted are bound to it.
1687
1758
  *
1688
1759
  * A non-runner command (a wrapper script) may instead print a bare count
1689
- * summary ({@link testCountSummarySchema}) as its last stdout line (T13753).
1760
+ * summary ({@link testCountSummarySchema}) as its last stdout line (T13753),
1761
+ * and node:test may print TAP ({@link tapTestCounts}, T14051).
1762
+ *
1763
+ * A candidate that parses as a count report but fails its schema is recorded
1764
+ * in `refusals` with its first issue (T14060), so the error can say which
1765
+ * report was found and why it was refused.
1690
1766
  *
1691
1767
  * @param captured - Result of running the gate command.
1768
+ * @param refusals - Receives why each report-like candidate was refused, in the order the
1769
+ * candidates are tried (last stdout line, TAP, then the output newest-first); the
1770
+ * first is the one reported.
1692
1771
  * @returns Validated counts, or `null` when the run emitted no usable report.
1693
1772
  * @task T12308
1694
1773
  * @task T13753
1774
+ * @task T14051
1775
+ * @task T14060
1695
1776
  */
1696
- function structuredTestCounts(captured) {
1777
+ function structuredTestCounts(captured, refusals) {
1697
1778
  const lastLine = captured.stdout.trimEnd().split('\n').at(-1)?.trim() ?? '';
1698
1779
  if (lastLine.startsWith('{')) {
1699
1780
  try {
1700
- const summary = testCountSummarySchema.safeParse(JSON.parse(lastLine));
1781
+ const raw = JSON.parse(lastLine);
1782
+ const summary = testCountSummarySchema.safeParse(raw);
1701
1783
  if (summary.success)
1702
1784
  return summary.data;
1785
+ // A line carrying testResults is a full report: the search below judges it.
1786
+ if (looksLikeCountReport(raw) && !Object.hasOwn(raw, 'testResults'))
1787
+ refusals.push(`the last stdout line is not a count summary (${firstSchemaIssue(summary.error)})`);
1703
1788
  }
1704
1789
  catch {
1705
1790
  // Not JSON: fall through to the full-report search.
1706
1791
  }
1707
1792
  }
1793
+ const tap = tapTestCounts(captured.stdout);
1794
+ if (tap !== null) {
1795
+ if ('refusal' in tap) {
1796
+ refusals.push(tap.refusal);
1797
+ return null;
1798
+ }
1799
+ return tap;
1800
+ }
1708
1801
  const text = `${captured.stdout}\n${captured.stderr}`.trim();
1709
1802
  if (text.length === 0)
1710
1803
  return null;
1711
1804
  const tryParse = (candidate) => {
1712
1805
  try {
1713
- const report = testCountReportSchema.safeParse(JSON.parse(candidate));
1714
- return report.success ? report.data : null;
1806
+ const raw = JSON.parse(candidate);
1807
+ const report = testCountReportSchema.safeParse(raw);
1808
+ if (report.success)
1809
+ return report.data;
1810
+ if (looksLikeCountReport(raw))
1811
+ refusals.push(`a JSON report in its output fails the full report shape (${firstSchemaIssue(report.error)})`);
1812
+ return null;
1715
1813
  }
1716
1814
  catch {
1717
1815
  return null;
@@ -1820,10 +1918,12 @@ async function fileStamp(path) {
1820
1918
  *
1821
1919
  * @param before - Each candidate's stamp just before the spawn.
1822
1920
  * @param startedAt - Epoch ms just before the spawn.
1921
+ * @param refusals - Receives why a fresh report that failed its schema was refused (T14060).
1823
1922
  * @returns Validated counts, or null.
1824
1923
  * @task T13782
1924
+ * @task T14060
1825
1925
  */
1826
- async function freshReportCounts(before, startedAt) {
1926
+ async function freshReportCounts(before, startedAt, refusals) {
1827
1927
  for (const [path, was] of before) {
1828
1928
  const now = await fileStamp(path);
1829
1929
  if (now === null || now.mtimeMs < startedAt || (was !== null && was.sha256 === now.sha256))
@@ -1835,6 +1935,7 @@ async function freshReportCounts(before, startedAt) {
1835
1935
  const report = testCountReportSchema.safeParse(raw);
1836
1936
  if (report.success)
1837
1937
  return report.data;
1938
+ refusals.push(`${path} fails the full report shape (${firstSchemaIssue(report.error)})`);
1838
1939
  }
1839
1940
  catch {
1840
1941
  // Unreadable or not JSON: not a report of this run.
@@ -1849,24 +1950,40 @@ async function freshReportCounts(before, startedAt) {
1849
1950
  * reader had no way to learn what "supported" meant, what shape was expected,
1850
1951
  * or which flag produced it — so the reported resolution was to delete the
1851
1952
  * `minCount` from the gate, which removes the guarantee rather than meeting it.
1953
+ * node:test (`node --test`, `tsx --test`) is detected before the package
1954
+ * managers, which run it too and whose `--reporter=json` it rejects (T14051);
1955
+ * a report that was found but refused is named with its first issue (T14060).
1852
1956
  *
1853
1957
  * @param gate - Gate whose command needs a machine-readable reporter.
1958
+ * @param refusal - Why the newest report-like candidate was refused, if any.
1854
1959
  * @task T12308
1960
+ * @task T14051
1961
+ * @task T14060
1855
1962
  */
1856
- function describeMissingTestCount(gate) {
1963
+ function describeMissingTestCount(gate, refusal) {
1857
1964
  const invoked = [gate.command, ...(gate.args ?? [])].join(' ');
1858
- const flag = /jest/.test(invoked)
1859
- ? '--json'
1860
- : /vitest|pnpm|npm|yarn|bun/.test(invoked)
1861
- ? '--reporter=json'
1862
- : '<your runner\u2019s JSON reporter flag>';
1863
- return (`minCount ${gate.minCount} cannot be proved: \`${invoked}\` emitted no machine-readable ` +
1864
- `test report, and an exit code alone carries no count. Add a JSON reporter to the gate ` +
1865
- `command itself (e.g. \`${invoked} ${flag}\`) so the run that is being attested is the ` +
1866
- `run that is counted. A report file this run writes (its --outputFile, or ` +
1867
- `${REDIRECTED_JSON_REPORT}) is read too, but one produced by a separate invocation is ` +
1868
- `deliberately not accepted \u2014 it is not bound to this execution; record that as \`test-run:<path>\` ` +
1869
- `evidence instead, or drop minCount if an exit code is the guarantee you want.`);
1965
+ const flag = /\b(?:node|tsx)\b.*\s--test(?![\w-])/.test(invoked)
1966
+ ? '--test-reporter=tap'
1967
+ : /jest/.test(invoked)
1968
+ ? '--json'
1969
+ : /vitest|pnpm|npm|yarn|bun/.test(invoked)
1970
+ ? '--reporter=json'
1971
+ : '<your runner\u2019s JSON reporter flag>';
1972
+ const found = refusal === undefined
1973
+ ? `\`${invoked}\` emitted no machine-readable test report`
1974
+ : `\`${invoked}\` emitted a test report that was refused: ${refusal}`;
1975
+ return (`minCount ${gate.minCount} cannot be proved: ${found}, and an exit code alone carries no ` +
1976
+ `count. Add a reporter to the gate command itself (e.g. \`${invoked} ${flag}\`) so the run ` +
1977
+ `that is being attested is the run that is counted. Accepted: a full Vitest/Jest JSON report ` +
1978
+ `(numTotalTests, numPassedTests, numFailedTests, numPendingTests, numTodoTests, the four ` +
1979
+ `numTotal/Passed/Failed/PendingTestSuites counters, success, testResults[].assertionResults, ` +
1980
+ `counters equal to the assertions); a bare summary as the LAST stdout line, at minimum ` +
1981
+ `{"numPassedTests":N} (numFailedTests, numTotalTests and success optional, no testResults); ` +
1982
+ `or node:test TAP (--test-reporter=tap) with its 1..N plan and # tests/# pass/# fail summary. ` +
1983
+ `A report file this run writes (its --outputFile, or ${REDIRECTED_JSON_REPORT}) is read too, ` +
1984
+ `but one produced by a separate invocation is deliberately not accepted \u2014 it is not bound ` +
1985
+ `to this execution; record that as \`test-run:<path>\` evidence instead, or drop minCount if ` +
1986
+ `an exit code is the guarantee you want.`);
1870
1987
  }
1871
1988
  /**
1872
1989
  * Zero-count runner summaries that name failure without reporting any: node:test
@@ -1917,13 +2034,15 @@ async function runTestGate(gate, index, projectRoot, timeoutMs, context) {
1917
2034
  const announced = await announcedReportFile(captured.stdout, projectRoot);
1918
2035
  if (announced !== null && !before.has(announced))
1919
2036
  before.set(announced, null);
1920
- const counts = structuredTestCounts(captured) ?? (await freshReportCounts(before, startedAt));
2037
+ const refusals = [];
2038
+ const counts = structuredTestCounts(captured, refusals) ??
2039
+ (await freshReportCounts(before, startedAt, refusals));
1921
2040
  // T12308: the counts come from this run's own validated report; only their
1922
2041
  // ABSENCE is an error, because inferring a count from exit zero is the thing
1923
2042
  // that must not happen. T13753: the error keeps the run's execution record.
1924
2043
  if (gate.minCount !== undefined && gate.minCount > 0) {
1925
2044
  if (counts === null)
1926
- return processGateResult(index, gate, captured, 'error', describeMissingTestCount(gate));
2045
+ return processGateResult(index, gate, captured, 'error', describeMissingTestCount(gate, refusals[0]));
1927
2046
  if (counts.numPassedTests < gate.minCount)
1928
2047
  return processGateResult(index, gate, captured, 'fail', `Structured report counts ${counts.numPassedTests} passing tests, below the required minimum of ${gate.minCount}`);
1929
2048
  }