@mjasnikovs/pi-task 0.38.29 → 0.38.31

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 (373) hide show
  1. package/dist/config/config.d.ts +70 -70
  2. package/dist/config/config.js +26 -35
  3. package/dist/config/extension-list.d.ts +6 -5
  4. package/dist/config/extension-list.js +3 -2
  5. package/dist/config/reasoning-args.d.ts +9 -7
  6. package/dist/config/reasoning-args.js +12 -10
  7. package/dist/config/reasoning.d.ts +44 -105
  8. package/dist/config/reasoning.js +27 -704
  9. package/dist/config/register.d.ts +34 -48
  10. package/dist/config/register.js +41 -51
  11. package/dist/config/tool-list.d.ts +16 -16
  12. package/dist/config/tool-list.js +1 -1
  13. package/dist/index.js +2 -0
  14. package/dist/remote/bridge.d.ts +19 -10
  15. package/dist/remote/bridge.js +3 -2
  16. package/dist/remote/broadcast.js +3 -1
  17. package/dist/remote/events.js +12 -11
  18. package/dist/remote/history.d.ts +1 -1
  19. package/dist/remote/protocol.d.ts +6 -3
  20. package/dist/remote/protocol.js +2 -1
  21. package/dist/remote/push.d.ts +16 -16
  22. package/dist/remote/push.js +27 -27
  23. package/dist/remote/register.d.ts +3 -3
  24. package/dist/remote/register.js +17 -19
  25. package/dist/remote/server.d.ts +9 -8
  26. package/dist/remote/server.js +15 -14
  27. package/dist/remote/session-state.d.ts +5 -4
  28. package/dist/remote/session-state.js +8 -5
  29. package/dist/remote/sw.d.ts +7 -6
  30. package/dist/remote/sw.js +7 -6
  31. package/dist/remote/tailscale.d.ts +4 -2
  32. package/dist/remote/tailscale.js +4 -2
  33. package/dist/remote/ui-highlight.js +6 -5
  34. package/dist/remote/ui-render.js +4 -4
  35. package/dist/remote/ui-script.js +24 -24
  36. package/dist/remote/ui-styles.d.ts +1 -1
  37. package/dist/remote/ui-styles.js +10 -13
  38. package/dist/remote/ui-tools.js +9 -6
  39. package/dist/shared/child-extensions.d.ts +29 -17
  40. package/dist/shared/child-extensions.js +29 -17
  41. package/dist/shared/child-output.d.ts +30 -24
  42. package/dist/shared/child-output.js +25 -17
  43. package/dist/shared/child-process.d.ts +47 -40
  44. package/dist/shared/child-process.js +50 -59
  45. package/dist/shared/command-watchdog.d.ts +85 -16
  46. package/dist/shared/command-watchdog.js +115 -21
  47. package/dist/shared/fs-text.d.ts +16 -10
  48. package/dist/shared/fs-text.js +16 -10
  49. package/dist/shared/git-runner.d.ts +25 -25
  50. package/dist/shared/git-runner.js +25 -25
  51. package/dist/shared/leaked-tool-call.d.ts +17 -11
  52. package/dist/shared/leaked-tool-call.js +23 -15
  53. package/dist/shared/model-endpoint.d.ts +29 -16
  54. package/dist/shared/model-endpoint.js +33 -21
  55. package/dist/shared/pi-invocation.d.ts +7 -4
  56. package/dist/shared/pi-invocation.js +12 -7
  57. package/dist/shared/pkg-version.d.ts +13 -5
  58. package/dist/shared/pkg-version.js +13 -5
  59. package/dist/shared/reasoning-capability.d.ts +35 -24
  60. package/dist/shared/reasoning-capability.js +35 -24
  61. package/dist/shared/stream-watchdog.d.ts +60 -44
  62. package/dist/shared/stream-watchdog.js +62 -45
  63. package/dist/task/accept-debt.d.ts +41 -43
  64. package/dist/task/accept-debt.js +73 -65
  65. package/dist/task/api-synthesis.d.ts +24 -21
  66. package/dist/task/api-synthesis.js +32 -26
  67. package/dist/task/apis-contract.d.ts +32 -64
  68. package/dist/task/apis-contract.js +32 -64
  69. package/dist/task/artifact-closure.d.ts +27 -13
  70. package/dist/task/artifact-closure.js +95 -67
  71. package/dist/task/auto-commit.d.ts +46 -35
  72. package/dist/task/auto-commit.js +51 -38
  73. package/dist/task/auto-io.d.ts +45 -25
  74. package/dist/task/auto-io.js +57 -29
  75. package/dist/task/auto-orchestrator.d.ts +26 -24
  76. package/dist/task/auto-orchestrator.js +192 -165
  77. package/dist/task/auto-prompts.d.ts +36 -24
  78. package/dist/task/auto-prompts.js +40 -26
  79. package/dist/task/autofix-ledger.d.ts +27 -25
  80. package/dist/task/autofix-ledger.js +29 -26
  81. package/dist/task/batch-test-task.d.ts +20 -12
  82. package/dist/task/batch-test-task.js +67 -60
  83. package/dist/task/boot-probe.d.ts +60 -44
  84. package/dist/task/boot-probe.js +91 -72
  85. package/dist/task/cancel-input.d.ts +30 -16
  86. package/dist/task/cancel-input.js +20 -11
  87. package/dist/task/cancel-points.d.ts +27 -20
  88. package/dist/task/cancel-points.js +30 -22
  89. package/dist/task/child-runner.d.ts +124 -55
  90. package/dist/task/child-runner.js +298 -90
  91. package/dist/task/child-status.d.ts +23 -16
  92. package/dist/task/child-status.js +23 -16
  93. package/dist/task/clamp-output.js +12 -5
  94. package/dist/task/command-run.d.ts +31 -28
  95. package/dist/task/command-run.js +44 -35
  96. package/dist/task/command-shrink.d.ts +25 -18
  97. package/dist/task/command-shrink.js +37 -31
  98. package/dist/task/command-watchdog.d.ts +9 -6
  99. package/dist/task/command-watchdog.js +21 -15
  100. package/dist/task/context-attribution.d.ts +34 -26
  101. package/dist/task/context-attribution.js +34 -26
  102. package/dist/task/context-silence.d.ts +39 -29
  103. package/dist/task/context-silence.js +35 -25
  104. package/dist/task/context-usage.d.ts +16 -9
  105. package/dist/task/context-usage.js +16 -9
  106. package/dist/task/contracts.d.ts +8 -4
  107. package/dist/task/contracts.js +25 -17
  108. package/dist/task/coverage-loop.d.ts +22 -18
  109. package/dist/task/coverage-loop.js +35 -30
  110. package/dist/task/critique-probes.d.ts +13 -14
  111. package/dist/task/critique-probes.js +50 -39
  112. package/dist/task/debug-log.d.ts +13 -5
  113. package/dist/task/debug-log.js +32 -20
  114. package/dist/task/decompose-fidelity.d.ts +11 -9
  115. package/dist/task/decompose-fidelity.js +38 -33
  116. package/dist/task/decompose-granularity.d.ts +41 -38
  117. package/dist/task/decompose-granularity.js +41 -38
  118. package/dist/task/deep-render-check.d.ts +22 -14
  119. package/dist/task/deep-render-check.js +40 -31
  120. package/dist/task/dropped-input.d.ts +12 -7
  121. package/dist/task/dropped-input.js +5 -2
  122. package/dist/task/enforce-attribution.d.ts +38 -47
  123. package/dist/task/enforce-attribution.js +46 -52
  124. package/dist/task/enforce-guidelines.d.ts +31 -20
  125. package/dist/task/enforce-guidelines.js +32 -21
  126. package/dist/task/enrichment.d.ts +7 -2
  127. package/dist/task/enrichment.js +26 -14
  128. package/dist/task/env-notes.d.ts +16 -7
  129. package/dist/task/env-notes.js +48 -31
  130. package/dist/task/env-template-closure.d.ts +4 -4
  131. package/dist/task/env-template-closure.js +42 -34
  132. package/dist/task/external-context.d.ts +28 -21
  133. package/dist/task/external-context.js +17 -12
  134. package/dist/task/failure-classifier.d.ts +4 -5
  135. package/dist/task/failure-classifier.js +30 -8
  136. package/dist/task/file-inventory.d.ts +15 -11
  137. package/dist/task/file-inventory.js +25 -22
  138. package/dist/task/final-gate-fix.d.ts +74 -86
  139. package/dist/task/final-gate-fix.js +97 -116
  140. package/dist/task/final-gate-progress.d.ts +29 -46
  141. package/dist/task/final-gate-progress.js +40 -51
  142. package/dist/task/final-gate.d.ts +64 -97
  143. package/dist/task/final-gate.js +192 -199
  144. package/dist/task/fix-child.d.ts +21 -27
  145. package/dist/task/fix-child.js +21 -27
  146. package/dist/task/foreign-path.d.ts +6 -5
  147. package/dist/task/foreign-path.js +0 -0
  148. package/dist/task/frozen-conflict.d.ts +9 -10
  149. package/dist/task/frozen-conflict.js +61 -64
  150. package/dist/task/frozen-path-guard.d.ts +35 -14
  151. package/dist/task/frozen-path-guard.js +56 -39
  152. package/dist/task/gate-child.d.ts +27 -28
  153. package/dist/task/gate-child.js +36 -35
  154. package/dist/task/gate-deps.d.ts +34 -27
  155. package/dist/task/gate-deps.js +169 -159
  156. package/dist/task/gate-tally.d.ts +77 -80
  157. package/dist/task/gate-tally.js +65 -68
  158. package/dist/task/git-state-guard.d.ts +15 -11
  159. package/dist/task/git-state-guard.js +76 -66
  160. package/dist/task/impl-widget.d.ts +25 -16
  161. package/dist/task/impl-widget.js +27 -17
  162. package/dist/task/implementation-guards.d.ts +26 -0
  163. package/dist/task/implementation-guards.js +177 -0
  164. package/dist/task/implementation-thinking.d.ts +33 -31
  165. package/dist/task/implementation-thinking.js +5 -6
  166. package/dist/task/implementation-turn.d.ts +39 -31
  167. package/dist/task/implementation-turn.js +41 -28
  168. package/dist/task/inline-markdown.d.ts +20 -7
  169. package/dist/task/inline-markdown.js +15 -6
  170. package/dist/task/launch-config-gap.js +25 -39
  171. package/dist/task/launch-contract.d.ts +18 -21
  172. package/dist/task/launch-contract.js +28 -30
  173. package/dist/task/launch-manifest.d.ts +6 -2
  174. package/dist/task/launch-manifest.js +35 -34
  175. package/dist/task/ledger.js +16 -14
  176. package/dist/task/lint-fix.d.ts +6 -8
  177. package/dist/task/lint-fix.js +67 -69
  178. package/dist/task/loop-detector.d.ts +27 -8
  179. package/dist/task/loop-detector.js +38 -14
  180. package/dist/task/mid-run-input.d.ts +17 -15
  181. package/dist/task/mid-run-input.js +17 -15
  182. package/dist/task/orchestrator.d.ts +24 -28
  183. package/dist/task/orchestrator.js +89 -66
  184. package/dist/task/orientation.d.ts +18 -23
  185. package/dist/task/orientation.js +24 -31
  186. package/dist/task/owned-freeze-conflict.d.ts +21 -20
  187. package/dist/task/owned-freeze-conflict.js +52 -85
  188. package/dist/task/owned-freeze-reassign.d.ts +40 -60
  189. package/dist/task/owned-freeze-reassign.js +41 -61
  190. package/dist/task/parsers.d.ts +4 -2
  191. package/dist/task/parsers.js +4 -4
  192. package/dist/task/phases.d.ts +41 -48
  193. package/dist/task/phases.js +196 -252
  194. package/dist/task/plan-io.d.ts +6 -7
  195. package/dist/task/plan-io.js +6 -7
  196. package/dist/task/plan-orchestrator.d.ts +10 -8
  197. package/dist/task/plan-orchestrator.js +14 -10
  198. package/dist/task/plan-prompts.d.ts +6 -5
  199. package/dist/task/plan-prompts.js +6 -5
  200. package/dist/task/plan-readonly.d.ts +4 -5
  201. package/dist/task/plan-readonly.js +4 -5
  202. package/dist/task/plan-rounds.d.ts +17 -29
  203. package/dist/task/plan-rounds.js +21 -34
  204. package/dist/task/plan-session.d.ts +58 -72
  205. package/dist/task/plan-session.js +61 -83
  206. package/dist/task/probe-gaming.d.ts +28 -27
  207. package/dist/task/probe-gaming.js +0 -0
  208. package/dist/task/prohibition-probe.d.ts +14 -16
  209. package/dist/task/prompts.d.ts +3 -4
  210. package/dist/task/prompts.js +17 -26
  211. package/dist/task/qa-transcript.d.ts +15 -22
  212. package/dist/task/qa-transcript.js +15 -21
  213. package/dist/task/question-box.d.ts +17 -13
  214. package/dist/task/question-box.js +19 -15
  215. package/dist/task/question-dedup.d.ts +6 -7
  216. package/dist/task/question-dedup.js +13 -14
  217. package/dist/task/question-dialog.d.ts +22 -32
  218. package/dist/task/question-dialog.js +22 -32
  219. package/dist/task/question-source.d.ts +18 -44
  220. package/dist/task/question-source.js +22 -51
  221. package/dist/task/refuted-constraint.d.ts +11 -31
  222. package/dist/task/refuted-constraint.js +27 -51
  223. package/dist/task/regenerable-artifacts.d.ts +12 -31
  224. package/dist/task/regenerable-artifacts.js +12 -31
  225. package/dist/task/render-check.d.ts +11 -22
  226. package/dist/task/render-check.js +33 -46
  227. package/dist/task/repo-health-check.d.ts +10 -14
  228. package/dist/task/repo-health-check.js +17 -23
  229. package/dist/task/requirements.d.ts +38 -71
  230. package/dist/task/requirements.js +78 -126
  231. package/dist/task/research-fanout-budget.d.ts +51 -88
  232. package/dist/task/research-fanout-budget.js +51 -88
  233. package/dist/task/research-worker.d.ts +29 -39
  234. package/dist/task/research-worker.js +37 -61
  235. package/dist/task/resume-gap.d.ts +14 -15
  236. package/dist/task/root-cause-repair.d.ts +9 -9
  237. package/dist/task/root-cause-repair.js +28 -40
  238. package/dist/task/run-bracket.d.ts +10 -13
  239. package/dist/task/run-end.d.ts +12 -22
  240. package/dist/task/run-end.js +8 -16
  241. package/dist/task/run-final-gate.d.ts +19 -21
  242. package/dist/task/run-final-gate.js +62 -80
  243. package/dist/task/runner-globs.d.ts +12 -13
  244. package/dist/task/runner-globs.js +12 -13
  245. package/dist/task/runner-resolve.d.ts +9 -9
  246. package/dist/task/runner-resolve.js +22 -23
  247. package/dist/task/script-escape.d.ts +10 -12
  248. package/dist/task/script-escape.js +13 -14
  249. package/dist/task/serve-entry.d.ts +1 -1
  250. package/dist/task/serve-entry.js +22 -25
  251. package/dist/task/service-blocks.js +4 -2
  252. package/dist/task/shipped-source.d.ts +11 -29
  253. package/dist/task/shipped-source.js +11 -29
  254. package/dist/task/skip-escape.js +10 -14
  255. package/dist/task/spec-urls.d.ts +26 -65
  256. package/dist/task/spec-urls.js +26 -65
  257. package/dist/task/spec-validation.d.ts +17 -20
  258. package/dist/task/spec-validation.js +17 -20
  259. package/dist/task/stall-detector.d.ts +23 -30
  260. package/dist/task/stall-detector.js +23 -30
  261. package/dist/task/stream-watchdog.d.ts +14 -12
  262. package/dist/task/stream-watchdog.js +14 -12
  263. package/dist/task/substitution-probe.d.ts +17 -20
  264. package/dist/task/substitution-probe.js +17 -20
  265. package/dist/task/task-gates.d.ts +36 -41
  266. package/dist/task/task-gates.js +95 -106
  267. package/dist/task/task-io.d.ts +4 -4
  268. package/dist/task/task-io.js +4 -4
  269. package/dist/task/task-parsers.js +4 -3
  270. package/dist/task/task-provenance.d.ts +2 -2
  271. package/dist/task/task-provenance.js +11 -13
  272. package/dist/task/task-types.d.ts +4 -3
  273. package/dist/task/terminal-outcome.d.ts +14 -16
  274. package/dist/task/terminal-outcome.js +12 -14
  275. package/dist/task/test-assembly.d.ts +13 -20
  276. package/dist/task/test-assembly.js +13 -20
  277. package/dist/task/timings.d.ts +5 -3
  278. package/dist/task/timings.js +5 -3
  279. package/dist/task/title-label.d.ts +9 -4
  280. package/dist/task/title-label.js +9 -4
  281. package/dist/task/type-only-answer.d.ts +44 -52
  282. package/dist/task/type-only-answer.js +44 -52
  283. package/dist/task/unfailable-command.d.ts +18 -24
  284. package/dist/task/unfailable-command.js +21 -27
  285. package/dist/task/unknown-routing.d.ts +10 -4
  286. package/dist/task/unknown-routing.js +10 -4
  287. package/dist/task/user-directives.d.ts +5 -8
  288. package/dist/task/user-directives.js +5 -8
  289. package/dist/task/verify-quality.d.ts +18 -22
  290. package/dist/task/verify-quality.js +45 -46
  291. package/dist/task/verify-reconcile.d.ts +15 -10
  292. package/dist/task/verify-reconcile.js +45 -43
  293. package/dist/task/verify-resolution.d.ts +24 -20
  294. package/dist/task/verify-resolution.js +51 -50
  295. package/dist/task/verify-work.d.ts +59 -66
  296. package/dist/task/verify-work.js +101 -138
  297. package/dist/task/widget.d.ts +15 -14
  298. package/dist/task/widget.js +22 -17
  299. package/dist/task/wiring-claims.d.ts +25 -32
  300. package/dist/task/wiring-claims.js +30 -35
  301. package/dist/task/write-guard.d.ts +39 -39
  302. package/dist/task/write-guard.js +48 -51
  303. package/dist/task/yolo.d.ts +34 -30
  304. package/dist/task/yolo.js +42 -37
  305. package/dist/workers/abstention.d.ts +21 -41
  306. package/dist/workers/abstention.js +27 -48
  307. package/dist/workers/brave-search.d.ts +4 -3
  308. package/dist/workers/brave-search.js +5 -2
  309. package/dist/workers/brave-warning.d.ts +7 -4
  310. package/dist/workers/brave-warning.js +19 -7
  311. package/dist/workers/ddg-search.d.ts +6 -6
  312. package/dist/workers/ddg-search.js +18 -12
  313. package/dist/workers/docs-cache.js +5 -2
  314. package/dist/workers/docs-chunk.d.ts +30 -37
  315. package/dist/workers/docs-chunk.js +37 -41
  316. package/dist/workers/docs-core.d.ts +28 -44
  317. package/dist/workers/docs-core.js +25 -44
  318. package/dist/workers/docs-index.js +4 -3
  319. package/dist/workers/docs-lookup.d.ts +15 -22
  320. package/dist/workers/docs-lookup.js +12 -21
  321. package/dist/workers/docs-project.d.ts +15 -9
  322. package/dist/workers/docs-project.js +17 -10
  323. package/dist/workers/docs-resolve.d.ts +19 -20
  324. package/dist/workers/docs-resolve.js +35 -32
  325. package/dist/workers/docs-retrieve.d.ts +5 -6
  326. package/dist/workers/docs-retrieve.js +18 -15
  327. package/dist/workers/exa-search.d.ts +9 -6
  328. package/dist/workers/exa-search.js +23 -12
  329. package/dist/workers/fetch-core.d.ts +13 -16
  330. package/dist/workers/fetch-core.js +23 -23
  331. package/dist/workers/focused-extractor.d.ts +13 -12
  332. package/dist/workers/focused-extractor.js +27 -19
  333. package/dist/workers/html-clean.js +24 -14
  334. package/dist/workers/http-request.d.ts +28 -20
  335. package/dist/workers/http-request.js +22 -17
  336. package/dist/workers/npm-version.d.ts +28 -11
  337. package/dist/workers/npm-version.js +24 -15
  338. package/dist/workers/phantom-imports.d.ts +15 -12
  339. package/dist/workers/phantom-imports.js +30 -24
  340. package/dist/workers/pi-worker-core.d.ts +65 -96
  341. package/dist/workers/pi-worker-core.js +93 -181
  342. package/dist/workers/pi-worker-docs.d.ts +24 -19
  343. package/dist/workers/pi-worker-docs.js +67 -76
  344. package/dist/workers/pi-worker-fetch.d.ts +7 -3
  345. package/dist/workers/pi-worker-fetch.js +27 -19
  346. package/dist/workers/pi-worker-search.js +12 -8
  347. package/dist/workers/pi-worker.d.ts +9 -4
  348. package/dist/workers/pi-worker.js +21 -14
  349. package/dist/workers/reasoning-warning.d.ts +18 -17
  350. package/dist/workers/reasoning-warning.js +22 -20
  351. package/dist/workers/research-cache.js +50 -78
  352. package/dist/workers/search-core.js +7 -5
  353. package/dist/workers/search-types.d.ts +10 -9
  354. package/dist/workers/search-types.js +9 -8
  355. package/dist/workers/session-hint.d.ts +13 -14
  356. package/dist/workers/session-hint.js +8 -9
  357. package/dist/workers/shared.d.ts +21 -25
  358. package/dist/workers/shared.js +0 -0
  359. package/dist/workers/single-read-extension.d.ts +14 -7
  360. package/dist/workers/single-read-extension.js +14 -7
  361. package/dist/workers/single-read-guard.d.ts +27 -30
  362. package/dist/workers/single-read-guard.js +36 -36
  363. package/dist/workers/typeonly-log.d.ts +12 -9
  364. package/dist/workers/typeonly-log.js +29 -33
  365. package/dist/workers/worker-channels.d.ts +15 -23
  366. package/dist/workers/worker-channels.js +15 -23
  367. package/dist/workers/worker-failure.d.ts +38 -46
  368. package/dist/workers/worker-failure.js +31 -39
  369. package/dist/workers/worker-kill.d.ts +25 -26
  370. package/dist/workers/worker-kill.js +16 -19
  371. package/dist/workers/worker-profiles.d.ts +54 -56
  372. package/dist/workers/worker-profiles.js +63 -39
  373. package/package.json +10 -8
@@ -7,26 +7,28 @@ export interface PiTaskConfig {
7
7
  enforceGuidelines: boolean;
8
8
  verifyWork: boolean;
9
9
  /**
10
- * Run the four research workers concurrently instead of one at a time.
11
- * DEFAULT OFF: serial was A/B-proven faster on a single-GPU local backend
12
- * (concurrent streams split the GPU and slow each other ~4×, see
13
- * phases.ts). Turn on only for a parallel-capable backend.
10
+ * Run the four research workers concurrently instead of one at a time
11
+ * (task/phases.ts). DEFAULT OFF. Serial is also what lets a worker read the
12
+ * sections finished before it APIS builds on the FILES map, and gets
13
+ * nothing under the parallel branch. Measure your own backend before
14
+ * turning this on.
14
15
  */
15
16
  parallelResearchWorkers: boolean;
16
17
  /**
17
- * Cache docs/search/fetch worker RESULTS for the duration of one /task-auto run
18
- * so sibling tasks re-asking the same (package/url, query) reuse the first
19
- * pipeline's digest instead of re-fetching (mx5 run-8 F10: the research phase
20
- * burned 75 of 363 min largely re-fetching the same external docs across ~20
21
- * siblings). Per-run isolated, external-only (project-source `.` lookups excluded),
22
- * success-only. DEFAULT ON the F10 live A/B showed no answer-quality regression
23
- * (a cache hit serves byte-identical text to the first fetch; distinct queries never
24
- * collide).
18
+ * Cache docs/search/fetch worker RESULTS for the duration of one /task-auto
19
+ * run, so sibling tasks re-asking the same (package/url, query) reuse the
20
+ * first pipeline's digest instead of re-fetching it. Per-run isolated,
21
+ * external-only (project-source `.` lookups are excluded), success-only.
22
+ *
23
+ * DEFAULT ON. A hit replays the stored text byte for byte. The key is the
24
+ * tool name plus the whole query normalised for case and whitespace, so
25
+ * two spellings of one question share a digest, and nothing else does.
25
26
  */
26
27
  researchCache: boolean;
27
28
  /**
28
29
  * Which engine backs web search (pi-worker-search + freshness/enrichment).
29
- * `exa` and `ddg` need no API key; `brave` needs BRAVE_SEARCH_API_KEY.
30
+ * `exa` and `ddg` need no API key; `brave` needs one (see
31
+ * SEARCH_PROVIDER_KEY_ENV in workers/search-types.ts).
30
32
  * DEFAULT `exa` so search works out of the box with zero configuration.
31
33
  */
32
34
  searchProvider: SearchProvider;
@@ -44,21 +46,21 @@ export interface PiTaskConfig {
44
46
  extensionWhitelist: string[];
45
47
  /**
46
48
  * Wall-clock ceiling (ms) on a SINGLE tool execution before the command
47
- * watchdog steps in. Local models routinely run a command that never returns
48
- * (e.g. `godot --headless` with no timeout, a dev server, a hung test) and
49
- * the run wedges until the user manually aborts. pi's bash tool has an
50
- * OPTIONAL timeout with NO default (bash.js), so a command the model didn't
51
- * bound runs forever; this is the missing default.
49
+ * watchdog steps in. pi's bash tool declares its `timeout` parameter as
50
+ * "Timeout in seconds (optional, no default timeout)" and returns undefined
51
+ * when it is absent, so a command the model didn't bound runs forever. This
52
+ * is the missing default.
52
53
  *
53
54
  * ONE knob, TWO surfaces (shared/command-watchdog.ts): in the MAIN session
54
- * the overrun call is cancelled via ctx.abort() (kills the tool's whole
55
- * process tree) plus an auto-reminder turn; in the verify/fix GATE children
55
+ * the overrun fires ctx.abort(), which ends the whole agent operation — pi's
56
+ * bash tool answers that signal by killing the command's entire process
57
+ * tree — followed by an auto-reminder turn; in the verify/fix GATE children
56
58
  * (gate-deps.ts) the child is killed and re-spawned with a hint, the ceiling
57
- * halving on repeat hangs. 0 = off — which unguards BOTH surfaces, gates
58
- * included. Tool-agnostic: it arms on any tool execution, though in practice
59
- * only bash runs long enough to trip it.
60
- * DEFAULT 15 min: long enough for a real build/test suite, short enough that
61
- * a true hang doesn't cost half an hour of dead time.
59
+ * halving per prior hang. 0 = off — which unguards BOTH surfaces, gates
60
+ * included. Tool-agnostic: it arms on any tool execution.
61
+ *
62
+ * The default is a compromise: it has to outlast a real build or test suite
63
+ * on the slowest machine you run this on, and still end a true hang.
62
64
  */
63
65
  requestTimeoutMs: number;
64
66
  /**
@@ -82,19 +84,21 @@ export interface PiTaskConfig {
82
84
  * aborts the request (shared/stream-watchdog.ts). A hung or silently-dropped
83
85
  * stream throws nothing, so neither the connection-error retry (needs a
84
86
  * reported error) nor the command watchdog (covers tool calls only) nor the
85
- * child stall guard (a reachable endpoint is proof of life) can see it — mx5
86
- * run 14 lost ~2.9h to three such hangs while the model server stayed healthy.
87
+ * child stall guard (a reachable endpoint is proof of life) can see it. The
88
+ * server stays healthy the whole time; only the stream is gone.
87
89
  *
88
- * Measured as time since the LAST stream event of any kind, so a slow model
89
- * emitting one token every 30s is never touched; only total silence counts.
90
- * Suspended while a tool executes — that window is the command watchdog's.
90
+ * Measured as time since the LAST stream event of any kind, so a model that
91
+ * is merely slow is never touched however slow it is; only total silence
92
+ * counts. Suspended between `tool_execution_start` and the last call
93
+ * settling — that window belongs to the command watchdog.
91
94
  *
92
95
  * ONE knob, TWO surfaces: the MAIN session aborts the turn through the same
93
96
  * plumbing the command watchdog uses and posts a resume reminder; a CHILD is
94
97
  * killed and its result routed into the EXISTING connection-error retry.
95
98
  * 0 = off, on both surfaces.
96
- * DEFAULT 10 min: local prompt processing on a 32k context legitimately emits
97
- * nothing for minutes, so a 60-120s ceiling would kill healthy long prompts.
99
+ *
100
+ * The default is generous on purpose: a local backend can sit in prompt
101
+ * processing emitting nothing at all, and that silence is healthy.
98
102
  */
99
103
  streamInactivityMs: number;
100
104
  /**
@@ -114,33 +118,32 @@ export interface PiTaskConfig {
114
118
  yoloMode: boolean;
115
119
  /**
116
120
  * How much the run writes to its `.pi-tasks/*-debug.log` forensic trail
117
- * (task/debug-log.ts). NOTHING in pi-task ever reads these files back —
118
- * `task-io.ts` only globs `TASK_NNNN.md`, and auto-commit's trail snapshot
119
- * copies bytes without parsing them so this knob is behaviour-neutral by
120
- * construction. It trades disk and repo noise against the ability to explain
121
- * a run after it has finished.
121
+ * (task/debug-log.ts). Nothing in `src/` reads these files back —
122
+ * `task-io.ts` only matches `TASK_NNNN.md`, and auto-commit's trail snapshot
123
+ * reads every `.pi-tasks/` file as bytes and writes them back unparsed — so
124
+ * this knob is behaviour-neutral by construction. It trades disk and repo
125
+ * noise against the ability to explain a run after it has finished. The
126
+ * TESTS do read the trail back, which is why the test preload pins the
127
+ * config path away from the developer's own file.
122
128
  *
123
129
  * `full` is every line the child model emitted plus every tool result;
124
130
  * `events` keeps only decisions and guard actions; `off` writes nothing.
125
131
  *
126
132
  * DEFAULT `events`, not `off`, because the two levels are not the same kind
127
- * of record. Measured on a real 247 KB `verify-debug.log` (IAR1, 1315 lines):
128
- * the child's own output and the `↳` tool dumps are 85% of the bytes, while
129
- * the `=== ===` markers are 15% and that 15% is the ONLY record of what
130
- * the guards did (`GIT-STATE GUARD child mutated graded state`, the
131
- * write-capable child's `tree changes`, the FAIL reason). mx5 run 11's
132
- * final-fix child deleted a source file; the tree-changes line is why that
133
- * was findable at all. Silencing the chatter costs nothing; silencing the
134
- * guard record makes the next incident unreconstructible, and a debug log
135
- * cannot be recovered after the fact.
133
+ * of record. The child's own output and the `↳` tool dumps are bulk. The
134
+ * `=== ===` markers are the only record of what the guards did the
135
+ * git-state guard firing, a write-capable child's tree changes, a FAIL
136
+ * reason. Silencing the chatter costs nothing. Silencing the guard record
137
+ * makes the next incident unreconstructible, and a debug log cannot be
138
+ * recovered after the fact.
136
139
  */
137
140
  debugLogs: DebugLogLevel;
138
141
  /**
139
142
  * Which reasoning profile is in force. See config/reasoning.ts for the four
140
143
  * modes and the group vocabulary.
141
144
  *
142
- * DEFAULT `default`, whose table ships all-`inherit` so installing this
143
- * version changes no child's argv until the user opts in.
145
+ * DEFAULT `default`, which uses the shipped per-group table. `off` and `on`
146
+ * override every group at once; `custom` reads the user's own table.
144
147
  */
145
148
  reasoningMode: ReasoningMode;
146
149
  /**
@@ -169,9 +172,10 @@ export declare const DEBUG_LOG_OPTIONS: readonly DebugLogLevel[];
169
172
  */
170
173
  export declare function sanitizeDebugLogs(value: unknown): DebugLogLevel;
171
174
  /**
172
- * The command-watchdog timeout choices offered by /task-config, newest-first in
173
- * the cycle order the picker shows. The stored config value is the ms number;
174
- * the label is display-only (mirrors the searchProvider label/value split).
175
+ * The command-watchdog timeout choices offered by /task-config, in the cycle
176
+ * order the picker shows: ascending, with `off` last. The stored config value is
177
+ * the ms number; the label is display-only (mirrors the searchProvider
178
+ * label/value split).
175
179
  */
176
180
  export declare const COMMAND_TIMEOUT_OPTIONS: ReadonlyArray<{
177
181
  label: string;
@@ -186,8 +190,8 @@ export declare function sanitizeRequestTimeoutMs(value: unknown): number;
186
190
  export declare function sanitizeCommandTimeoutExemptTools(value: unknown): string[];
187
191
  /**
188
192
  * The stream-watchdog choices offered by /task-config, in cycle order. Every
189
- * option is minutes, not seconds: the failure this guards costs hours, and the
190
- * legitimate silence it must tolerate (local prompt processing) is minutes.
193
+ * option is minutes, not seconds: the silence this must tolerate a local
194
+ * backend in prompt processing is itself measured in minutes.
191
195
  */
192
196
  export declare const STREAM_INACTIVITY_OPTIONS: ReadonlyArray<{
193
197
  label: string;
@@ -212,35 +216,31 @@ export declare function sanitizeExtensionWhitelist(value: unknown): string[];
212
216
  * How each setting's STORED value becomes a safe in-memory value — one loader per
213
217
  * key, keyed on the config's own type.
214
218
  *
215
- * `ConfigItem` (config/register.ts) already absorbed three of the four edits its
216
- * own header names: *"Adding one enum setting meant four coordinated edits (row,
217
- * format arm, parse arm, sanitizer) and NONE of them failed to compile if you
218
- * forgot it."* The sanitizer was the fourth, and it stayed behind in this file as
219
- * a hand-ordered statement ladder covering 7 of 14 keys. This is the mapped type
220
- * that closes it: a new field on `PiTaskConfig` is a compile error until it
221
- * declares how a hostile value becomes a safe one.
219
+ * The mapped type is the point: a new field on `PiTaskConfig` is a compile error
220
+ * until it declares how a hostile value becomes a safe one. Adding a field and
221
+ * nothing else fails tsc twice once on DEFAULT_CONFIG, once here.
222
222
  */
223
223
  export declare const CONFIG_LOADERS: {
224
224
  [K in keyof PiTaskConfig]: (raw: unknown) => PiTaskConfig[K];
225
225
  };
226
226
  /**
227
- * Turn parsed config JSON into a `PiTaskConfig`. Pure this is the seam the load
228
- * block used to have none of, so every hostile-value case was reachable only
229
- * through `getConfig()`, which reads the developer's own machine.
227
+ * Turn parsed config JSON into a `PiTaskConfig`. Pure, so every hostile-value
228
+ * case is reachable from a test without going through `getConfig()`, which reads
229
+ * whatever this machine has on disk.
230
230
  *
231
- * A non-object `raw` yields the defaults. That is not merely defensive: the old
232
- * block spread `parsed` directly, and `{...DEFAULT_CONFIG, ...'ab'}` produces
233
- * numeric index keys. Keys absent from the table are dropped rather than carried
234
- * into the config object.
231
+ * A non-object `raw` yields the defaults. Spreading a string instead would
232
+ * produce numeric index keys: `{...DEFAULT_CONFIG, ...'ab'}` gains `0` and `1`.
233
+ * Keys absent from the sanitizer table are dropped rather than carried into the
234
+ * config object.
235
235
  */
236
236
  export declare function loadConfig(raw: unknown): PiTaskConfig;
237
237
  /**
238
238
  * Where the saved config lives. `PI_TASK_CONFIG_PATH` overrides it.
239
239
  *
240
240
  * The override exists because this module loads the real file at import time,
241
- * which made every test that reads a config value depend on the developer's own
242
- * `~/.config/pi-task/config.json` — a machine-local `"debugLogs": "off"` failed
243
- * 12 tests here while CI (no config file at all) stayed green. The test preload
241
+ * which makes every test that reads a config value depend on the developer's own
242
+ * `~/.config/pi-task/config.json` — a machine-local `"debugLogs": "off"` is
243
+ * enough to fail the tests that read `plan-debug.log` back. The test preload
244
244
  * points this at a path under the tmp dir that never exists, so tests always see
245
245
  * DEFAULT_CONFIG. Read once at module eval: the preload runs before any import.
246
246
  */
@@ -23,9 +23,10 @@ export function sanitizeDebugLogs(value) {
23
23
  : DEFAULT_DEBUG_LOGS;
24
24
  }
25
25
  /**
26
- * The command-watchdog timeout choices offered by /task-config, newest-first in
27
- * the cycle order the picker shows. The stored config value is the ms number;
28
- * the label is display-only (mirrors the searchProvider label/value split).
26
+ * The command-watchdog timeout choices offered by /task-config, in the cycle
27
+ * order the picker shows: ascending, with `off` last. The stored config value is
28
+ * the ms number; the label is display-only (mirrors the searchProvider
29
+ * label/value split).
29
30
  */
30
31
  export const COMMAND_TIMEOUT_OPTIONS = [
31
32
  { label: '5 min', ms: 5 * 60_000 },
@@ -63,8 +64,8 @@ export function sanitizeCommandTimeoutExemptTools(value) {
63
64
  }
64
65
  /**
65
66
  * The stream-watchdog choices offered by /task-config, in cycle order. Every
66
- * option is minutes, not seconds: the failure this guards costs hours, and the
67
- * legitimate silence it must tolerate (local prompt processing) is minutes.
67
+ * option is minutes, not seconds: the silence this must tolerate a local
68
+ * backend in prompt processing is itself measured in minutes.
68
69
  */
69
70
  export const STREAM_INACTIVITY_OPTIONS = [
70
71
  { label: '5 min', ms: 5 * 60_000 },
@@ -93,8 +94,6 @@ export const DEFAULT_CONFIG = {
93
94
  enforceGuidelines: true,
94
95
  verifyWork: true,
95
96
  parallelResearchWorkers: false,
96
- // ON: the F10 live A/B showed no answer-quality regression (fidelity 3/3, quality
97
- // 3/3, 0 collisions; ~14.5s of repeated docs lookups collapse to 0ms on a hit).
98
97
  researchCache: true,
99
98
  searchProvider: 'exa',
100
99
  extensionWhitelist: [],
@@ -103,12 +102,11 @@ export const DEFAULT_CONFIG = {
103
102
  streamInactivityMs: DEFAULT_STREAM_INACTIVITY_MS,
104
103
  // OFF: auto-answering is for unattended throwaway runs only.
105
104
  yoloMode: false,
106
- // EVENTS: the model chatter is 85% of the bytes and nobody reads it; the
107
- // guard/verdict markers are the 15% that explains a failed run.
105
+ // EVENTS: the model chatter is bulk nobody reads; the guard and verdict
106
+ // markers are what explains a failed run.
108
107
  debugLogs: DEFAULT_DEBUG_LOGS,
109
- // DEFAULT: the measured per-group table, which currently holds `inherit` in
110
- // every cell. Every child's argv is byte-identical to the version before
111
- // reasoning profiles existed until a cell is filled in by an A/B.
108
+ // DEFAULT: the shipped per-group table. A cell left at `inherit` emits no
109
+ // --thinking flag, so that child keeps the host's own level.
112
110
  reasoningMode: 'default',
113
111
  reasoningLevels: { ...DEFAULT_REASONING_TABLE }
114
112
  };
@@ -123,12 +121,9 @@ export function sanitizeExtensionWhitelist(value) {
123
121
  }
124
122
  /**
125
123
  * A boolean setting's loader. Only a REAL boolean counts; anything else falls
126
- * back to the shipped default.
127
- *
128
- * This is `yoloMode`'s guard, generalised. Its comment — *"a hand-edited
129
- * `"yoloMode": "false"` is a truthy string"* — was true verbatim of the other
130
- * seven booleans, none of which had it, so a stale `"verifyWork": "off"` reached
131
- * `getConfig().verifyWork` as truthy and a `"autoCommit": 0` reached it as falsy.
124
+ * back to the shipped default — a hand-edited `"verifyWork": "off"` is a truthy
125
+ * string and a `"autoCommit": 0` is a falsy number, and neither may decide a
126
+ * setting.
132
127
  */
133
128
  function asBoolean(key) {
134
129
  return raw => (typeof raw === 'boolean' ? raw : DEFAULT_CONFIG[key]);
@@ -137,13 +132,9 @@ function asBoolean(key) {
137
132
  * How each setting's STORED value becomes a safe in-memory value — one loader per
138
133
  * key, keyed on the config's own type.
139
134
  *
140
- * `ConfigItem` (config/register.ts) already absorbed three of the four edits its
141
- * own header names: *"Adding one enum setting meant four coordinated edits (row,
142
- * format arm, parse arm, sanitizer) and NONE of them failed to compile if you
143
- * forgot it."* The sanitizer was the fourth, and it stayed behind in this file as
144
- * a hand-ordered statement ladder covering 7 of 14 keys. This is the mapped type
145
- * that closes it: a new field on `PiTaskConfig` is a compile error until it
146
- * declares how a hostile value becomes a safe one.
135
+ * The mapped type is the point: a new field on `PiTaskConfig` is a compile error
136
+ * until it declares how a hostile value becomes a safe one. Adding a field and
137
+ * nothing else fails tsc twice once on DEFAULT_CONFIG, once here.
147
138
  */
148
139
  export const CONFIG_LOADERS = {
149
140
  remote: asBoolean('remote'),
@@ -166,14 +157,14 @@ export const CONFIG_LOADERS = {
166
157
  reasoningLevels: sanitizeReasoningLevels
167
158
  };
168
159
  /**
169
- * Turn parsed config JSON into a `PiTaskConfig`. Pure this is the seam the load
170
- * block used to have none of, so every hostile-value case was reachable only
171
- * through `getConfig()`, which reads the developer's own machine.
160
+ * Turn parsed config JSON into a `PiTaskConfig`. Pure, so every hostile-value
161
+ * case is reachable from a test without going through `getConfig()`, which reads
162
+ * whatever this machine has on disk.
172
163
  *
173
- * A non-object `raw` yields the defaults. That is not merely defensive: the old
174
- * block spread `parsed` directly, and `{...DEFAULT_CONFIG, ...'ab'}` produces
175
- * numeric index keys. Keys absent from the table are dropped rather than carried
176
- * into the config object.
164
+ * A non-object `raw` yields the defaults. Spreading a string instead would
165
+ * produce numeric index keys: `{...DEFAULT_CONFIG, ...'ab'}` gains `0` and `1`.
166
+ * Keys absent from the sanitizer table are dropped rather than carried into the
167
+ * config object.
177
168
  */
178
169
  export function loadConfig(raw) {
179
170
  if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {
@@ -194,9 +185,9 @@ export function loadConfig(raw) {
194
185
  * Where the saved config lives. `PI_TASK_CONFIG_PATH` overrides it.
195
186
  *
196
187
  * The override exists because this module loads the real file at import time,
197
- * which made every test that reads a config value depend on the developer's own
198
- * `~/.config/pi-task/config.json` — a machine-local `"debugLogs": "off"` failed
199
- * 12 tests here while CI (no config file at all) stayed green. The test preload
188
+ * which makes every test that reads a config value depend on the developer's own
189
+ * `~/.config/pi-task/config.json` — a machine-local `"debugLogs": "off"` is
190
+ * enough to fail the tests that read `plan-debug.log` back. The test preload
200
191
  * points this at a path under the tmp dir that never exists, so tests always see
201
192
  * DEFAULT_CONFIG. Read once at module eval: the preload runs before any import.
202
193
  */
@@ -1,10 +1,11 @@
1
1
  /**
2
2
  * Enumerates the host's installed pi extensions for the /task-config whitelist
3
- * (GitHub issue #4) using pi's OWN resolver the same DefaultPackageManager
4
- * the host runtime discovers extensions with so the menu always mirrors what
5
- * `pi list`/discovery would load: install a package and it appears, uninstall
6
- * it and it vanishes (a stale whitelist entry is then skipped at spawn time by
7
- * extensionArgs' existence filter, never fatal).
3
+ * (GitHub issue #4) using pi's OWN resolver: the call below is the same
4
+ * `new DefaultPackageManager(...)` plus `resolve(() => "skip")` that pi's own
5
+ * startup makes (cli/startup-ui.js). So the menu shows what the host would
6
+ * load install a package and it appears, uninstall it and it vanishes (a
7
+ * stale whitelist entry is then skipped at spawn time by extensionArgs'
8
+ * existence filter, never fatal).
8
9
  */
9
10
  export interface InstalledExtension {
10
11
  /** Absolute entry-point path — the whitelist identity AND the `-e` value. */
@@ -44,8 +44,9 @@ export async function listInstalledExtensions(opts) {
44
44
  const selfRoot = opts.selfRoot ?? selfPackageRoot();
45
45
  const settingsManager = SettingsManager.create(opts.cwd, agentDir);
46
46
  const pm = new DefaultPackageManager({ cwd: opts.cwd, agentDir, settingsManager });
47
- // "skip": a package in settings whose install dir is missing must not
48
- // trigger an interactive install prompt from inside a config menu.
47
+ // "skip": a package in settings whose install dir is missing is passed over.
48
+ // Without this callback pi installs it instead, which a config menu must
49
+ // never do on the user's behalf.
49
50
  const resolved = await pm.resolve(() => Promise.resolve('skip'));
50
51
  const out = [];
51
52
  for (const r of resolved.extensions) {
@@ -1,12 +1,13 @@
1
1
  /**
2
2
  * The live-config bridge for reasoning profiles: group in, argv fragment out.
3
3
  *
4
- * Separate from reasoning.ts because that module must stay import-free see its
5
- * header. This file is the one hop that reads `getConfig()`, so it imports both
6
- * and neither imports it back: a tree, not a cycle.
4
+ * Separate from reasoning.ts because that module must take no import with a
5
+ * runtime side effect see its header. The `getConfig()` read lives here
6
+ * instead: this file imports both, and nothing in config/ imports it back, so
7
+ * the graph stays a tree.
7
8
  *
8
9
  * Read PER CALL, never cached at module scope, so a /task-config change lands on
9
- * the next child without a restart the same contract childBaseArgs states.
10
+ * the next child without a restart. Same contract `childBaseArgs` keeps.
10
11
  */
11
12
  import { type PiTaskConfig } from './config.js';
12
13
  import { type ReasoningGroup } from './reasoning.js';
@@ -14,8 +15,9 @@ import { type ReasoningGroup } from './reasoning.js';
14
15
  * The `['--thinking', level]` fragment for a group, or `[]` when the group is
15
16
  * `inherit` and the child should keep falling back to settings.json.
16
17
  *
17
- * This is the ONLY function the argv builders call. They never read config
18
- * themselves an argv builder that resolves its own policy is one that cannot
19
- * be told to do something else, which is how childBaseArgs became universal.
18
+ * Every argv builder calls this rather than reading config itself. The two
19
+ * callers that skip it are not argv builders: the host-session turn
20
+ * (implementation-thinking.ts) and the settings UI (register.ts) both need the
21
+ * level itself, not a flag, so they call `resolveReasoning` directly.
20
22
  */
21
23
  export declare function groupThinkingArgs(group: ReasoningGroup, cfg?: PiTaskConfig): string[];
@@ -1,12 +1,13 @@
1
1
  /**
2
2
  * The live-config bridge for reasoning profiles: group in, argv fragment out.
3
3
  *
4
- * Separate from reasoning.ts because that module must stay import-free see its
5
- * header. This file is the one hop that reads `getConfig()`, so it imports both
6
- * and neither imports it back: a tree, not a cycle.
4
+ * Separate from reasoning.ts because that module must take no import with a
5
+ * runtime side effect see its header. The `getConfig()` read lives here
6
+ * instead: this file imports both, and nothing in config/ imports it back, so
7
+ * the graph stays a tree.
7
8
  *
8
9
  * Read PER CALL, never cached at module scope, so a /task-config change lands on
9
- * the next child without a restart the same contract childBaseArgs states.
10
+ * the next child without a restart. Same contract `childBaseArgs` keeps.
10
11
  */
11
12
  import { getConfig } from './config.js';
12
13
  import { resolveReasoning, thinkingArgs } from './reasoning.js';
@@ -14,13 +15,14 @@ import { resolveReasoning, thinkingArgs } from './reasoning.js';
14
15
  * The `['--thinking', level]` fragment for a group, or `[]` when the group is
15
16
  * `inherit` and the child should keep falling back to settings.json.
16
17
  *
17
- * This is the ONLY function the argv builders call. They never read config
18
- * themselves an argv builder that resolves its own policy is one that cannot
19
- * be told to do something else, which is how childBaseArgs became universal.
18
+ * Every argv builder calls this rather than reading config itself. The two
19
+ * callers that skip it are not argv builders: the host-session turn
20
+ * (implementation-thinking.ts) and the settings UI (register.ts) both need the
21
+ * level itself, not a flag, so they call `resolveReasoning` directly.
20
22
  */
21
23
  export function groupThinkingArgs(group, cfg) {
22
- // The default is EVALUATED HERE, per call, which is the contract this module
23
- // exists to keep. Hoisting the read to module scope would leave every test
24
- // green, so the parameter is what makes the contract assertable at all.
24
+ // The default is evaluated HERE, per call. Hoisting the read to module scope
25
+ // would leave every test green, so the optional parameter is what makes the
26
+ // per-call contract assertable.
25
27
  return thinkingArgs(resolveReasoning(group, cfg ?? getConfig()));
26
28
  }