@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
@@ -3,25 +3,18 @@
3
3
  * (`/task-auto`) — and the one place its numbering, its formatting and its
4
4
  * provenance policy live.
5
5
  *
6
- * `question-dialog.ts` unified the ANSWER side of these loops: the picker cards
7
- * and the reply mapping. It did not unify what the loop RECORDS, and that was
8
- * eight retyped push sites across two files, each choosing a suffix by hand
9
- * according to which branch of an `if/else` it stood in.
6
+ * `question-dialog.ts` owns the ANSWER side of these loops the picker cards and
7
+ * the reply mapping. This owns what the loop RECORDS.
10
8
  *
11
- * The cost is written into the code. `phases.ts` states the invariant in a
12
- * comment *"No provenance stamp here, unlike clarify's transcript: this string
13
- * is fed back VERBATIM into the next grill-gen prompt, so a `(accepted
14
- * recommendation)` suffix would become model input"* and TWELVE LINES ABOVE it,
15
- * the YOLO branch pushes `${answer} ${YOLO_STAMP}` into that very array. The rule
16
- * was violated inside the loop body that declares it, because the rule lived in
17
- * prose and the decision lived at each push.
18
- *
19
- * Here it is a property of a value: an entry states its KIND, and the policy says
20
- * where that kind's provenance is allowed to appear.
9
+ * Provenance is a property of a value here, not a decision taken at each push
10
+ * site: an entry states its KIND, and the policy says where that kind's
11
+ * provenance is allowed to appear. The two renderings below differ ONLY in those
12
+ * suffixes, which is how a hand-stamped transcript drifts apart unnoticed.
21
13
  *
22
14
  * NOT unified here: `plan-session.ts`'s `PlanEntry` transcript. It is a different
23
- * shape — decisions vs advisory notes, persisted to its own task file, with no
24
- * `Qn:`/`An:` numbering — and folding it in would be a rename, not a deepening.
15
+ * shape — model decisions, advisory notes and user-stated decisions in one list,
16
+ * persisted to its own task file — and folding it in would be a rename, not a
17
+ * deepening.
25
18
  */
26
19
  import { YOLO_STAMP } from './yolo.js';
27
20
  /**
@@ -42,10 +35,11 @@ export const QA_PROVENANCE = {
42
35
  * GRILL: stamps `auto` and both YOLO kinds in the record, and shows the generator
43
36
  * nothing.
44
37
  *
45
- * `accepted` is deliberately NOT in the record set. Grill's record reaches
46
- * `COMPOSE_PROMPT` and `CRITIQUE_PROMPT`, where it is named GROUND TRUTH; clarify's
47
- * reaches a decompose prompt. Whether those two should agree is a prompt question
48
- * with its own A/B, so today's answer is preserved rather than harmonised here.
38
+ * `accepted` is deliberately NOT in the record set, and clarify's policy below
39
+ * disagrees. Grill's record is handed to `COMPOSE_PROMPT` and `CRITIQUE_PROMPT`
40
+ * (the latter names the Q&A GROUND TRUTH); clarify's is handed to
41
+ * `AUTO_DECOMPOSE_PROMPT`. Whether the two should agree is a question about those
42
+ * prompts, so each keeps its own answer here.
49
43
  */
50
44
  export const GRILL_QA_POLICY = {
51
45
  record: new Set(['auto', 'yolo', 'yolo-skip']),
@@ -75,7 +69,7 @@ export class QaTranscript {
75
69
  get entries() {
76
70
  return this._entries;
77
71
  }
78
- /** Record one answered question. The number is assigned here, not by the caller. */
72
+ /** Record one answered question. Position IS the number; no caller supplies one. */
79
73
  add(kind, question, answer) {
80
74
  this._entries.push({ kind, question, answer });
81
75
  }
@@ -1,14 +1,15 @@
1
1
  /**
2
2
  * Boxed question dialog for the clarify / grill phases.
3
3
  *
4
- * The built-in `ctx.ui.select` renders every option as a bare line under one
5
- * outer frame the question, the recommendation, and the choices all read as a
6
- * single blob. The remote (browser) prompt card instead gives each response its
7
- * own bounded panel, tints the recommended one green, and separates everything
8
- * with margins. This module mirrors that remote style in the terminal: a custom
9
- * `ctx.ui.custom` component that draws each answer in its own bounding box with a
10
- * green RECOMMENDED tag, an accent-highlighted cursor box, and clear vertical
11
- * spacing.
4
+ * The built-in `ctx.ui.select` takes `options: string[]` and builds one
5
+ * `SelectList` inside a single `frame` (pi-coding-agent's llama/ui.js), so the
6
+ * question, the recommendation and the choices read as one blob and no option can
7
+ * be styled apart from the rest. The remote prompt card instead puts the
8
+ * recommendation in its own panel with a green left border and a green label
9
+ * (`.rec-panel` / `.rec-label` in remote/ui-styles.ts). This module mirrors that in
10
+ * the terminal: a `ctx.ui.custom` component that draws each answer in its own
11
+ * bounding box with a green RECOMMENDED tag, an accent cursor bar, and vertical
12
+ * spacing between cards.
12
13
  *
13
14
  * `renderQuestionBox` is the pure layout — width in, lines out — so the visual
14
15
  * structure (borders, tag, cursor arrow, padding) is unit-testable without a
@@ -41,12 +42,14 @@ export declare const HINT_TEXT = "\u2191\u2193 navigate \u00B7 enter select \u00
41
42
  export declare const MANUAL_CARD_LABEL = "\u270E Type a different answer\u2026";
42
43
  /**
43
44
  * Lay the whole dialog out for `width` columns: a QUESTION label + wrapped
44
- * question, one bounding box per card (recommended tinted green, the cursor box
45
- * highlighted with an accent border and "" arrow), and a key-hint footer.
45
+ * question, one bounding box per card (the recommended one tinted green, the
46
+ * selected one given an accent border and a "" bar in the gutter), and a
47
+ * key-hint footer.
46
48
  */
47
49
  export declare function renderQuestionBox(width: number, question: string, cards: BoxCard[], selected: number, c: BoxColors, hintText?: string): string[];
48
50
  export declare function boxColors(theme: ThemeLike): BoxColors;
49
- /** Focusable picker component; navigation mirrors the built-in select dialog. */
51
+ /** Focusable picker component. Navigation is pi-tui's own `tui.select.up`,
52
+ * `.down`, `.confirm` and `.cancel` bindings, plus `j`/`k`. */
50
53
  export declare class QuestionBoxComponent implements Component {
51
54
  private readonly question;
52
55
  private readonly cards;
@@ -54,8 +57,9 @@ export declare class QuestionBoxComponent implements Component {
54
57
  private readonly onChoose;
55
58
  private readonly onCancel;
56
59
  private selected;
57
- /** Card labels in display order (recommended first, manual last). Read-only
58
- * view for tests that drive the picker without parsing rendered output. */
60
+ /** Card labels in display order, free-text card included at whatever index
61
+ * `manualPosition` put it. Read-only view for tests that drive the picker
62
+ * without parsing rendered output. */
59
63
  get cardLabels(): string[];
60
64
  /** The question header text. Read-only view for tests. */
61
65
  get headerText(): string;
@@ -1,14 +1,15 @@
1
1
  /**
2
2
  * Boxed question dialog for the clarify / grill phases.
3
3
  *
4
- * The built-in `ctx.ui.select` renders every option as a bare line under one
5
- * outer frame the question, the recommendation, and the choices all read as a
6
- * single blob. The remote (browser) prompt card instead gives each response its
7
- * own bounded panel, tints the recommended one green, and separates everything
8
- * with margins. This module mirrors that remote style in the terminal: a custom
9
- * `ctx.ui.custom` component that draws each answer in its own bounding box with a
10
- * green RECOMMENDED tag, an accent-highlighted cursor box, and clear vertical
11
- * spacing.
4
+ * The built-in `ctx.ui.select` takes `options: string[]` and builds one
5
+ * `SelectList` inside a single `frame` (pi-coding-agent's llama/ui.js), so the
6
+ * question, the recommendation and the choices read as one blob and no option can
7
+ * be styled apart from the rest. The remote prompt card instead puts the
8
+ * recommendation in its own panel with a green left border and a green label
9
+ * (`.rec-panel` / `.rec-label` in remote/ui-styles.ts). This module mirrors that in
10
+ * the terminal: a `ctx.ui.custom` component that draws each answer in its own
11
+ * bounding box with a green RECOMMENDED tag, an accent cursor bar, and vertical
12
+ * spacing between cards.
12
13
  *
13
14
  * `renderQuestionBox` is the pure layout — width in, lines out — so the visual
14
15
  * structure (borders, tag, cursor arrow, padding) is unit-testable without a
@@ -53,15 +54,16 @@ function renderCard(card, selected, boxWidth, c) {
53
54
  const bodyLines = wrapTextWithAnsi(card.label, innerWidth);
54
55
  const body = (bodyLines.length > 0 ? bodyLines : ['']).map(line => borderFn('│ ') + padTo(line, innerWidth) + borderFn(' │'));
55
56
  const bottom = borderFn(`└${dash(boxWidth - 2)}┘`);
56
- // A full-height accent bar in the gutter marks the selected card far more
57
- // visible than a single "▸" glyph on the top border alone.
57
+ // A full-height accent bar in the gutter marks the selected card; it occupies
58
+ // the two GUTTER columns every card reserves, so nothing shifts.
58
59
  const cursor = selected ? c.arrow('▌') + ' ' : ' ';
59
60
  return [cursor + top, ...body.map(b => cursor + b), cursor + bottom];
60
61
  }
61
62
  /**
62
63
  * Lay the whole dialog out for `width` columns: a QUESTION label + wrapped
63
- * question, one bounding box per card (recommended tinted green, the cursor box
64
- * highlighted with an accent border and "" arrow), and a key-hint footer.
64
+ * question, one bounding box per card (the recommended one tinted green, the
65
+ * selected one given an accent border and a "" bar in the gutter), and a
66
+ * key-hint footer.
65
67
  */
66
68
  export function renderQuestionBox(width, question, cards, selected, c, hintText = HINT_TEXT) {
67
69
  const W = Math.min(Math.max(width, 12), MAX_CONTENT_WIDTH);
@@ -93,7 +95,8 @@ export function boxColors(theme) {
93
95
  };
94
96
  }
95
97
  // ─── Component ─────────────────────────────────────────────────────────────────
96
- /** Focusable picker component; navigation mirrors the built-in select dialog. */
98
+ /** Focusable picker component. Navigation is pi-tui's own `tui.select.up`,
99
+ * `.down`, `.confirm` and `.cancel` bindings, plus `j`/`k`. */
97
100
  export class QuestionBoxComponent {
98
101
  question;
99
102
  cards;
@@ -101,8 +104,9 @@ export class QuestionBoxComponent {
101
104
  onChoose;
102
105
  onCancel;
103
106
  selected = 0;
104
- /** Card labels in display order (recommended first, manual last). Read-only
105
- * view for tests that drive the picker without parsing rendered output. */
107
+ /** Card labels in display order, free-text card included at whatever index
108
+ * `manualPosition` put it. Read-only view for tests that drive the picker
109
+ * without parsing rendered output. */
106
110
  get cardLabels() {
107
111
  return this.cards.map(c => c.label);
108
112
  }
@@ -1,14 +1,13 @@
1
1
  /**
2
2
  * Detects when a freshly-generated clarifying question is a near-duplicate of one
3
3
  * already asked. The clarify/grill loops re-call the generator after every answer
4
- * and rely on a prompt instruction ("Never re-ask something already answered") to
5
- * stop repeats. A weaker local model ignores that and re-asks the same fork worded
6
- * differently (observed: a "Bun bundler vs Vite" question asked four ways across a
7
- * single run). This is a deterministic backstop so a model that won't self-police
8
- * can't barrage the user with the same decision.
4
+ * and rely on a prompt instruction "Never re-ask something already answered",
5
+ * carried by both prompts.ts and auto-prompts.ts to stop repeats. A model that
6
+ * ignores it re-asks the same fork worded differently, so this is a deterministic
7
+ * backstop against barraging the user with one decision.
9
8
  *
10
- * Pure logic, no I/O trivially unit-testable, and validated against the actual
11
- * repeated questions from a real /task-auto run (see question-dedup.test.ts).
9
+ * Pure logic, no I/O: the module imports nothing. question-dedup.test.ts drives it
10
+ * against a recorded set of ten questions in which three restate one earlier fork.
12
11
  */
13
12
  /**
14
13
  * Lowercase, drop markdown emphasis/backticks, split on non-alphanumeric, then
@@ -1,14 +1,13 @@
1
1
  /**
2
2
  * Detects when a freshly-generated clarifying question is a near-duplicate of one
3
3
  * already asked. The clarify/grill loops re-call the generator after every answer
4
- * and rely on a prompt instruction ("Never re-ask something already answered") to
5
- * stop repeats. A weaker local model ignores that and re-asks the same fork worded
6
- * differently (observed: a "Bun bundler vs Vite" question asked four ways across a
7
- * single run). This is a deterministic backstop so a model that won't self-police
8
- * can't barrage the user with the same decision.
4
+ * and rely on a prompt instruction "Never re-ask something already answered",
5
+ * carried by both prompts.ts and auto-prompts.ts to stop repeats. A model that
6
+ * ignores it re-asks the same fork worded differently, so this is a deterministic
7
+ * backstop against barraging the user with one decision.
9
8
  *
10
- * Pure logic, no I/O trivially unit-testable, and validated against the actual
11
- * repeated questions from a real /task-auto run (see question-dedup.test.ts).
9
+ * Pure logic, no I/O: the module imports nothing. question-dedup.test.ts drives it
10
+ * against a recorded set of ten questions in which three restate one earlier fork.
12
11
  */
13
12
  // Function words plus the boilerplate the prompt makes every question share
14
13
  // ("should we use", "or should", "this determines whether the task", …). Stripping
@@ -142,11 +141,11 @@ export function jaccard(a, b) {
142
141
  const union = a.size + b.size - inter;
143
142
  return union === 0 ? 0 : inter / union;
144
143
  }
145
- // Validated against the real mx5 run (question-dedup.test.ts): the re-asked
146
- // SPA-build/serve forks scored 0.152 / 0.275 / 0.421 against an earlier question,
147
- // while every genuinely-distinct subsystem question topped out at 0.077. 0.12 sits
148
- // in that gap above the distinct ceiling, below the lowest true duplicate — so
149
- // it catches the repeats without suppressing a real question.
144
+ // The similarity at which a question counts as a re-ask. It is low because the
145
+ // stopword list has already stripped the scaffolding every generated question
146
+ // shares, leaving only the salient nouns: two questions about the same fork overlap
147
+ // on those, two different subsystems share almost none. question-dedup.test.ts pins
148
+ // both sides the re-asks must be caught, the distinct questions must not be.
150
149
  export const DEFAULT_DUP_THRESHOLD = 0.12;
151
150
  /**
152
151
  * True when `next` is a near-duplicate of any question in `prior` (Jaccard of
@@ -161,8 +160,8 @@ export function isDuplicateQuestion(prior, next, threshold = DEFAULT_DUP_THRESHO
161
160
  }
162
161
  // After this many consecutive near-duplicate questions, the question loop stops:
163
162
  // a model that can't produce a novel question after being told to move on has
164
- // nothing genuinely new left to ask. Shared by /task-auto's clarify loop and
165
- // /task's grill loop.
163
+ // nothing genuinely new left to ask. Read by grill (phases.ts) and by the shared
164
+ // question source (question-source.ts) that clarify and /task-plan both drive.
166
165
  export const MAX_DUP_STRIKES = 2;
167
166
  // Reprompt injected when a duplicate is caught — tells the model the topic is
168
167
  // settled and to either move to a different open fork or finish.
@@ -7,26 +7,17 @@
7
7
  * display; decide whether the question is a binary fork; short-circuit under
8
8
  * YOLO; build `A: …` / `B: …` cards; call `ui.ask`; treat `undefined` as a
9
9
  * cancel; and map the reply back onto an answer — where an empty submit accepts
10
- * the recommendation, a bare "A"/"B" from a remote user (or the picker's
11
- * free-text fallback) maps back to the option's full text, and anything else is
12
- * taken verbatim.
10
+ * the recommendation, a bare "A"/"B" ON A FORK (from a remote user, or from the
11
+ * picker's free-text fallback) maps back to that option's full text, and anything
12
+ * else is taken verbatim.
13
13
  *
14
- * The mapping is the load-bearing part. Storing the literal letter "A" leaves the
15
- * next generation call a dangling reference it cannot decode, so getting it wrong
16
- * is not cosmetic.
14
+ * The mapping is the load-bearing part. The recorded answer is fed back into the
15
+ * next generation call, so storing the literal letter "A" would hand that call a
16
+ * dangling reference it cannot decode.
17
17
  *
18
- * It was written three times. The Plan session factored its copy into a pure
19
- * `resolveAnswer` returning a typed `AnswerSource`, and its own docstring said so
20
- * out loud "Mirrors the identical mapping in phaseGrill and planAuto" — but the
21
- * two mirrors were never converted, and they had already drifted apart in three
22
- * ways (which of them stamps an accepted recommendation, which has a
23
- * single-option card branch, which handles a typed reply that equals an option).
24
- * None was a crash. The next edit to any of them is where the bug lands, which is
25
- * why they now share this.
26
- *
27
- * What stays at the call sites is POLICY, not mechanics: grill's auto-answer and
28
- * widget line, clarify's plan-shape and triage pre-emption, plan's control
29
- * actions. Those genuinely differ.
18
+ * What stays at the call sites is POLICY, not mechanics: grill's auto-answer
19
+ * (`phaseAutoAnswer`) and its widget line, clarify's plan-shape fork and
20
+ * answer-side triage, plan's control actions. Those genuinely differ.
30
21
  */
31
22
  import type { AnswerSource } from './plan-io.js';
32
23
  import type { YoloPick } from './yolo.js';
@@ -46,8 +37,10 @@ export declare function isTwoOption(p: PendingQuestion): boolean;
46
37
  /**
47
38
  * The answer cards: the recommendation first (index 0 is the green RECOMMENDED
48
39
  * card), the alternative second when the question is a fork. `undefined` — not an
49
- * empty array — when there is nothing to recommend, because that is what makes
50
- * `ui.ask` fall back to a bare text prompt instead of an empty picker.
40
+ * empty array — when there is nothing to recommend, so a conditional spread of the
41
+ * result leaves the `options` key off the ask spec entirely. Either way the local
42
+ * side falls back to a bare text prompt: bridge.ts boxes only when
43
+ * `options.length > 0`.
51
44
  */
52
45
  export declare function buildOptionCards(p: PendingQuestion): Array<{
53
46
  label: string;
@@ -57,14 +50,13 @@ export declare function buildOptionCards(p: PendingQuestion): Array<{
57
50
  * Map what the picker returned onto the answer that gets recorded, and say WHERE
58
51
  * the answer came from.
59
52
  *
60
- * The `source` is returned rather than baked into the string because the three
61
- * call sites disagree about provenance stamping, and that disagreement is real:
62
- * `/task-auto`'s clarify transcript marks an accepted recommendation
63
- * ("… (accepted recommendation)") while grill's does not, because grill's
64
- * transcript is fed back verbatim into the next grill-gen prompt and the stamp
65
- * would become model input. Keeping the stamp at the call site makes that a
66
- * one-line difference you can see instead of a divergence hidden inside two
67
- * six-branch ladders.
53
+ * The `source` is returned rather than baked into the string because each
54
+ * transcript owns its own provenance table `QA_PROVENANCE` (qa-transcript.ts)
55
+ * for grill and clarify, `SOURCE_STAMP` (plan-io.ts) for the plan file — and they
56
+ * disagree. That disagreement is real: clarify marks an accepted recommendation
57
+ * "(accepted recommendation)" while grill marks nothing, because grill's
58
+ * transcript is fed back verbatim into the next grill-gen prompt, where the stamp
59
+ * would become model input rather than the answer.
68
60
  */
69
61
  export declare function resolveAnswer(p: PendingQuestion, raw: string): {
70
62
  answer: string;
@@ -119,9 +111,7 @@ export type SettledKind = 'yolo' | 'yolo-skip' | 'accepted' | 'typed';
119
111
  * Settle one question: YOLO short-circuit, cards, ask, record.
120
112
  *
121
113
  * Returns `'cancelled'` rather than throwing, because that is the one thing the
122
- * two callers genuinely disagree about grill throws `USER_CANCELLED` into the
123
- * phase ladder, clarify announces and returns null from the plan. Everything
124
- * before it was written out twice at ~50 lines each and had already drifted on
125
- * `recommended2`, harmless today only because the bridge re-guards it.
114
+ * two callers genuinely disagree about: grill throws `USER_CANCELLED` into the
115
+ * phase ladder, clarify announces and returns null from the plan.
126
116
  */
127
117
  export declare function settleQuestion(input: SettleQuestionInput): Promise<'settled' | 'cancelled'>;
@@ -7,26 +7,17 @@
7
7
  * display; decide whether the question is a binary fork; short-circuit under
8
8
  * YOLO; build `A: …` / `B: …` cards; call `ui.ask`; treat `undefined` as a
9
9
  * cancel; and map the reply back onto an answer — where an empty submit accepts
10
- * the recommendation, a bare "A"/"B" from a remote user (or the picker's
11
- * free-text fallback) maps back to the option's full text, and anything else is
12
- * taken verbatim.
10
+ * the recommendation, a bare "A"/"B" ON A FORK (from a remote user, or from the
11
+ * picker's free-text fallback) maps back to that option's full text, and anything
12
+ * else is taken verbatim.
13
13
  *
14
- * The mapping is the load-bearing part. Storing the literal letter "A" leaves the
15
- * next generation call a dangling reference it cannot decode, so getting it wrong
16
- * is not cosmetic.
14
+ * The mapping is the load-bearing part. The recorded answer is fed back into the
15
+ * next generation call, so storing the literal letter "A" would hand that call a
16
+ * dangling reference it cannot decode.
17
17
  *
18
- * It was written three times. The Plan session factored its copy into a pure
19
- * `resolveAnswer` returning a typed `AnswerSource`, and its own docstring said so
20
- * out loud "Mirrors the identical mapping in phaseGrill and planAuto" — but the
21
- * two mirrors were never converted, and they had already drifted apart in three
22
- * ways (which of them stamps an accepted recommendation, which has a
23
- * single-option card branch, which handles a typed reply that equals an option).
24
- * None was a crash. The next edit to any of them is where the bug lands, which is
25
- * why they now share this.
26
- *
27
- * What stays at the call sites is POLICY, not mechanics: grill's auto-answer and
28
- * widget line, clarify's plan-shape and triage pre-emption, plan's control
29
- * actions. Those genuinely differ.
18
+ * What stays at the call sites is POLICY, not mechanics: grill's auto-answer
19
+ * (`phaseAutoAnswer`) and its widget line, clarify's plan-shape fork and
20
+ * answer-side triage, plan's control actions. Those genuinely differ.
30
21
  */
31
22
  import { stripInlineMarkdown } from './inline-markdown.js';
32
23
  /** True when the question is a binary fork rather than a single recommendation. */
@@ -36,8 +27,10 @@ export function isTwoOption(p) {
36
27
  /**
37
28
  * The answer cards: the recommendation first (index 0 is the green RECOMMENDED
38
29
  * card), the alternative second when the question is a fork. `undefined` — not an
39
- * empty array — when there is nothing to recommend, because that is what makes
40
- * `ui.ask` fall back to a bare text prompt instead of an empty picker.
30
+ * empty array — when there is nothing to recommend, so a conditional spread of the
31
+ * result leaves the `options` key off the ask spec entirely. Either way the local
32
+ * side falls back to a bare text prompt: bridge.ts boxes only when
33
+ * `options.length > 0`.
41
34
  */
42
35
  export function buildOptionCards(p) {
43
36
  if (isTwoOption(p)) {
@@ -55,14 +48,13 @@ export function buildOptionCards(p) {
55
48
  * Map what the picker returned onto the answer that gets recorded, and say WHERE
56
49
  * the answer came from.
57
50
  *
58
- * The `source` is returned rather than baked into the string because the three
59
- * call sites disagree about provenance stamping, and that disagreement is real:
60
- * `/task-auto`'s clarify transcript marks an accepted recommendation
61
- * ("… (accepted recommendation)") while grill's does not, because grill's
62
- * transcript is fed back verbatim into the next grill-gen prompt and the stamp
63
- * would become model input. Keeping the stamp at the call site makes that a
64
- * one-line difference you can see instead of a divergence hidden inside two
65
- * six-branch ladders.
51
+ * The `source` is returned rather than baked into the string because each
52
+ * transcript owns its own provenance table `QA_PROVENANCE` (qa-transcript.ts)
53
+ * for grill and clarify, `SOURCE_STAMP` (plan-io.ts) for the plan file — and they
54
+ * disagree. That disagreement is real: clarify marks an accepted recommendation
55
+ * "(accepted recommendation)" while grill marks nothing, because grill's
56
+ * transcript is fed back verbatim into the next grill-gen prompt, where the stamp
57
+ * would become model input rather than the answer.
66
58
  */
67
59
  export function resolveAnswer(p, raw) {
68
60
  const typed = raw.trim();
@@ -92,10 +84,8 @@ export function resolveAnswer(p, raw) {
92
84
  * Settle one question: YOLO short-circuit, cards, ask, record.
93
85
  *
94
86
  * Returns `'cancelled'` rather than throwing, because that is the one thing the
95
- * two callers genuinely disagree about grill throws `USER_CANCELLED` into the
96
- * phase ladder, clarify announces and returns null from the plan. Everything
97
- * before it was written out twice at ~50 lines each and had already drifted on
98
- * `recommended2`, harmless today only because the bridge re-guards it.
87
+ * two callers genuinely disagree about: grill throws `USER_CANCELLED` into the
88
+ * phase ladder, clarify announces and returns null from the plan.
99
89
  */
100
90
  export async function settleQuestion(input) {
101
91
  const { ui, transcript, plain, shown, render, yolo } = input;
@@ -1,36 +1,12 @@
1
1
  /**
2
- * Where the NEXT question comes from — the other half of `question-dialog.ts`.
2
+ * Where the NEXT question comes from — the other half of `question-dialog.ts`,
3
+ * which owns the ANSWER side.
3
4
  *
4
- * `question-dialog.ts` unified the ANSWER side of the adaptive dialogs (the picker
5
- * cards, the reply mapping) and its own docstring makes the argument for doing so:
6
- * *"It was written three times… the two mirrors were never converted, and they had
7
- * already drifted apart in three ways… The next edit to any of them is where the
8
- * bug lands."* The QUESTION side — generate → parse → pick the real question →
9
- * dedupe → spend one corrective re-prompt → yield or exhaust — was left behind,
10
- * and it had drifted between the two loops that use the SAME parser on the SAME
11
- * prompt format (`plan-prompts.ts` says `parseClarifyList` parses it "UNCHANGED";
12
- * `auto-prompts.ts` specifies the identical shape).
13
- *
14
- * The five drifts, all in clarify's favour of being wrong:
15
- *
16
- * 1. **Which entry is the question.** `parseClarifyList` pushes an entry for
17
- * EVERY numbered line, and the local model writes numbered analysis notes
18
- * before the question it was asked for (measured live). `pickQuestion` prefers
19
- * the first entry carrying a `SUGGESTED:` line; clarify took `parsed[0]`
20
- * blindly, showing the note as the question and losing the recommendation
21
- * attached further down.
22
- * 2. **NONE vs unparseable.** The parser returns `[]` for both. Clarify's
23
- * `if (parsed.length === 0) break` ended the whole clarify — and decomposed the
24
- * feature with ZERO clarifications — on a formatting slip.
25
- * 3. **A re-typed sentinel.** `isNoneReply`'s regex was a byte-identical second
26
- * copy of the parser's own.
27
- * 4. **Missing SUGGESTED** bought one corrective re-prompt in plan and none in
28
- * clarify, so clarify showed a card-less question.
29
- * 5. **The deferral guard.** It exists because an accepted "clarify with the user
30
- * before proceeding" rode into `/task`'s handoff AS AN AUTHORITATIVE DECISION
31
- * and produced a task whose VERIFY asserted no source file had changed.
32
- * Clarify's answers ride into the decompose prompt and the AUTO file with
33
- * exactly the same authority, and had no guard.
5
+ * One state machine: generate parse → pick the real question dedupe → spend
6
+ * one corrective re-prompt yield or exhaust. Two loops drive it, `/task-auto`'s
7
+ * clarify and `/task-plan`, and they use the SAME parser on the SAME prompt format
8
+ * plan-prompts.ts says `parseClarifyList` parses its output UNCHANGED, and
9
+ * auto-prompts.ts specifies the identical shape.
34
10
  *
35
11
  * NOT unified here: grill's generation loop. It uses a different parser
36
12
  * (`parseGrillQuestions`, which yields bare strings) and has no `SUGGESTED` at
@@ -41,11 +17,9 @@
41
17
  */
42
18
  import { type ClarifyQuestion } from './parsers.js';
43
19
  /**
44
- * The cap on distinct questions ONE adaptive dialog may ask.
45
- *
46
- * Clarify and plan each declared their own `8`, linked only by a comment saying
47
- * "matches /task-auto's MAX_CLARIFY_QUESTIONS, for the same reason". They bound
48
- * the same thing for the same reason; this is that reason, once.
20
+ * Default cap on distinct questions ONE adaptive dialog may ask. Both live
21
+ * callers pass their own constant of the same value instead
22
+ * (MAX_CLARIFY_QUESTIONS, MAX_PLAN_QUESTIONS); this is what an unset `cap` gets.
49
23
  */
50
24
  export declare const MAX_DIALOG_QUESTIONS = 8;
51
25
  /** True when the reply is the deliberate "nothing left to ask" sentinel, as
@@ -54,13 +28,12 @@ export declare function isNoneReply(raw: string): boolean;
54
28
  /**
55
29
  * Which of the parsed entries is the actual question.
56
30
  *
57
- * `parseClarifyList` turns EVERY numbered line into an entry, and the local model
58
- * sometimes writes a numbered analysis note or two before the question it was
59
- * asked for (measured live: the first numbered line was a note like
60
- * "1. gateDebugWriter in orchestrator.ts wraps a raw append function"). Taking
61
- * entry 0 blindly then shows the note as the question and loses the SUGGESTED line
62
- * attached further down. The prompt requires exactly one SUGGESTED, and the parser
63
- * attaches it to the entry it follows.
31
+ * `parseClarifyList` turns EVERY numbered line into an entry, and a model that
32
+ * writes a numbered analysis note before the question it was asked for produces
33
+ * more than one. Taking entry 0 blindly then shows the note as the question and
34
+ * loses the SUGGESTED line attached further down. The prompt requires exactly one
35
+ * SUGGESTED, and the parser attaches it to the entry it follows, so preferring the
36
+ * entry that HAS one lands on the real question.
64
37
  */
65
38
  export declare function pickQuestion<T extends {
66
39
  suggested?: string;
@@ -88,7 +61,8 @@ export interface QuestionSourceDeps {
88
61
  generate: (hint: string | null) => Promise<string>;
89
62
  /** The corrective re-prompt for a reply the parser could not read. */
90
63
  formatHint: string;
91
- /** Ordered quality rules; each may fire at most once per question. */
64
+ /** Ordered quality rules. At most ONE fires per question: they share a single
65
+ * corrective re-prompt, spent by the first rule that detects a defect. */
92
66
  rules?: ReadonlyArray<QuestionRule>;
93
67
  cap?: number;
94
68
  log?: (msg: string) => void;