@cleocode/core 2026.10.3 → 2026.10.4

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 (210) hide show
  1. package/dist/build-provenance.json +2 -2
  2. package/dist/cloud/nexus-enrol.d.ts +9 -0
  3. package/dist/cloud/nexus-enrol.d.ts.map +1 -1
  4. package/dist/cloud/nexus-enrol.js +45 -2
  5. package/dist/cloud/nexus-enrol.js.map +1 -1
  6. package/dist/cloud/nexus-first-run.d.ts +142 -0
  7. package/dist/cloud/nexus-first-run.d.ts.map +1 -0
  8. package/dist/cloud/nexus-first-run.js +352 -0
  9. package/dist/cloud/nexus-first-run.js.map +1 -0
  10. package/dist/cloud/nexus-project-names.d.ts +173 -0
  11. package/dist/cloud/nexus-project-names.d.ts.map +1 -0
  12. package/dist/cloud/nexus-project-names.js +314 -0
  13. package/dist/cloud/nexus-project-names.js.map +1 -0
  14. package/dist/cloud/nexus-vault-keys.d.ts +33 -2
  15. package/dist/cloud/nexus-vault-keys.d.ts.map +1 -1
  16. package/dist/cloud/nexus-vault-keys.js +132 -12
  17. package/dist/cloud/nexus-vault-keys.js.map +1 -1
  18. package/dist/dispatch/contracts/derive-output-contract.d.ts +1 -1
  19. package/dist/dispatch/contracts/derive-output-contract.d.ts.map +1 -1
  20. package/dist/dispatch/contracts/derive-output-contract.js +2 -1
  21. package/dist/dispatch/contracts/derive-output-contract.js.map +1 -1
  22. package/dist/dispatch/contracts/output-contracts.d.ts +2 -1
  23. package/dist/dispatch/contracts/output-contracts.d.ts.map +1 -1
  24. package/dist/dispatch/contracts/output-contracts.js +1 -1
  25. package/dist/dispatch/contracts/output-contracts.js.map +1 -1
  26. package/dist/dispatch/mvi-projection.d.ts +1 -1
  27. package/dist/dispatch/mvi-projection.d.ts.map +1 -1
  28. package/dist/dispatch/mvi-projection.js +1 -1
  29. package/dist/dispatch/mvi-projection.js.map +1 -1
  30. package/dist/docs/export-document.js +24462 -24572
  31. package/dist/docs/export-document.js.map +3 -3
  32. package/dist/doctor/db-substrate.d.ts +6 -9
  33. package/dist/doctor/db-substrate.d.ts.map +1 -1
  34. package/dist/doctor/db-substrate.js +10 -14
  35. package/dist/doctor/db-substrate.js.map +1 -1
  36. package/dist/doctor/migrations.d.ts +18 -0
  37. package/dist/doctor/migrations.d.ts.map +1 -1
  38. package/dist/doctor/migrations.js +54 -2
  39. package/dist/doctor/migrations.js.map +1 -1
  40. package/dist/error-catalog.js +1 -1
  41. package/dist/error-catalog.js.map +1 -1
  42. package/dist/errors.d.ts +1 -1
  43. package/dist/errors.d.ts.map +1 -1
  44. package/dist/errors.js +1 -1
  45. package/dist/errors.js.map +1 -1
  46. package/dist/init.d.ts.map +1 -1
  47. package/dist/init.js +21 -5
  48. package/dist/init.js.map +1 -1
  49. package/dist/llm/conversation.d.ts.map +1 -1
  50. package/dist/llm/conversation.js +15 -4
  51. package/dist/llm/conversation.js.map +1 -1
  52. package/dist/llm/plugin-facade.js +277 -376
  53. package/dist/llm/plugin-facade.js.map +3 -3
  54. package/dist/llm/transports/bedrock.d.ts +1 -0
  55. package/dist/llm/transports/bedrock.d.ts.map +1 -1
  56. package/dist/llm/transports/bedrock.js +30 -12
  57. package/dist/llm/transports/bedrock.js.map +1 -1
  58. package/dist/memory/decision-contradiction.d.ts.map +1 -1
  59. package/dist/memory/decision-contradiction.js +10 -5
  60. package/dist/memory/decision-contradiction.js.map +1 -1
  61. package/dist/memory/dialectic-evaluator.d.ts.map +1 -1
  62. package/dist/memory/dialectic-evaluator.js +4 -1
  63. package/dist/memory/dialectic-evaluator.js.map +1 -1
  64. package/dist/memory/transcript-extractor.d.ts.map +1 -1
  65. package/dist/memory/transcript-extractor.js +3 -2
  66. package/dist/memory/transcript-extractor.js.map +1 -1
  67. package/dist/metrics/token-service.d.ts +16 -0
  68. package/dist/metrics/token-service.d.ts.map +1 -1
  69. package/dist/metrics/token-service.js +18 -0
  70. package/dist/metrics/token-service.js.map +1 -1
  71. package/dist/nexus/api-contracts.d.ts.map +1 -1
  72. package/dist/nexus/api-contracts.js +27 -11
  73. package/dist/nexus/api-contracts.js.map +1 -1
  74. package/dist/nexus/api-extractors/http-extractor.d.ts +2 -2
  75. package/dist/nexus/api-extractors/http-extractor.d.ts.map +1 -1
  76. package/dist/nexus/api-extractors/http-extractor.js +3 -3
  77. package/dist/nexus/api-extractors/http-extractor.js.map +1 -1
  78. package/dist/nexus/clusters.js +1 -1
  79. package/dist/nexus/clusters.js.map +1 -1
  80. package/dist/nexus/diff.d.ts +1 -1
  81. package/dist/nexus/diff.d.ts.map +1 -1
  82. package/dist/nexus/diff.js +3 -2
  83. package/dist/nexus/diff.js.map +1 -1
  84. package/dist/nexus/flows.js +1 -1
  85. package/dist/nexus/flows.js.map +1 -1
  86. package/dist/nexus/identity.d.ts +8 -0
  87. package/dist/nexus/identity.d.ts.map +1 -1
  88. package/dist/nexus/identity.js +17 -1
  89. package/dist/nexus/identity.js.map +1 -1
  90. package/dist/nexus/index.d.ts +1 -1
  91. package/dist/nexus/index.d.ts.map +1 -1
  92. package/dist/nexus/index.js +2 -2
  93. package/dist/nexus/index.js.map +1 -1
  94. package/dist/nexus/nexus-bridge.d.ts.map +1 -1
  95. package/dist/nexus/nexus-bridge.js +5 -5
  96. package/dist/nexus/nexus-bridge.js.map +1 -1
  97. package/dist/nexus/registry.d.ts +22 -0
  98. package/dist/nexus/registry.d.ts.map +1 -1
  99. package/dist/nexus/registry.js +76 -1
  100. package/dist/nexus/registry.js.map +1 -1
  101. package/dist/paths.js +1 -1
  102. package/dist/paths.js.map +1 -1
  103. package/dist/project-scope.js +1 -1
  104. package/dist/project-scope.js.map +1 -1
  105. package/dist/project-tombstone.js +1 -1
  106. package/dist/project-tombstone.js.map +1 -1
  107. package/dist/release/open.d.ts +3 -6
  108. package/dist/release/open.d.ts.map +1 -1
  109. package/dist/release/open.js +59 -23
  110. package/dist/release/open.js.map +1 -1
  111. package/dist/release/preflight-skip.d.ts +69 -10
  112. package/dist/release/preflight-skip.d.ts.map +1 -1
  113. package/dist/release/preflight-skip.js +195 -47
  114. package/dist/release/preflight-skip.js.map +1 -1
  115. package/dist/render/colors.js +1 -19
  116. package/dist/render/colors.js.map +1 -1
  117. package/dist/render/tasks/colors.js +1 -1
  118. package/dist/render/tasks/colors.js.map +1 -1
  119. package/dist/resources/governor.d.ts +12 -0
  120. package/dist/resources/governor.d.ts.map +1 -1
  121. package/dist/resources/governor.js +5 -1
  122. package/dist/resources/governor.js.map +1 -1
  123. package/dist/resources/heavy-command-hook-delivery.d.ts +144 -0
  124. package/dist/resources/heavy-command-hook-delivery.d.ts.map +1 -0
  125. package/dist/resources/heavy-command-hook-delivery.js +204 -0
  126. package/dist/resources/heavy-command-hook-delivery.js.map +1 -0
  127. package/dist/resources/heavy-command.d.ts +69 -0
  128. package/dist/resources/heavy-command.d.ts.map +1 -1
  129. package/dist/resources/heavy-command.js +479 -7
  130. package/dist/resources/heavy-command.js.map +1 -1
  131. package/dist/resources/run-class.d.ts.map +1 -1
  132. package/dist/resources/run-class.js +1 -0
  133. package/dist/resources/run-class.js.map +1 -1
  134. package/dist/routing/build-command-groups.d.ts +1 -1
  135. package/dist/routing/build-command-groups.d.ts.map +1 -1
  136. package/dist/routing/build-command-groups.js +4 -1
  137. package/dist/routing/build-command-groups.js.map +1 -1
  138. package/dist/scaffold/ensure-skills.d.ts.map +1 -1
  139. package/dist/scaffold/ensure-skills.js +58 -2
  140. package/dist/scaffold/ensure-skills.js.map +1 -1
  141. package/dist/selfimprove/fix-gen.js +277 -376
  142. package/dist/selfimprove/fix-gen.js.map +3 -3
  143. package/dist/sessions/briefing.d.ts.map +1 -1
  144. package/dist/sessions/briefing.js +11 -0
  145. package/dist/sessions/briefing.js.map +1 -1
  146. package/dist/store/dual-scope-db.d.ts.map +1 -1
  147. package/dist/store/dual-scope-db.js +6 -1
  148. package/dist/store/dual-scope-db.js.map +1 -1
  149. package/dist/store/table-classification.d.ts +27 -0
  150. package/dist/store/table-classification.d.ts.map +1 -1
  151. package/dist/store/table-classification.js +32 -0
  152. package/dist/store/table-classification.js.map +1 -1
  153. package/dist/store/vault-manifest.d.ts +5 -1
  154. package/dist/store/vault-manifest.d.ts.map +1 -1
  155. package/dist/store/vault-manifest.js +9 -2
  156. package/dist/store/vault-manifest.js.map +1 -1
  157. package/dist/system/health.d.ts +13 -0
  158. package/dist/system/health.d.ts.map +1 -1
  159. package/dist/system/health.js +96 -1
  160. package/dist/system/health.js.map +1 -1
  161. package/dist/tasks/affected-packages.d.ts +20 -7
  162. package/dist/tasks/affected-packages.d.ts.map +1 -1
  163. package/dist/tasks/affected-packages.js +39 -13
  164. package/dist/tasks/affected-packages.js.map +1 -1
  165. package/dist/tasks/affected-template.d.ts +93 -0
  166. package/dist/tasks/affected-template.d.ts.map +1 -0
  167. package/dist/tasks/affected-template.js +198 -0
  168. package/dist/tasks/affected-template.js.map +1 -0
  169. package/dist/tasks/command-line.d.ts +4 -1
  170. package/dist/tasks/command-line.d.ts.map +1 -1
  171. package/dist/tasks/command-line.js +7 -2
  172. package/dist/tasks/command-line.js.map +1 -1
  173. package/dist/tasks/done-plan.d.ts.map +1 -1
  174. package/dist/tasks/done-plan.js +12 -2
  175. package/dist/tasks/done-plan.js.map +1 -1
  176. package/dist/tasks/duplicate-detector.d.ts.map +1 -1
  177. package/dist/tasks/duplicate-detector.js +11 -5
  178. package/dist/tasks/duplicate-detector.js.map +1 -1
  179. package/dist/tasks/evidence.d.ts.map +1 -1
  180. package/dist/tasks/evidence.js +185 -11
  181. package/dist/tasks/evidence.js.map +1 -1
  182. package/dist/tasks/heavy-tool-env.d.ts +385 -18
  183. package/dist/tasks/heavy-tool-env.d.ts.map +1 -1
  184. package/dist/tasks/heavy-tool-env.js +719 -40
  185. package/dist/tasks/heavy-tool-env.js.map +1 -1
  186. package/dist/tasks/index.d.ts +2 -2
  187. package/dist/tasks/index.d.ts.map +1 -1
  188. package/dist/tasks/index.js +1 -1
  189. package/dist/tasks/index.js.map +1 -1
  190. package/dist/tasks/tool-cache-env.d.ts +20 -13
  191. package/dist/tasks/tool-cache-env.d.ts.map +1 -1
  192. package/dist/tasks/tool-cache-env.js +27 -48
  193. package/dist/tasks/tool-cache-env.js.map +1 -1
  194. package/dist/tasks/tool-cache.d.ts +8 -0
  195. package/dist/tasks/tool-cache.d.ts.map +1 -1
  196. package/dist/tasks/tool-cache.js +19 -6
  197. package/dist/tasks/tool-cache.js.map +1 -1
  198. package/dist/tasks/tool-semaphore.d.ts +66 -23
  199. package/dist/tasks/tool-semaphore.d.ts.map +1 -1
  200. package/dist/tasks/tool-semaphore.js +96 -34
  201. package/dist/tasks/tool-semaphore.js.map +1 -1
  202. package/dist/upgrade.d.ts.map +1 -1
  203. package/dist/upgrade.js +37 -4
  204. package/dist/upgrade.js.map +1 -1
  205. package/dist/validation/doctor/checks.d.ts +17 -0
  206. package/dist/validation/doctor/checks.d.ts.map +1 -1
  207. package/dist/validation/doctor/checks.js +83 -0
  208. package/dist/validation/doctor/checks.js.map +1 -1
  209. package/package.json +13 -13
  210. package/schemas/project-context.schema.json +5 -1
@@ -28,19 +28,51 @@
28
28
  * |---|---|---|
29
29
  * | `NODE_OPTIONS=--max-old-space-size=N` | Heap ceiling for EVERY node process in the tree, inherited | node docs; appended, never clobbered |
30
30
  * | `VITEST_MAX_WORKERS=N` | `if (process.env.VITEST_MAX_WORKERS) resolved.maxWorkers = parseInt(...)` — overrides the resolved config, so it binds projects that set their own | read out of vitest 4.1.4 `dist/chunks/coverage.*.js` |
31
- * | `npm_config_workspace_concurrency=N` | Bounds `pnpm -r` fan-out across workspace packages | `npm_config_workspace_concurrency=1 pnpm config get workspace-concurrency` → `1` |
31
+ * | `npm_config_workspace_concurrency=N` / `pnpm_config_workspace_concurrency=N` | Bounds `pnpm -r` fan-out across workspace packages (pnpm 10 reads the first, pnpm 11+ the second) | `npm_config_workspace_concurrency=1 pnpm config get workspace-concurrency` → `1` on pnpm 10.30; `pnpm_config_…` → `1` on pnpm 12.6 (T13122) |
32
32
  *
33
33
  * Together these bound the product the semaphore could not see:
34
34
  * `packages in flight × workers per run × heap per worker`.
35
35
  *
36
- * Applied ONLY to `test` / `build`. Capping `lint` or `typecheck` would
37
- * serialise cheap single-process work for no benefit.
36
+ * The worker levers apply ONLY to `test` / `build`, the tools that fork.
37
+ * `typecheck` and `lint` are single processes, but not cheap ones: one
38
+ * TypeScript program on a large monorepo holds 2–5 GB (a live `tsc --noEmit`
39
+ * held 4.7 GB on 2026-10-03), so since T13123 they get the heap ceiling and the
40
+ * workspace-concurrency bound too ({@link isMemoryBoundTool}), and no worker
41
+ * variables, which nothing they run reads.
38
42
  *
39
- * A project that genuinely wants more can set any of these itself — an existing
40
- * value is always respected, because a deliberate setting beats our default.
43
+ * ## An inherited value can tighten the plan, never loosen it (T13122)
44
+ *
45
+ * The overlay is merged over the CALLER's environment: whatever the shell
46
+ * profile, the agent harness or a parent process exported. Until T13122 an
47
+ * inherited value always won, on the theory that "a deliberate setting beats our
48
+ * default". A shell profile is not a per-project decision: on 2026-10-03 a
49
+ * `~/.zprofile` export of `NODE_OPTIONS=--max-old-space-size=8192` reached a
50
+ * `cleo verify --evidence tool:test`, and the run got 6 workers × 8 GiB = all of
51
+ * a 48 GiB Mac, because the worker count was sized for a 4 GiB heap it was not
52
+ * getting.
53
+ *
54
+ * So the run has a heap budget — the default worker count times the default heap
55
+ * ({@link heavyRunBudgetMb}) — and the overlay is planned against it
56
+ * ({@link planHeavyToolEnv}):
57
+ *
58
+ * - an inherited `NODE_OPTIONS` heap that fits the budget is kept, and the
59
+ * worker count shrinks so `workers × heap` still fits; one above the budget
60
+ * is clamped to it;
61
+ * - an inherited worker count or workspace concurrency at or below the plan
62
+ * is kept; one above it is clamped;
63
+ * - only an explicit CLEO override asks for more: `CLEO_HEAVY_HEAP_MB`,
64
+ * `CLEO_HEAVY_WORKERS`, `CLEO_HEAVY_WORKSPACE_CONCURRENCY`.
65
+ *
66
+ * A project that wants more for its own suite still sets it in its own script
67
+ * (`"test": "NODE_OPTIONS=… vitest run"`) or config: that runs below the
68
+ * overlay and is untouched by it. The plan, and every value it clamped, is
69
+ * reported by `cleo verify` and `cleo run`.
41
70
  *
42
71
  * @task T12096
72
+ * @task T13122
73
+ * @task T13123
43
74
  */
75
+ import type { HeavyToolResourcePlan } from '@cleocode/contracts';
44
76
  import type { CanonicalTool } from './tool-resolver.js';
45
77
  /**
46
78
  * Heap ceiling per node process, in MiB.
@@ -64,8 +96,94 @@ export declare const MIN_HEAVY_WORKERS = 1;
64
96
  * memory-bound box does not finish at all.
65
97
  */
66
98
  export declare const WORKSPACE_CONCURRENCY = 1;
99
+ /**
100
+ * The default heap never drops below this, in MiB, however small the machine —
101
+ * one worker must be able to run a real suite.
102
+ *
103
+ * @task T13122
104
+ */
105
+ export declare const MIN_HEAVY_HEAP_MB = 1024;
106
+ /**
107
+ * Fraction of total RAM the DEFAULT heap may reach. {@link HEAVY_TOOL_HEAP_MB}
108
+ * on an 8 GiB laptop is half the machine; on a 4 GiB box it would be all of it,
109
+ * which is no ceiling at all. Machines of 8 GiB and up are unaffected.
110
+ *
111
+ * @task T13122
112
+ */
113
+ export declare const HEAVY_HEAP_RAM_FRACTION = 0.5;
114
+ /**
115
+ * Explicit heap ceiling for heavy tools, in MiB. The only way to ask for a heap
116
+ * above the run's budget: unlike an inherited `NODE_OPTIONS`, it is never
117
+ * clamped.
118
+ *
119
+ * @task T13122
120
+ */
121
+ export declare const HEAVY_HEAP_ENV = "CLEO_HEAVY_HEAP_MB";
122
+ /**
123
+ * Explicit worker count for heavy tools. Replaces the planned count for every
124
+ * runner variable, even when that puts the run over its budget.
125
+ *
126
+ * @task T13122
127
+ */
128
+ export declare const HEAVY_WORKERS_ENV = "CLEO_HEAVY_WORKERS";
129
+ /**
130
+ * Explicit workspace concurrency for heavy tools (`pnpm -r` packages in flight).
131
+ *
132
+ * @task T13122
133
+ */
134
+ export declare const HEAVY_WORKSPACE_CONCURRENCY_ENV = "CLEO_HEAVY_WORKSPACE_CONCURRENCY";
135
+ /**
136
+ * The two spellings of pnpm's `workspace-concurrency` in the environment. pnpm
137
+ * 10 reads only `npm_config_workspace_concurrency`; pnpm 11+ reads only
138
+ * `pnpm_config_workspace_concurrency` (measured: pnpm 10.30.0 and 12.6.0 each
139
+ * report `undefined` for the other spelling). Setting one bounded `pnpm -r`
140
+ * fan-out on one pnpm major and silently nothing on the other, so the overlay
141
+ * sets both — for every launcher, because an `npm test` script that runs
142
+ * `pnpm -r` still reads them. Both are read case-insensitively, and an
143
+ * uppercase spelling outranks the lowercase one, so an inherited
144
+ * `NPM_CONFIG_WORKSPACE_CONCURRENCY` is planned and overlaid as well
145
+ * ({@link workspaceConcurrencyNames}).
146
+ *
147
+ * @task T13122
148
+ */
149
+ export declare const WORKSPACE_CONCURRENCY_VARS: readonly ["npm_config_workspace_concurrency", "pnpm_config_workspace_concurrency"];
150
+ /**
151
+ * Every environment name that sets pnpm's workspace concurrency in `env`: the
152
+ * two canonical spellings, plus any case or dash variant of them present (pnpm
153
+ * reads these case-insensitively, uppercase first, and `workspace-concurrency`
154
+ * with a dash as readily).
155
+ *
156
+ * @param env - The caller's environment.
157
+ * @returns The names to plan and overlay, canonical first.
158
+ * @task T13122
159
+ */
160
+ export declare function workspaceConcurrencyNames(env: NodeJS.ProcessEnv): string[];
161
+ /**
162
+ * V8 young-generation (semi-space) ceiling a plan allows, in MiB: Node 24's own
163
+ * default on a 64-bit host. `heap_size_limit` is old space plus three
164
+ * semi-spaces (measured on Node 24: `--max-old-space-size=4096` with
165
+ * `--max-semi-space-size=4096` reports 16384 MiB), so an inherited large
166
+ * semi-space would multiply the planned heap without touching the old-space
167
+ * flag; above this it is clamped.
168
+ *
169
+ * @task T13122
170
+ */
171
+ export declare const MAX_SEMI_SPACE_MB = 64;
67
172
  /** Environment overlay to merge into a heavy tool's spawn env. */
68
173
  export type HeavyToolEnv = Readonly<Record<string, string>>;
174
+ /**
175
+ * The overlay for one heavy or memory-bound tool spawn, with the plan behind it
176
+ * (T13122).
177
+ *
178
+ * `resources` is `null` for a tool that is not memory-bound, whose overlay is
179
+ * empty.
180
+ */
181
+ export interface HeavyToolSpawnPlan {
182
+ /** Variables to merge over the caller's environment. */
183
+ readonly overlay: HeavyToolEnv;
184
+ /** What was chosen and why; `null` when the tool is not heavy. */
185
+ readonly resources: HeavyToolResourcePlan | null;
186
+ }
69
187
  /**
70
188
  * Whether a canonical tool is heavy enough to need bounding.
71
189
  *
@@ -87,19 +205,225 @@ export type HeavyToolEnv = Readonly<Record<string, string>>;
87
205
  */
88
206
  export declare function isHeavyTool(canonical: CanonicalTool): boolean;
89
207
  /**
90
- * Worker count this machine can hold, given {@link GIB_PER_WORKER}.
208
+ * Whether a canonical tool's memory is bounded: a heap ceiling and workspace
209
+ * concurrency in its spawn env, and a RAM-derived machine-wide slot count that
210
+ * shrinks under pressure.
211
+ *
212
+ * A superset of {@link isHeavyTool}. `typecheck` and `lint` were treated as
213
+ * cheap (`max(2, cpus/2)` slots, no ceiling) until T13123: nine concurrent
214
+ * `tsc` runs of 2–5 GB each on an 18-core box is most of 48 GB. `audit` and
215
+ * `security-scan` stay unbounded — they are network-bound and small.
216
+ *
217
+ * @param canonical - the tool in question.
218
+ * @returns `true` for `test`, `build`, `typecheck` and `lint`.
219
+ *
220
+ * @example
221
+ * ```ts
222
+ * isMemoryBoundTool('typecheck'); // true
223
+ * isMemoryBoundTool('audit'); // false
224
+ * ```
225
+ *
226
+ * @task T13123
227
+ */
228
+ export declare function isMemoryBoundTool(canonical: CanonicalTool): boolean;
229
+ /**
230
+ * Default worker count this machine can hold, given {@link GIB_PER_WORKER}.
231
+ *
232
+ * The planned count ({@link planHeavyToolEnv}) never exceeds this: a small
233
+ * inherited heap does not buy extra workers, because each worker also costs
234
+ * memory outside its heap.
91
235
  *
92
236
  * @param totalRamGib - total RAM in GiB; defaults to a live reading.
93
237
  * @returns a value in `[MIN_HEAVY_WORKERS, MAX_HEAVY_WORKERS]`.
94
238
  */
95
239
  export declare function heavyToolWorkers(totalRamGib?: number): number;
96
240
  /**
97
- * Append `--max-old-space-size` to an existing `NODE_OPTIONS`, or create it.
241
+ * Default heap ceiling per Node process, in MiB: {@link HEAVY_TOOL_HEAP_MB},
242
+ * lowered to {@link HEAVY_HEAP_RAM_FRACTION} of RAM on a machine under 8 GiB
243
+ * (never below {@link MIN_HEAVY_HEAP_MB}).
244
+ *
245
+ * @param totalRamGib - total RAM in GiB; defaults to a live reading.
246
+ * @returns the default heap in MiB.
247
+ *
248
+ * @example
249
+ * ```ts
250
+ * defaultHeavyHeapMb(64); // → 4096
251
+ * defaultHeavyHeapMb(4); // → 2048
252
+ * ```
253
+ *
254
+ * @task T13122
255
+ */
256
+ export declare function defaultHeavyHeapMb(totalRamGib?: number): number;
257
+ /**
258
+ * Default heap ceiling for a single-process tool (`typecheck`, `lint`), in MiB:
259
+ * {@link defaultHeavyHeapMb}, but never above a quarter of RAM — V8's own
260
+ * default old space on a machine under 16 GiB (measured 4288 MiB with no flags
261
+ * on a 64 GiB host, the capped default) — so the plan never RAISES a `tsc`'s
262
+ * ceiling on a small machine (review of #1810). Never below
263
+ * {@link MIN_HEAVY_HEAP_MB}.
264
+ *
265
+ * @param totalRamGib - total RAM in GiB; defaults to a live reading.
266
+ * @returns the default heap in MiB.
267
+ *
268
+ * @example
269
+ * ```ts
270
+ * defaultSingleProcessHeapMb(64); // → 4096
271
+ * defaultSingleProcessHeapMb(8); // → 2048
272
+ * ```
273
+ *
274
+ * @task T13123
275
+ */
276
+ export declare function defaultSingleProcessHeapMb(totalRamGib?: number): number;
277
+ /**
278
+ * Heap budget for one heavy run, in MiB: the default worker count times the
279
+ * default heap. `workspace concurrency × workers × heap` must fit in it.
280
+ *
281
+ * Unchanged by T13122 for the default case (6 × 4096 = 24 GiB on 36 GiB and
282
+ * up, 1 × 4096 on 8 GiB); what changed is that an inherited heap is now planned
283
+ * against it instead of multiplying it.
98
284
  *
99
- * Never clobbers: a project may legitimately set `--experimental-*` flags there,
100
- * and dropping them would break the very command we are trying to run. An
101
- * existing `--max-old-space-size` is left alone — an explicit choice outranks
102
- * our default.
285
+ * @param totalRamGib - total RAM in GiB; defaults to a live reading.
286
+ * @returns the budget in MiB.
287
+ *
288
+ * @example
289
+ * ```ts
290
+ * heavyRunBudgetMb(64); // → 24576 (6 workers × 4096)
291
+ * heavyRunBudgetMb(16); // → 8192 (2 workers × 4096)
292
+ * heavyRunBudgetMb(8); // → 4096 (1 worker × 4096)
293
+ * ```
294
+ *
295
+ * @task T13122
296
+ */
297
+ export declare function heavyRunBudgetMb(totalRamGib?: number): number;
298
+ /**
299
+ * `NODE_OPTIONS` flags that set a V8 heap limit. `max-old-space-size` and its
300
+ * percentage form decide the old-space ceiling; `max-semi-space-size` sizes the
301
+ * young generation, three of which count toward the limit, and is capped at
302
+ * {@link MAX_SEMI_SPACE_MB}.
303
+ *
304
+ * @task T12989
305
+ * @task T13122
306
+ */
307
+ export declare const HEAP_FLAG_NAMES: ReadonlySet<string>;
308
+ /**
309
+ * The V8 heap flags a `NODE_OPTIONS` value sets, by name, with the value in
310
+ * effect.
311
+ *
312
+ * V8 reads flags left to right and a later value replaces an earlier one, so
313
+ * the LAST occurrence of each flag is the effective one. Underscores in a flag
314
+ * name read as dashes, as they do to V8, and the space-separated spelling
315
+ * (`--max-old-space-size 4096`) is read too.
316
+ *
317
+ * @param nodeOptions - A `NODE_OPTIONS` value, if any.
318
+ * @returns flag name → effective value, in first-seen order.
319
+ *
320
+ * @task T12989
321
+ * @task T13122
322
+ */
323
+ export declare function parseHeapFlags(nodeOptions: string | undefined): ReadonlyMap<string, string>;
324
+ /**
325
+ * The old-space heap ceiling a `NODE_OPTIONS` value asks for, in MiB, or
326
+ * `null` when it sets none (or sets one Node could not use).
327
+ *
328
+ * `--max-old-space-size-percentage` wins over `--max-old-space-size` whatever
329
+ * their order (measured on Node 24.21: `=10` beside `=2048` gave a 6745 MiB
330
+ * limit on a 64 GiB machine either way round), and resolves against total RAM.
331
+ *
332
+ * @param nodeOptions - A `NODE_OPTIONS` value, if any.
333
+ * @param totalRamMb - Total RAM in MiB, for the percentage form.
334
+ * @returns the requested heap in MiB, or `null`.
335
+ *
336
+ * @example
337
+ * ```ts
338
+ * inheritedHeapMb('--max-old-space-size=8192', 65536); // → 8192
339
+ * inheritedHeapMb('--max-old-space-size-percentage=25', 65536); // → 16384
340
+ * inheritedHeapMb('--enable-source-maps', 65536); // → null
341
+ * ```
342
+ *
343
+ * @task T13122
344
+ */
345
+ export declare function inheritedHeapMb(nodeOptions: string | undefined, totalRamMb: number): number | null;
346
+ /**
347
+ * Set the old-space heap ceiling in a `NODE_OPTIONS` value: every existing
348
+ * `--max-old-space-size` and `--max-old-space-size-percentage` is cut out and
349
+ * one `--max-old-space-size=<heapMb>` appended. Every other byte survives — a
350
+ * project may rely on `--experimental-*` or a quoted `--require` path there.
351
+ *
352
+ * Removing the percentage form is required, not tidiness: it outranks the size
353
+ * form whatever the order, so leaving it would silently undo the ceiling.
354
+ *
355
+ * @param existing - current `NODE_OPTIONS`, if any.
356
+ * @param heapMb - ceiling to apply.
357
+ * @returns the rewritten value.
358
+ *
359
+ * @example
360
+ * ```ts
361
+ * withHeapCeiling('--enable-source-maps --max-old-space-size=8192', 4096);
362
+ * // → '--enable-source-maps --max-old-space-size=4096'
363
+ * ```
364
+ *
365
+ * @task T13122
366
+ */
367
+ export declare function withHeapCeiling(existing: string | undefined, heapMb: number): string;
368
+ /**
369
+ * Cap the semi-space (young generation) flag of a `NODE_OPTIONS` value at
370
+ * {@link MAX_SEMI_SPACE_MB}: a larger `--max-semi-space-size` is cut out and the
371
+ * cap appended. A value at or under the cap is left alone.
372
+ *
373
+ * @param existing - `NODE_OPTIONS`, if any.
374
+ * @returns The value to use, and the inherited semi-space it clamped (or `null`).
375
+ *
376
+ * @example
377
+ * ```ts
378
+ * withSemiSpaceCap('--max-semi-space-size=4096'); // → { value: '--max-semi-space-size=64', clampedFrom: 4096 }
379
+ * ```
380
+ *
381
+ * @task T13122
382
+ */
383
+ export declare function withSemiSpaceCap(existing: string | undefined): {
384
+ value: string | undefined;
385
+ clampedFrom: number | null;
386
+ };
387
+ /**
388
+ * Bound an inherited `MAKEFLAGS` to `workers` jobs.
389
+ *
390
+ * Absent: `-j<workers>` (GNU make sizes a bare `-j` off nproc). Carrying a
391
+ * jobserver (`--jobserver-auth=` / `--jobserver-fds=`): kept, since inside a
392
+ * `make` recipe the parent's jobserver already bounds the jobs. Otherwise any
393
+ * `-j`, `-jN`, `--jobs[=N]`, a short cluster ending in j (`-sj18`) or make's
394
+ * dash-less first word (`j18`) above `workers` (a bare one is unlimited) is
395
+ * replaced by `-j<workers>`, keeping every other flag — a profile-wide
396
+ * `export MAKEFLAGS=-j18` no longer outruns the plan.
397
+ *
398
+ * @param raw - The inherited `MAKEFLAGS`.
399
+ * @param workers - The planned worker count.
400
+ * @returns The value to set, or `null` to keep the inherited one.
401
+ * @task T13122
402
+ */
403
+ export declare function boundMakeflags(raw: string | undefined, workers: number): string | null;
404
+ /**
405
+ * Remove npm's `Unknown env config` warnings from captured output.
406
+ *
407
+ * npm warns once per run for every `npm_config_*` variable it does not know,
408
+ * including `npm_config_workspace_concurrency`, which the overlay sets for the
409
+ * `pnpm -r` an `npm test` script may run. The warning would otherwise sit in
410
+ * the stderr tail CLEO quotes when a tool fails and push the real error out of
411
+ * it; the variable itself stays, because dropping it for npm unbounded those
412
+ * child `pnpm -r` runs (review of #1808).
413
+ *
414
+ * @param text - Captured stderr.
415
+ * @returns The text without those warning lines.
416
+ * @task T13122
417
+ */
418
+ export declare function withoutNpmEnvConfigWarnings(text: string): string;
419
+ /**
420
+ * Append `--max-old-space-size` to an existing `NODE_OPTIONS`, or create it,
421
+ * leaving an existing `--max-old-space-size` alone.
422
+ *
423
+ * @deprecated Since T13122 the heavy-tool overlay plans the heap against the
424
+ * run's budget instead of letting any inherited value win; use
425
+ * {@link planHeavyToolEnv} (or {@link withHeapCeiling} to set a ceiling).
426
+ * Kept for SDK consumers.
103
427
  *
104
428
  * @param existing - current `NODE_OPTIONS`, if any.
105
429
  * @param heapMb - ceiling to apply.
@@ -107,26 +431,69 @@ export declare function heavyToolWorkers(totalRamGib?: number): number;
107
431
  */
108
432
  export declare function mergeNodeOptions(existing: string | undefined, heapMb: number): string;
109
433
  /**
110
- * Build the environment overlay for a heavy tool spawn.
434
+ * Plan a heavy or memory-bound tool spawn: the environment overlay, and the
435
+ * resource plan behind it (T13122, T13123).
436
+ *
437
+ * The heap is chosen first — `CLEO_HEAVY_HEAP_MB`, else the inherited
438
+ * `NODE_OPTIONS` heap when it fits the budget (clamped to it otherwise), else
439
+ * {@link defaultHeavyHeapMb}. The worker count then derives from the heap
440
+ * actually in effect, `⌊budget / (packages × heap)⌋`, never above
441
+ * {@link heavyToolWorkers}, so `packages × workers × heap` stays within
442
+ * {@link heavyRunBudgetMb}. Inherited worker counts and workspace concurrency
443
+ * are kept at or below the plan and clamped above it; `CLEO_HEAVY_WORKERS` and
444
+ * `CLEO_HEAVY_WORKSPACE_CONCURRENCY` override.
445
+ *
446
+ * A single-process memory-bound tool (`typecheck`, `lint`) gets the same heap
447
+ * ceiling and workspace concurrency, and no worker variables: its plan is one
448
+ * process (T13123).
449
+ *
450
+ * @param canonical - the canonical tool about to be spawned.
451
+ * @param env - the environment the child would otherwise inherit.
452
+ * @param totalRamGib - total RAM in GiB; injectable for deterministic tests.
453
+ * @returns the overlay and plan; an empty overlay and `null` plan for a tool
454
+ * that is not memory-bound (`audit`, `security-scan`).
455
+ *
456
+ * @example
457
+ * ```ts
458
+ * // A shell profile exported an 8 GiB heap on a 64 GiB machine:
459
+ * const { overlay, resources } = planHeavyToolEnv(
460
+ * 'test', { NODE_OPTIONS: '--max-old-space-size=8192' }, 64);
461
+ * overlay.VITEST_MAX_WORKERS; // → '3' (3 × 8192 = the 24576 MiB budget)
462
+ * resources?.heapSource; // → 'inherited'
463
+ * ```
464
+ *
465
+ * @task T12096
466
+ * @task T13122
467
+ * @task T13123
468
+ */
469
+ export declare function planHeavyToolEnv(canonical: CanonicalTool, env?: NodeJS.ProcessEnv, totalRamGib?: number): HeavyToolSpawnPlan;
470
+ /**
471
+ * Build the environment overlay for a heavy or memory-bound tool spawn: the
472
+ * `overlay` of {@link planHeavyToolEnv}.
111
473
  *
112
- * Returns an empty object for non-heavy tools, so the caller can merge
113
- * unconditionally.
474
+ * Returns an empty object for a tool that is not memory-bound, so the caller
475
+ * can merge unconditionally.
114
476
  *
115
477
  * @param canonical - the canonical tool about to be spawned.
116
478
  * @param env - the environment the child would otherwise inherit.
117
479
  * @param totalRamGib - total RAM in GiB; injectable for deterministic tests.
118
- * @returns variables to overlay; existing deliberate values are preserved.
480
+ * @returns variables to overlay; inherited values within the plan are kept.
119
481
  *
120
482
  * @example
121
483
  * ```ts
122
- * const overlay = heavyToolEnv('test', process.env, 62);
484
+ * const overlay = heavyToolEnv('test', {}, 62);
123
485
  * // { NODE_OPTIONS: '--max-old-space-size=4096',
124
486
  * // VITEST_MAX_WORKERS: '6',
125
- * // npm_config_workspace_concurrency: '1' }
126
- * heavyToolEnv('lint', process.env, 62); // → {}
487
+ * // npm_config_workspace_concurrency: '1', … }
488
+ * heavyToolEnv('typecheck', {}, 62);
489
+ * // { NODE_OPTIONS: '--max-old-space-size=4096',
490
+ * // npm_config_workspace_concurrency: '1', pnpm_config_workspace_concurrency: '1' }
491
+ * heavyToolEnv('audit', process.env, 62); // → {}
127
492
  * ```
128
493
  *
129
494
  * @task T12096
495
+ * @task T13122
496
+ * @task T13123
130
497
  */
131
498
  export declare function heavyToolEnv(canonical: CanonicalTool, env?: NodeJS.ProcessEnv, totalRamGib?: number): HeavyToolEnv;
132
499
  //# sourceMappingURL=heavy-tool-env.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"heavy-tool-env.d.ts","sourceRoot":"","sources":["../../src/tasks/heavy-tool-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC,kFAAkF;AAClF,eAAO,MAAM,cAAc,IAAI,CAAC;AAEhC,0EAA0E;AAC1E,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAEnC,gFAAgF;AAChF,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAEnC;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC,kEAAkE;AAClE,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAc5D;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,aAAa,GAAG,OAAO,CAE7D;AA+BD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,GAAE,MAA+B,GAAG,MAAM,CAGrF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAKrF;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,aAAa,EACxB,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,WAAW,GAAE,MAA+B,GAC3C,YAAY,CAyBd"}
1
+ {"version":3,"file":"heavy-tool-env.d.ts","sourceRoot":"","sources":["../../src/tasks/heavy-tool-env.ts"],"names":[],"mappings":"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"}