@mjasnikovs/pi-task 0.38.29 → 0.38.30

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 (370) 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/remote/bridge.d.ts +19 -10
  14. package/dist/remote/bridge.js +3 -2
  15. package/dist/remote/broadcast.js +3 -1
  16. package/dist/remote/events.js +12 -11
  17. package/dist/remote/history.d.ts +1 -1
  18. package/dist/remote/protocol.d.ts +6 -3
  19. package/dist/remote/protocol.js +2 -1
  20. package/dist/remote/push.d.ts +16 -16
  21. package/dist/remote/push.js +27 -27
  22. package/dist/remote/register.d.ts +3 -3
  23. package/dist/remote/register.js +17 -19
  24. package/dist/remote/server.d.ts +9 -8
  25. package/dist/remote/server.js +15 -14
  26. package/dist/remote/session-state.d.ts +5 -4
  27. package/dist/remote/session-state.js +8 -5
  28. package/dist/remote/sw.d.ts +7 -6
  29. package/dist/remote/sw.js +7 -6
  30. package/dist/remote/tailscale.d.ts +4 -2
  31. package/dist/remote/tailscale.js +4 -2
  32. package/dist/remote/ui-highlight.js +6 -5
  33. package/dist/remote/ui-render.js +4 -4
  34. package/dist/remote/ui-script.js +24 -24
  35. package/dist/remote/ui-styles.d.ts +1 -1
  36. package/dist/remote/ui-styles.js +10 -13
  37. package/dist/remote/ui-tools.js +9 -6
  38. package/dist/shared/child-extensions.d.ts +29 -17
  39. package/dist/shared/child-extensions.js +29 -17
  40. package/dist/shared/child-output.d.ts +30 -24
  41. package/dist/shared/child-output.js +25 -17
  42. package/dist/shared/child-process.d.ts +47 -40
  43. package/dist/shared/child-process.js +50 -59
  44. package/dist/shared/command-watchdog.d.ts +22 -16
  45. package/dist/shared/command-watchdog.js +28 -21
  46. package/dist/shared/fs-text.d.ts +16 -10
  47. package/dist/shared/fs-text.js +16 -10
  48. package/dist/shared/git-runner.d.ts +25 -25
  49. package/dist/shared/git-runner.js +25 -25
  50. package/dist/shared/leaked-tool-call.d.ts +17 -11
  51. package/dist/shared/leaked-tool-call.js +23 -15
  52. package/dist/shared/model-endpoint.d.ts +29 -16
  53. package/dist/shared/model-endpoint.js +33 -21
  54. package/dist/shared/pi-invocation.d.ts +7 -4
  55. package/dist/shared/pi-invocation.js +12 -7
  56. package/dist/shared/pkg-version.d.ts +13 -5
  57. package/dist/shared/pkg-version.js +13 -5
  58. package/dist/shared/reasoning-capability.d.ts +35 -24
  59. package/dist/shared/reasoning-capability.js +35 -24
  60. package/dist/shared/stream-watchdog.d.ts +60 -44
  61. package/dist/shared/stream-watchdog.js +62 -45
  62. package/dist/task/accept-debt.d.ts +41 -43
  63. package/dist/task/accept-debt.js +73 -65
  64. package/dist/task/api-synthesis.d.ts +24 -21
  65. package/dist/task/api-synthesis.js +32 -26
  66. package/dist/task/apis-contract.d.ts +32 -64
  67. package/dist/task/apis-contract.js +32 -64
  68. package/dist/task/artifact-closure.d.ts +27 -13
  69. package/dist/task/artifact-closure.js +95 -67
  70. package/dist/task/auto-commit.d.ts +46 -35
  71. package/dist/task/auto-commit.js +51 -38
  72. package/dist/task/auto-io.d.ts +45 -25
  73. package/dist/task/auto-io.js +57 -29
  74. package/dist/task/auto-orchestrator.d.ts +26 -24
  75. package/dist/task/auto-orchestrator.js +178 -162
  76. package/dist/task/auto-prompts.d.ts +36 -24
  77. package/dist/task/auto-prompts.js +40 -26
  78. package/dist/task/autofix-ledger.d.ts +27 -25
  79. package/dist/task/autofix-ledger.js +29 -26
  80. package/dist/task/batch-test-task.d.ts +20 -12
  81. package/dist/task/batch-test-task.js +67 -60
  82. package/dist/task/boot-probe.d.ts +60 -44
  83. package/dist/task/boot-probe.js +91 -72
  84. package/dist/task/cancel-input.d.ts +30 -16
  85. package/dist/task/cancel-input.js +20 -11
  86. package/dist/task/cancel-points.d.ts +27 -20
  87. package/dist/task/cancel-points.js +30 -22
  88. package/dist/task/child-runner.d.ts +46 -51
  89. package/dist/task/child-runner.js +48 -49
  90. package/dist/task/child-status.d.ts +23 -16
  91. package/dist/task/child-status.js +23 -16
  92. package/dist/task/clamp-output.js +12 -5
  93. package/dist/task/command-run.d.ts +31 -28
  94. package/dist/task/command-run.js +44 -35
  95. package/dist/task/command-shrink.d.ts +25 -18
  96. package/dist/task/command-shrink.js +37 -31
  97. package/dist/task/command-watchdog.d.ts +9 -6
  98. package/dist/task/command-watchdog.js +21 -15
  99. package/dist/task/context-attribution.d.ts +34 -26
  100. package/dist/task/context-attribution.js +34 -26
  101. package/dist/task/context-silence.d.ts +39 -29
  102. package/dist/task/context-silence.js +35 -25
  103. package/dist/task/context-usage.d.ts +16 -9
  104. package/dist/task/context-usage.js +16 -9
  105. package/dist/task/contracts.d.ts +8 -4
  106. package/dist/task/contracts.js +25 -17
  107. package/dist/task/coverage-loop.d.ts +22 -18
  108. package/dist/task/coverage-loop.js +35 -30
  109. package/dist/task/critique-probes.d.ts +13 -14
  110. package/dist/task/critique-probes.js +50 -39
  111. package/dist/task/debug-log.d.ts +13 -5
  112. package/dist/task/debug-log.js +32 -20
  113. package/dist/task/decompose-fidelity.d.ts +11 -9
  114. package/dist/task/decompose-fidelity.js +38 -33
  115. package/dist/task/decompose-granularity.d.ts +41 -38
  116. package/dist/task/decompose-granularity.js +41 -38
  117. package/dist/task/deep-render-check.d.ts +22 -14
  118. package/dist/task/deep-render-check.js +40 -31
  119. package/dist/task/dropped-input.d.ts +12 -7
  120. package/dist/task/dropped-input.js +5 -2
  121. package/dist/task/enforce-attribution.d.ts +38 -47
  122. package/dist/task/enforce-attribution.js +46 -52
  123. package/dist/task/enforce-guidelines.d.ts +31 -20
  124. package/dist/task/enforce-guidelines.js +32 -21
  125. package/dist/task/enrichment.d.ts +7 -2
  126. package/dist/task/enrichment.js +26 -14
  127. package/dist/task/env-notes.d.ts +16 -7
  128. package/dist/task/env-notes.js +48 -31
  129. package/dist/task/env-template-closure.d.ts +4 -4
  130. package/dist/task/env-template-closure.js +42 -34
  131. package/dist/task/external-context.d.ts +28 -21
  132. package/dist/task/external-context.js +17 -12
  133. package/dist/task/failure-classifier.d.ts +4 -5
  134. package/dist/task/failure-classifier.js +6 -7
  135. package/dist/task/file-inventory.d.ts +15 -11
  136. package/dist/task/file-inventory.js +25 -22
  137. package/dist/task/final-gate-fix.d.ts +74 -86
  138. package/dist/task/final-gate-fix.js +97 -116
  139. package/dist/task/final-gate-progress.d.ts +29 -46
  140. package/dist/task/final-gate-progress.js +40 -51
  141. package/dist/task/final-gate.d.ts +64 -97
  142. package/dist/task/final-gate.js +192 -199
  143. package/dist/task/fix-child.d.ts +21 -27
  144. package/dist/task/fix-child.js +21 -27
  145. package/dist/task/foreign-path.d.ts +6 -5
  146. package/dist/task/foreign-path.js +0 -0
  147. package/dist/task/frozen-conflict.d.ts +9 -10
  148. package/dist/task/frozen-conflict.js +61 -64
  149. package/dist/task/frozen-path-guard.d.ts +35 -14
  150. package/dist/task/frozen-path-guard.js +56 -39
  151. package/dist/task/gate-child.d.ts +27 -28
  152. package/dist/task/gate-child.js +36 -35
  153. package/dist/task/gate-deps.d.ts +34 -27
  154. package/dist/task/gate-deps.js +169 -159
  155. package/dist/task/gate-tally.d.ts +77 -80
  156. package/dist/task/gate-tally.js +65 -68
  157. package/dist/task/git-state-guard.d.ts +15 -11
  158. package/dist/task/git-state-guard.js +76 -66
  159. package/dist/task/impl-widget.d.ts +25 -16
  160. package/dist/task/impl-widget.js +27 -17
  161. package/dist/task/implementation-thinking.d.ts +33 -31
  162. package/dist/task/implementation-thinking.js +5 -6
  163. package/dist/task/implementation-turn.d.ts +34 -31
  164. package/dist/task/implementation-turn.js +29 -27
  165. package/dist/task/inline-markdown.d.ts +20 -7
  166. package/dist/task/inline-markdown.js +15 -6
  167. package/dist/task/launch-config-gap.js +25 -39
  168. package/dist/task/launch-contract.d.ts +18 -21
  169. package/dist/task/launch-contract.js +28 -30
  170. package/dist/task/launch-manifest.d.ts +6 -2
  171. package/dist/task/launch-manifest.js +35 -34
  172. package/dist/task/ledger.js +16 -14
  173. package/dist/task/lint-fix.d.ts +6 -8
  174. package/dist/task/lint-fix.js +67 -69
  175. package/dist/task/loop-detector.d.ts +9 -8
  176. package/dist/task/loop-detector.js +16 -12
  177. package/dist/task/mid-run-input.d.ts +17 -15
  178. package/dist/task/mid-run-input.js +17 -15
  179. package/dist/task/orchestrator.d.ts +24 -28
  180. package/dist/task/orchestrator.js +62 -64
  181. package/dist/task/orientation.d.ts +18 -23
  182. package/dist/task/orientation.js +24 -31
  183. package/dist/task/owned-freeze-conflict.d.ts +21 -20
  184. package/dist/task/owned-freeze-conflict.js +52 -85
  185. package/dist/task/owned-freeze-reassign.d.ts +40 -60
  186. package/dist/task/owned-freeze-reassign.js +41 -61
  187. package/dist/task/parsers.d.ts +4 -2
  188. package/dist/task/parsers.js +4 -4
  189. package/dist/task/phases.d.ts +41 -48
  190. package/dist/task/phases.js +179 -248
  191. package/dist/task/plan-io.d.ts +6 -7
  192. package/dist/task/plan-io.js +6 -7
  193. package/dist/task/plan-orchestrator.d.ts +10 -8
  194. package/dist/task/plan-orchestrator.js +14 -10
  195. package/dist/task/plan-prompts.d.ts +6 -5
  196. package/dist/task/plan-prompts.js +6 -5
  197. package/dist/task/plan-readonly.d.ts +4 -5
  198. package/dist/task/plan-readonly.js +4 -5
  199. package/dist/task/plan-rounds.d.ts +17 -29
  200. package/dist/task/plan-rounds.js +21 -34
  201. package/dist/task/plan-session.d.ts +58 -72
  202. package/dist/task/plan-session.js +61 -83
  203. package/dist/task/probe-gaming.d.ts +28 -27
  204. package/dist/task/probe-gaming.js +0 -0
  205. package/dist/task/prohibition-probe.d.ts +14 -16
  206. package/dist/task/prompts.d.ts +3 -4
  207. package/dist/task/prompts.js +17 -26
  208. package/dist/task/qa-transcript.d.ts +15 -22
  209. package/dist/task/qa-transcript.js +15 -21
  210. package/dist/task/question-box.d.ts +17 -13
  211. package/dist/task/question-box.js +19 -15
  212. package/dist/task/question-dedup.d.ts +6 -7
  213. package/dist/task/question-dedup.js +13 -14
  214. package/dist/task/question-dialog.d.ts +22 -32
  215. package/dist/task/question-dialog.js +22 -32
  216. package/dist/task/question-source.d.ts +18 -44
  217. package/dist/task/question-source.js +22 -51
  218. package/dist/task/refuted-constraint.d.ts +11 -31
  219. package/dist/task/refuted-constraint.js +27 -51
  220. package/dist/task/regenerable-artifacts.d.ts +12 -31
  221. package/dist/task/regenerable-artifacts.js +12 -31
  222. package/dist/task/render-check.d.ts +11 -22
  223. package/dist/task/render-check.js +33 -46
  224. package/dist/task/repo-health-check.d.ts +10 -14
  225. package/dist/task/repo-health-check.js +17 -23
  226. package/dist/task/requirements.d.ts +38 -71
  227. package/dist/task/requirements.js +78 -126
  228. package/dist/task/research-fanout-budget.d.ts +51 -88
  229. package/dist/task/research-fanout-budget.js +51 -88
  230. package/dist/task/research-worker.d.ts +29 -39
  231. package/dist/task/research-worker.js +37 -61
  232. package/dist/task/resume-gap.d.ts +14 -15
  233. package/dist/task/root-cause-repair.d.ts +9 -9
  234. package/dist/task/root-cause-repair.js +28 -40
  235. package/dist/task/run-bracket.d.ts +10 -13
  236. package/dist/task/run-end.d.ts +12 -22
  237. package/dist/task/run-end.js +8 -16
  238. package/dist/task/run-final-gate.d.ts +19 -21
  239. package/dist/task/run-final-gate.js +62 -80
  240. package/dist/task/runner-globs.d.ts +12 -13
  241. package/dist/task/runner-globs.js +12 -13
  242. package/dist/task/runner-resolve.d.ts +9 -9
  243. package/dist/task/runner-resolve.js +22 -23
  244. package/dist/task/script-escape.d.ts +10 -12
  245. package/dist/task/script-escape.js +13 -14
  246. package/dist/task/serve-entry.d.ts +1 -1
  247. package/dist/task/serve-entry.js +22 -25
  248. package/dist/task/service-blocks.js +4 -2
  249. package/dist/task/shipped-source.d.ts +11 -29
  250. package/dist/task/shipped-source.js +11 -29
  251. package/dist/task/skip-escape.js +10 -14
  252. package/dist/task/spec-urls.d.ts +26 -65
  253. package/dist/task/spec-urls.js +26 -65
  254. package/dist/task/spec-validation.d.ts +17 -20
  255. package/dist/task/spec-validation.js +17 -20
  256. package/dist/task/stall-detector.d.ts +23 -30
  257. package/dist/task/stall-detector.js +23 -30
  258. package/dist/task/stream-watchdog.d.ts +14 -12
  259. package/dist/task/stream-watchdog.js +14 -12
  260. package/dist/task/substitution-probe.d.ts +17 -20
  261. package/dist/task/substitution-probe.js +17 -20
  262. package/dist/task/task-gates.d.ts +36 -41
  263. package/dist/task/task-gates.js +95 -106
  264. package/dist/task/task-io.d.ts +4 -4
  265. package/dist/task/task-io.js +4 -4
  266. package/dist/task/task-parsers.js +4 -3
  267. package/dist/task/task-provenance.d.ts +2 -2
  268. package/dist/task/task-provenance.js +11 -13
  269. package/dist/task/task-types.d.ts +4 -3
  270. package/dist/task/terminal-outcome.d.ts +14 -16
  271. package/dist/task/terminal-outcome.js +12 -14
  272. package/dist/task/test-assembly.d.ts +13 -20
  273. package/dist/task/test-assembly.js +13 -20
  274. package/dist/task/timings.d.ts +5 -3
  275. package/dist/task/timings.js +5 -3
  276. package/dist/task/title-label.d.ts +9 -4
  277. package/dist/task/title-label.js +9 -4
  278. package/dist/task/type-only-answer.d.ts +44 -52
  279. package/dist/task/type-only-answer.js +44 -52
  280. package/dist/task/unfailable-command.d.ts +18 -24
  281. package/dist/task/unfailable-command.js +21 -27
  282. package/dist/task/unknown-routing.d.ts +10 -4
  283. package/dist/task/unknown-routing.js +10 -4
  284. package/dist/task/user-directives.d.ts +5 -8
  285. package/dist/task/user-directives.js +5 -8
  286. package/dist/task/verify-quality.d.ts +18 -22
  287. package/dist/task/verify-quality.js +45 -46
  288. package/dist/task/verify-reconcile.d.ts +15 -10
  289. package/dist/task/verify-reconcile.js +45 -43
  290. package/dist/task/verify-resolution.d.ts +24 -20
  291. package/dist/task/verify-resolution.js +51 -50
  292. package/dist/task/verify-work.d.ts +59 -66
  293. package/dist/task/verify-work.js +101 -138
  294. package/dist/task/widget.d.ts +15 -14
  295. package/dist/task/widget.js +22 -17
  296. package/dist/task/wiring-claims.d.ts +25 -32
  297. package/dist/task/wiring-claims.js +30 -35
  298. package/dist/task/write-guard.d.ts +39 -39
  299. package/dist/task/write-guard.js +48 -51
  300. package/dist/task/yolo.d.ts +34 -30
  301. package/dist/task/yolo.js +42 -37
  302. package/dist/workers/abstention.d.ts +21 -41
  303. package/dist/workers/abstention.js +27 -48
  304. package/dist/workers/brave-search.d.ts +4 -3
  305. package/dist/workers/brave-search.js +5 -2
  306. package/dist/workers/brave-warning.d.ts +7 -4
  307. package/dist/workers/brave-warning.js +19 -7
  308. package/dist/workers/ddg-search.d.ts +6 -6
  309. package/dist/workers/ddg-search.js +18 -12
  310. package/dist/workers/docs-cache.js +5 -2
  311. package/dist/workers/docs-chunk.d.ts +30 -37
  312. package/dist/workers/docs-chunk.js +37 -41
  313. package/dist/workers/docs-core.d.ts +28 -44
  314. package/dist/workers/docs-core.js +25 -44
  315. package/dist/workers/docs-index.js +4 -3
  316. package/dist/workers/docs-lookup.d.ts +15 -22
  317. package/dist/workers/docs-lookup.js +12 -21
  318. package/dist/workers/docs-project.d.ts +15 -9
  319. package/dist/workers/docs-project.js +17 -10
  320. package/dist/workers/docs-resolve.d.ts +19 -20
  321. package/dist/workers/docs-resolve.js +35 -32
  322. package/dist/workers/docs-retrieve.d.ts +5 -6
  323. package/dist/workers/docs-retrieve.js +18 -15
  324. package/dist/workers/exa-search.d.ts +9 -6
  325. package/dist/workers/exa-search.js +23 -12
  326. package/dist/workers/fetch-core.d.ts +13 -16
  327. package/dist/workers/fetch-core.js +23 -23
  328. package/dist/workers/focused-extractor.d.ts +12 -12
  329. package/dist/workers/focused-extractor.js +16 -19
  330. package/dist/workers/html-clean.js +24 -14
  331. package/dist/workers/http-request.d.ts +28 -20
  332. package/dist/workers/http-request.js +22 -17
  333. package/dist/workers/npm-version.d.ts +28 -11
  334. package/dist/workers/npm-version.js +24 -15
  335. package/dist/workers/phantom-imports.d.ts +15 -12
  336. package/dist/workers/phantom-imports.js +30 -24
  337. package/dist/workers/pi-worker-core.d.ts +69 -71
  338. package/dist/workers/pi-worker-core.js +100 -109
  339. package/dist/workers/pi-worker-docs.d.ts +24 -19
  340. package/dist/workers/pi-worker-docs.js +67 -76
  341. package/dist/workers/pi-worker-fetch.d.ts +7 -3
  342. package/dist/workers/pi-worker-fetch.js +27 -19
  343. package/dist/workers/pi-worker-search.js +12 -8
  344. package/dist/workers/pi-worker.d.ts +9 -4
  345. package/dist/workers/pi-worker.js +21 -14
  346. package/dist/workers/reasoning-warning.d.ts +18 -17
  347. package/dist/workers/reasoning-warning.js +22 -20
  348. package/dist/workers/research-cache.js +50 -78
  349. package/dist/workers/search-core.js +7 -5
  350. package/dist/workers/search-types.d.ts +10 -9
  351. package/dist/workers/search-types.js +9 -8
  352. package/dist/workers/session-hint.d.ts +13 -14
  353. package/dist/workers/session-hint.js +8 -9
  354. package/dist/workers/shared.d.ts +21 -25
  355. package/dist/workers/shared.js +0 -0
  356. package/dist/workers/single-read-extension.d.ts +14 -7
  357. package/dist/workers/single-read-extension.js +14 -7
  358. package/dist/workers/single-read-guard.d.ts +25 -28
  359. package/dist/workers/single-read-guard.js +32 -32
  360. package/dist/workers/typeonly-log.d.ts +12 -9
  361. package/dist/workers/typeonly-log.js +29 -33
  362. package/dist/workers/worker-channels.d.ts +15 -23
  363. package/dist/workers/worker-channels.js +15 -23
  364. package/dist/workers/worker-failure.d.ts +38 -46
  365. package/dist/workers/worker-failure.js +31 -39
  366. package/dist/workers/worker-kill.d.ts +25 -26
  367. package/dist/workers/worker-kill.js +16 -19
  368. package/dist/workers/worker-profiles.d.ts +43 -53
  369. package/dist/workers/worker-profiles.js +30 -38
  370. package/package.json +10 -8
@@ -4,10 +4,10 @@
4
4
  * The grill phase generates one clarifying question per KNOWN-UNKNOWN and lets a
5
5
  * `grill-auto` child either auto-answer it (ANSWER → the user never sees it) or
6
6
  * surface it (UNKNOWN → asked). The dangerous class is an integration / build-
7
- * wiring unknown — "how is this plugin wired into the build", "should the import
8
- * structure in the HTML entry change" — which `grill-auto` happily auto-answers
9
- * with a GUESS that then ships as a silent landmine (a real run shipped an
10
- * unstyled build this way).
7
+ * wiring unknown — "how is this plugin wired into the build", "where does the
8
+ * loader hook in" — which `grill-auto` will happily auto-answer with a GUESS. A
9
+ * wrong guess there is structural: the build still runs, and ships something the
10
+ * wiring never actually connected.
11
11
  *
12
12
  * This classifier identifies that class so the orchestrator can route it: try to
13
13
  * resolve it from fetched docs first, and if nothing grounded the answer, surface
@@ -24,5 +24,11 @@
24
24
  * surfaced to the user rather than auto-answered. Requires BOTH a tooling-surface
25
25
  * mention and wiring intent, so benign questions ("which log format?", "what
26
26
  * default page size?", "which file holds the auth handler?") do not trip it.
27
+ *
28
+ * Both factors are lexical, so the boundary is not exact in either direction. A
29
+ * bare `how is/are` counts as wiring intent, so "how is the plugin named?" trips
30
+ * it; and a wiring question phrased without one of the intent words — "should the
31
+ * import structure in the HTML entry change" — does not. Erring toward surfacing
32
+ * is the safe direction: the cost is one question the user waves through.
27
33
  */
28
34
  export declare function isIntegrationUnknown(question: string): boolean;
@@ -4,10 +4,10 @@
4
4
  * The grill phase generates one clarifying question per KNOWN-UNKNOWN and lets a
5
5
  * `grill-auto` child either auto-answer it (ANSWER → the user never sees it) or
6
6
  * surface it (UNKNOWN → asked). The dangerous class is an integration / build-
7
- * wiring unknown — "how is this plugin wired into the build", "should the import
8
- * structure in the HTML entry change" — which `grill-auto` happily auto-answers
9
- * with a GUESS that then ships as a silent landmine (a real run shipped an
10
- * unstyled build this way).
7
+ * wiring unknown — "how is this plugin wired into the build", "where does the
8
+ * loader hook in" — which `grill-auto` will happily auto-answer with a GUESS. A
9
+ * wrong guess there is structural: the build still runs, and ships something the
10
+ * wiring never actually connected.
11
11
  *
12
12
  * This classifier identifies that class so the orchestrator can route it: try to
13
13
  * resolve it from fetched docs first, and if nothing grounded the answer, surface
@@ -30,6 +30,12 @@ const WIRING_INTENT_RE = /\b(?:wir(?:e|ed|ing)|integrat(?:e|ed|es|ing|ion)|hook(
30
30
  * surfaced to the user rather than auto-answered. Requires BOTH a tooling-surface
31
31
  * mention and wiring intent, so benign questions ("which log format?", "what
32
32
  * default page size?", "which file holds the auth handler?") do not trip it.
33
+ *
34
+ * Both factors are lexical, so the boundary is not exact in either direction. A
35
+ * bare `how is/are` counts as wiring intent, so "how is the plugin named?" trips
36
+ * it; and a wiring question phrased without one of the intent words — "should the
37
+ * import structure in the HTML entry change" — does not. Erring toward surfacing
38
+ * is the safe direction: the cost is one question the user waves through.
33
39
  */
34
40
  export function isIntegrationUnknown(question) {
35
41
  if (!question)
@@ -3,14 +3,11 @@
3
3
  * directives a user writes into a raw task prompt, so a downstream rewrite (refine)
4
4
  * cannot silently drop them.
5
5
  *
6
- * The failure this closes (mx5 run 9, validated): the raw prompt was
7
- * "Research Playwright best practices VIA WEB SEARCH focus on E2E testing…"
8
- * Refine rewrote the task well in every other respect (it correctly killed a wrong
9
- * "Next.js" framing) but the "via web search" instruction vanished from the refined
10
- * spec entirely and the whole 2-run session then made ZERO pi-worker-search and
11
- * ZERO pi-worker-fetch calls. A user who explicitly asks for web search must get
12
- * web search; the model's paraphrase is not allowed to quietly demote it to
13
- * "research from local files".
6
+ * The failure this closes: a raw prompt saying "research X VIA WEB SEARCH" can be
7
+ * rewritten well in every other respect while the "via web search" instruction
8
+ * vanishes from the refined spec. Nothing downstream then asks for web search, so
9
+ * none happens. A user who explicitly names a tool must get that tool; a
10
+ * paraphrase is not allowed to quietly demote it to "research from local files".
14
11
  *
15
12
  * The mechanism is the lever, the prompt is the belt: refine is HANDED the
16
13
  * directives as a MUST-PRESERVE block (prompt), and — because a weak model still
@@ -3,14 +3,11 @@
3
3
  * directives a user writes into a raw task prompt, so a downstream rewrite (refine)
4
4
  * cannot silently drop them.
5
5
  *
6
- * The failure this closes (mx5 run 9, validated): the raw prompt was
7
- * "Research Playwright best practices VIA WEB SEARCH focus on E2E testing…"
8
- * Refine rewrote the task well in every other respect (it correctly killed a wrong
9
- * "Next.js" framing) but the "via web search" instruction vanished from the refined
10
- * spec entirely and the whole 2-run session then made ZERO pi-worker-search and
11
- * ZERO pi-worker-fetch calls. A user who explicitly asks for web search must get
12
- * web search; the model's paraphrase is not allowed to quietly demote it to
13
- * "research from local files".
6
+ * The failure this closes: a raw prompt saying "research X VIA WEB SEARCH" can be
7
+ * rewritten well in every other respect while the "via web search" instruction
8
+ * vanishes from the refined spec. Nothing downstream then asks for web search, so
9
+ * none happens. A user who explicitly names a tool must get that tool; a
10
+ * paraphrase is not allowed to quietly demote it to "research from local files".
14
11
  *
15
12
  * The mechanism is the lever, the prompt is the belt: refine is HANDED the
16
13
  * directives as a MUST-PRESERVE block (prompt), and — because a weak model still
@@ -5,45 +5,41 @@ export interface GrepOnlyVerifyFinding {
5
5
  lines: string[];
6
6
  }
7
7
  /**
8
- * Scan a composed spec's VERIFY block: all-static block that grep/cat-asserts
9
- * runnable source one finding per inspected file. Empty when the block
10
- * contains any execution command, has no VERIFY block, or inspects no runnable
11
- * source (doc/config-only tasks).
8
+ * Scan a composed spec's VERIFY block: one finding per runnable source file the
9
+ * block inspects, each carrying the verbatim lines that inspect it. Empty when
10
+ * the block contains any execution command, when the spec has no fenced VERIFY
11
+ * block, or when nothing runnable is inspected (doc/config-only tasks).
12
12
  */
13
13
  export declare function findGrepOnlyVerify(spec: string): GrepOnlyVerifyFinding[];
14
14
  /** One VERIFY command, classified by what it can observe. */
15
15
  export interface VerifyCommandClass {
16
16
  /** The command line, verbatim. */
17
17
  raw: string;
18
- /** Every pipeline segment is a STATIC head (grep/test/tsc/…) — it inspects
19
- * files and can never observe the deliverable's behaviour. */
18
+ /** Every pipeline segment's head is in STATIC_HEADS (grep/test/tsc/…) — it
19
+ * inspects files and can never observe the deliverable's behaviour. */
20
20
  staticOnly: boolean;
21
21
  /**
22
- * The command observes RUNTIME behaviour: an HTTP request, a port probe, a
23
- * process it starts and watches. This is the distinction nexttask 7's M3
24
- * turns on mx5 run 18's TASK_0023 VERIFY is all `node -e "…package.json…"`,
25
- * which EXECUTES node yet can only assert that a string is present in a
26
- * config file, and the behavioural half of the owned requirement ("serves
27
- * `/api` + static `dist/`") is exactly what it cannot see.
22
+ * The command names an HTTP request (`curl`, `wget`, an http(s) URL,
23
+ * `fetch(`), a port probe (`nc -z`, `ss -`, `lsof`, `localhost`,
24
+ * `127.0.0.1`) or `playwright`. Executing something is not enough:
25
+ * `bun run start` and `node -e "…package.json…"` are both false here they
26
+ * run, yet observe only a file's contents.
28
27
  */
29
28
  observesBehaviour: boolean;
30
29
  }
31
30
  /**
32
31
  * Classify each command of a spec's VERIFY block. Shares `segmentHead` with the
33
32
  * grep-theater detector, so "static" means one thing across the two measures.
34
- * Empty when the spec has no runnable VERIFY block.
33
+ * Empty when the spec has no fenced VERIFY block.
35
34
  */
36
35
  export declare function classifyVerifyCommands(spec: string): VerifyCommandClass[];
37
36
  /**
38
- * Retry hint when the critique rewrite KEPT the grep-theater block it was told
39
- * to fix (live A/B: 1/5 rewrites ignored the injected defect). Prepended to the
40
- * second rewrite attempt; the defect block naming the exact files is still in
41
- * the prompt body.
37
+ * Prepended to the SECOND `runWithEmphasisRetry` attempt when the first critique
38
+ * rewrite still leaves `findGrepOnlyVerify` non-empty. The generic emphasis line
39
+ * would claim the previous attempt had no VERIFY block, which is wrong here it
40
+ * had one. The defect block naming the exact files stays in the prompt body
41
+ * underneath the hint.
42
42
  */
43
43
  export declare const GREP_THEATER_RETRY_HINT: string;
44
- /**
45
- * Render the findings as a defect block for the critique rewrite: VERIFY must
46
- * EXECUTE the runnable deliverable and assert an observable outcome of THAT
47
- * run, not grep its source.
48
- */
44
+ /** Render the findings as the defect block handed to the critique rewrite. */
49
45
  export declare function grepOnlyVerifyDefectText(findings: GrepOnlyVerifyFinding[]): string;
@@ -1,24 +1,17 @@
1
1
  /**
2
- * Grep-theater VERIFY detector (mx5 run-13 Bug B), compose-critique side.
2
+ * Grep-theater VERIFY detector, wired as the `grep-theater` compose-critique
3
+ * probe in `critique-probes.ts`.
3
4
  *
4
- * TASK_0018's VERIFY block "verified" a build script with tsc + three greps on
5
- * build.ts's SOURCE it never ran `bun build.ts`. The greps asserted the
6
- * hallucinated `Bun.mkdirSync` line was present, so a broken build shipped
7
- * green and stayed broken for 14 tasks. Grep-on-source is not verification of
8
- * a runnable deliverable; only executing the artifact is.
9
- *
10
- * Deterministic shape (findSkipEscapes critique-rewrite pattern): a finding
11
- * fires when the VERIFY block (a) grep/cat-asserts the SOURCE of a runnable
12
- * file (.ts/.js/.sh — a build script, server, CLI entry) and (b) contains NO
13
- * execution command at all — every command is static inspection (grep, test,
14
- * ls, cat, tsc --noEmit, eslint, prettier). Any real execution anywhere in the
15
- * block (bun/node/npm run/test, curl, ./script) means the deliverable-runs
16
- * question is at worst partially covered, and we step aside — the guard may
17
- * only cost time, never work, so recall is floored at the unambiguous
18
- * all-static case rather than chasing which command exercises which file.
5
+ * A finding fires when the spec's VERIFY block (a) inspects the source of a
6
+ * TypeScript/JavaScript/shell file with grep/rg/cat/head/tail/wc and (b)
7
+ * contains no execution command at all every pipeline segment's head is in
8
+ * STATIC_HEADS. One unknown head anywhere in the block (bun, node, npm, yarn,
9
+ * pnpm, curl, `./script`, python3) counts as execution and the whole block is
10
+ * skipped. Recall is therefore floored at the unambiguous all-static case
11
+ * instead of deciding which command exercises which file.
19
12
  */
20
13
  import { parseVerifyBlock } from './spec-validation.js';
21
- /** Commands that only inspect — they never execute the shipped artifact. */
14
+ /** Commands that only inspect — a segment headed by one never runs the deliverable. */
22
15
  const STATIC_HEADS = new Set([
23
16
  'grep',
24
17
  'rg',
@@ -57,25 +50,33 @@ const STATIC_HEADS = new Set([
57
50
  'prettier',
58
51
  'biome'
59
52
  ]);
60
- /** A bare (unquoted) path token ending in a runnable-source extension. */
53
+ /**
54
+ * A bare path token ending in a runnable-source extension: ts, tsx, js, jsx,
55
+ * mjs, cjs, mts, cts, sh. The character class holds no quote, so a quoted
56
+ * `'build.ts'` never matches.
57
+ */
61
58
  const RUNNABLE_SRC_RE = /^[\w@./-]+\.(?:ts|tsx|js|jsx|mjs|cjs|mts|cts|sh)$/;
62
- /** Heads whose file arguments count as "inspecting the source of". */
59
+ /**
60
+ * Heads whose file arguments count as "inspecting the source of". The other
61
+ * STATIC_HEADS (sed, awk, jq, ls, diff, file …) keep a block static but name
62
+ * no target of their own.
63
+ */
63
64
  const INSPECT_HEADS = new Set(['grep', 'rg', 'cat', 'head', 'tail', 'wc']);
64
65
  /**
65
- * Shell-control noise that precedes (or IS) a segment without being a command:
66
- * `if grep -q x f; then` splits into an `if`-prefixed segment plus bare `then`;
67
- * `… || { echo FAIL; exit 1; }` yields `{ echo …` and `}` segments. Treating
68
- * these as unknown heads would count them as execution and silently blind the
69
- * detector on exactly the incident shape (run-13's VERIFY used all of them).
66
+ * Shell-control noise that precedes (or IS) a segment without being a command.
67
+ * `if grep -q x f; then` splits into `if grep -q x f` plus a bare ` then`;
68
+ * `… || { echo FAIL; exit 1; }` yields ` { echo FAIL`, ` exit 1` and ` }`.
69
+ * An unknown head counts as execution and skips the whole block, so treating
70
+ * these tokens as heads would blind the detector on any guarded grep.
70
71
  */
71
72
  const CONTROL_PREFIX = new Set(['if', 'elif', 'while', 'until', 'then', 'else', 'do', '!']);
72
73
  const CONTROL_ONLY = new Set(['}', ')', 'fi', 'done', 'esac']);
73
74
  /**
74
- * The effective head of one pipeline segment: shell-control prefixes, leading
75
- * `(`/`{`, VAR=val prefixes and `timeout N` are skipped; `bunx`/`npx` resolve
76
- * to the tool they invoke (so `bunx tsc --noEmit` is static).
77
- * `bun`/`npm`/`yarn`/`pnpm`/`node` stay as themselves whatever they run (a
78
- * script, a test suite, a file) is execution.
75
+ * The effective head of one pipeline segment: leading `(`/`{`/`!`,
76
+ * shell-control prefixes, VAR=val assignments and `timeout N` are skipped;
77
+ * `bunx`/`npx` resolve to the tool they invoke, so `bunx tsc --noEmit` stays
78
+ * static. `bun`/`npm`/`yarn`/`pnpm`/`node` stay as themselves and are absent
79
+ * from STATIC_HEADS, so whatever they run is execution.
79
80
  */
80
81
  function segmentHead(segment) {
81
82
  const tokens = segment.split(/\s+/).filter(t => t.length > 0);
@@ -112,10 +113,10 @@ function segmentHead(segment) {
112
113
  return { head, args: tokens.slice(i + 1) };
113
114
  }
114
115
  /**
115
- * Scan a composed spec's VERIFY block: all-static block that grep/cat-asserts
116
- * runnable source one finding per inspected file. Empty when the block
117
- * contains any execution command, has no VERIFY block, or inspects no runnable
118
- * source (doc/config-only tasks).
116
+ * Scan a composed spec's VERIFY block: one finding per runnable source file the
117
+ * block inspects, each carrying the verbatim lines that inspect it. Empty when
118
+ * the block contains any execution command, when the spec has no fenced VERIFY
119
+ * block, or when nothing runnable is inspected (doc/config-only tasks).
119
120
  */
120
121
  export function findGrepOnlyVerify(spec) {
121
122
  const cmds = parseVerifyBlock(spec);
@@ -123,9 +124,10 @@ export function findGrepOnlyVerify(spec) {
123
124
  return [];
124
125
  const inspected = new Map();
125
126
  for (const { raw } of cmds) {
126
- // Split into pipeline segments; quotes are rare in VERIFY one-liners and
127
- // a mis-split only risks a MISSED finding (a quoted `&&` making a fake
128
- // segment whose head is unknown counted as execution step aside).
127
+ // Split into pipeline segments. A mis-split a quoted `&&` making a
128
+ // fake segment leaves a segment whose head is unknown, which counts
129
+ // as execution and skips the block. The error direction is a MISSED
130
+ // finding, never a false one.
129
131
  for (const segment of raw.split(/&&|\|\||;|\|/)) {
130
132
  const s = segmentHead(segment);
131
133
  if (s === null)
@@ -152,7 +154,7 @@ const BEHAVIOUR_RE = /\bcurl\b|\bwget\b|\bhttpie?\b|https?:\/\/|\bnc\s+-z\b|\bss
152
154
  /**
153
155
  * Classify each command of a spec's VERIFY block. Shares `segmentHead` with the
154
156
  * grep-theater detector, so "static" means one thing across the two measures.
155
- * Empty when the spec has no runnable VERIFY block.
157
+ * Empty when the spec has no fenced VERIFY block.
156
158
  */
157
159
  export function classifyVerifyCommands(spec) {
158
160
  const cmds = parseVerifyBlock(spec);
@@ -171,10 +173,11 @@ export function classifyVerifyCommands(spec) {
171
173
  });
172
174
  }
173
175
  /**
174
- * Retry hint when the critique rewrite KEPT the grep-theater block it was told
175
- * to fix (live A/B: 1/5 rewrites ignored the injected defect). Prepended to the
176
- * second rewrite attempt; the defect block naming the exact files is still in
177
- * the prompt body.
176
+ * Prepended to the SECOND `runWithEmphasisRetry` attempt when the first critique
177
+ * rewrite still leaves `findGrepOnlyVerify` non-empty. The generic emphasis line
178
+ * would claim the previous attempt had no VERIFY block, which is wrong here it
179
+ * had one. The defect block naming the exact files stays in the prompt body
180
+ * underneath the hint.
178
181
  */
179
182
  export const GREP_THEATER_RETRY_HINT = '[SYSTEM NOTE: Your previous rewrite still shipped a VERIFY block whose only signal '
180
183
  + 'on the runnable deliverable is grep-on-source — every command is static inspection '
@@ -183,11 +186,7 @@ export const GREP_THEATER_RETRY_HINT = '[SYSTEM NOTE: Your previous rewrite stil
183
186
  + 'deliverable (e.g. `bun <script>.ts`, `bun run <script>`, start it and curl it) and '
184
187
  + 'assert an observable outcome of that run (exit code, a file the run produces, a '
185
188
  + 'served response). Keep greps only as additions to the run, never as the only signal.]';
186
- /**
187
- * Render the findings as a defect block for the critique rewrite: VERIFY must
188
- * EXECUTE the runnable deliverable and assert an observable outcome of THAT
189
- * run, not grep its source.
190
- */
189
+ /** Render the findings as the defect block handed to the critique rewrite. */
191
190
  export function grepOnlyVerifyDefectText(findings) {
192
191
  return [
193
192
  'GREP-THEATER VERIFY — every command in the VERIFY block is static inspection',
@@ -1,14 +1,17 @@
1
1
  export interface AbsenceAssertion {
2
- /** The verify line carrying the assertion (trimmed). */
2
+ /** The trimmed fragment the assertion was read out of: the whole VERIFY
3
+ * line, or only the condition when it came from an `if` header. */
3
4
  line: string;
4
5
  /** The path or grep pattern asserted absent (quotes stripped). */
5
6
  target: string;
6
7
  kind: 'path' | 'pattern';
7
8
  }
8
9
  /**
9
- * All absence assertions in the spec's VERIFY block. Scans the fenced commands:
10
- * `if` blocks whose body reaches `exit <nonzero>` contribute their condition's
11
- * POSITIVE probes; other lines contribute their NEGATED probes.
10
+ * All absence assertions in the spec's VERIFY block. An `if` line contributes
11
+ * its condition's POSITIVE probes only when a LATER line reaches
12
+ * `exit <nonzero>`: the body scan starts at the next command, so a one-line
13
+ * `if …; then exit 1; fi` yields nothing. Every other line contributes its
14
+ * NEGATED probes. Empty when the spec has no fenced VERIFY block.
12
15
  */
13
16
  export declare function findAbsenceAssertions(spec: string): AbsenceAssertion[];
14
17
  export interface AbsenceConflict {
@@ -25,12 +28,14 @@ export interface AbsenceConflictContext {
25
28
  /** The cross-slice contract registry text ('' when absent). */
26
29
  contracts: string;
27
30
  }
28
- /** Absence assertions that collide with the plan: the deterministic D lever. */
31
+ /** Every absence assertion that collides with the plan. disk, sibling and
32
+ * contract are tested independently, so one assertion can yield three. */
29
33
  export declare function findAbsenceConflicts(spec: string, ctx: AbsenceConflictContext): AbsenceConflict[];
30
- /** The forced critique-rewrite defect text (skip-escape pattern: MANDATORY,
31
- * self-contained, names the reconciliation). */
34
+ /** The defect block handed to the critique rewrite. Self-contained: it names
35
+ * each conflict, why it is one, and the reconciliation to apply. */
32
36
  export declare function absenceProbeText(conflicts: AbsenceConflict[]): string;
33
- /** Parse SIBLING titles out of the scope-fence text (buildScopeFence's listing),
34
- * excluding the "(THIS STEP)" line a task may legitimately assert about its
35
- * own deliverables. '' / undefined (bare /task, no plan) yields none. */
37
+ /** Parse SIBLING titles out of `buildScopeFence`'s listing, whose rows read
38
+ * `[N] head` and `[N] (THIS STEP) head`. The "(THIS STEP)" row is dropped a
39
+ * task may legitimately assert about its own deliverables. '' and undefined
40
+ * (a bare /task with no plan) yield none. */
36
41
  export declare function siblingTitlesFromPlanContext(planContext: string | undefined): string[];
@@ -1,47 +1,43 @@
1
1
  /**
2
2
  * verify-reconcile — deterministic reconciliation of a spec's VERIFY assertions
3
- * against the PLAN (mx5 run 11, goal D).
3
+ * against the plan. Wired as the `plan-contradiction` critique probe.
4
4
  *
5
- * The failure this closes: TASK_0009's composed spec carried
6
- * `if [ -f src/client/pages/admin.tsx ] || grep -rn 'Admin' src/client/pages/ …; then exit 1`
7
- * a NEGATIVE EXISTENCE assertion on a SIBLING task's pinned deliverable
8
- * (TASK_0008 shipped the admin page; the design pins the admin routes). The
9
- * scope fence ("do NOT build other steps' work") leaked into the verify script
10
- * as "other steps' work must be ABSENT". Verify then correctly FAILed at run
11
- * end, the user accepted it as debt, and the final-gate autofix treated the
12
- * debt as an instruction and `rm`'d the sibling's deliverable.
5
+ * A sibling step's deliverable is a fact about the tree this task runs in, never
6
+ * a valid absence target. A VERIFY line asserting it is missing is a guaranteed
7
+ * run-end FAIL, and an automated fixer handed that FAIL can "resolve" it by
8
+ * deleting the sibling's work. The defect has to die at spec time instead.
13
9
  *
14
- * A sibling's deliverable is a CLAIM about the tree this task runs in — never a
15
- * valid absence target. The defect must die at SPEC time (a forced critique
16
- * rewrite, the skip-escape pattern), not surface as a run-end verify-FAIL.
10
+ * Two shapes read as "this must be absent":
11
+ * - an `if` whose condition holds a POSITIVE existence probe (`[ -f P ]`,
12
+ * `test -e P`, `grep PAT …`) and whose body reaches `exit <nonzero>`;
13
+ * - a NEGATED probe anywhere else (`[ ! -f P ]`, `test ! -f P`,
14
+ * `! grep PAT …`), `|| exit`-guarded or standing alone.
15
+ * `grep -v` / `--invert-match` is a filter, not a probe, and is skipped; so is
16
+ * a target starting with `-` or `$`.
17
17
  *
18
- * Detection is deterministic and shape-aware for how these specs actually write
19
- * absence checks (measured on the real run-11 artifacts):
20
- * - `if <cond>; then … exit 1; fi` where <cond> contains a POSITIVE existence
21
- * probe (`[ -f P ]`, `test -e P`, `grep PAT …`): P/PAT must be absent or the
22
- * verify fails.
23
- * - a standalone / `|| exit`-guarded NEGATED probe (`[ ! -f P ]`,
24
- * `test ! -f P`, `! grep PAT …`): same meaning outside an if-header.
25
- * `grep -v` occurrences are filters, not probes, and are skipped.
26
- *
27
- * A detected absence target is a CONFLICT when the plan pins it elsewhere:
28
- * - 'disk' — the path already exists in the worktree at spec time (a
29
- * sibling shipped it; asserting its absence is a guaranteed
30
- * future FAIL);
18
+ * A detected target is a CONFLICT when the plan pins it elsewhere:
19
+ * - 'disk' — the path exists in the worktree at spec time;
31
20
  * - 'sibling' — a SIBLING task's title names it;
32
21
  * - 'contract' — the cross-slice contract registry quotes it.
33
- * Matching: pattern targets by case-insensitive substring (all-words matching
34
- * false-fires on `bun:sql` vs a "Bun SQL connection" title); path targets by
35
- * full-path substring or a word-bounded basename. No similarity thresholds.
22
+ * The three are checked independently, so one assertion can raise all three.
23
+ *
24
+ * Matching: pattern targets by case-insensitive substring; path targets by
25
+ * full-path substring or a word-bounded basename. No similarity thresholds and
26
+ * no all-words matching — all-words matches `bun:sql` against a "Bun SQL
27
+ * connection" title, where substring does not.
36
28
  *
37
- * The finding is a PROBE, not a gate: it forces the critique rewrite and names
38
- * the reconciliation (delete-tasks legitimately assert absence the rewrite
39
- * keeps the check when the GOAL explicitly deletes the artifact).
29
+ * The finding is a PROBE, not a gate: it only forces the critique rewrite, and
30
+ * `absenceProbeText` tells that rewrite to KEEP an absence check when the GOAL
31
+ * explicitly deletes the artifact.
40
32
  */
41
33
  import { parseVerifyBlock } from './spec-validation.js';
42
34
  /** A quoted or bare shell word. */
43
35
  const SHELL_WORD = `"[^"]+"|'[^']+'|[^\\s\\]&|;)]+`;
44
- /** Positive existence probes: `-f P` / `-e P` / `-d P` not preceded by `!`. */
36
+ /**
37
+ * A `-f`/`-e`/`-d` existence probe, with or without a leading `test`. The three
38
+ * `(!?)` groups cover every place a negation can sit — before the `[`, inside
39
+ * it, and before the flag — so the caller can tell `[ ! -f P ]` from `[ -f P ]`.
40
+ */
45
41
  const EXIST_RE = new RegExp(`(!?)\\s*(?:\\[\\[?\\s*)?(!?)\\s*(?:test\\s+)?(!?)\\s*-[efd]\\s+(${SHELL_WORD})`, 'g');
46
42
  /** grep probes: optional leading `!`, flags, then the first pattern argument. */
47
43
  const GREP_RE = new RegExp(`(!\\s+)?\\bgrep\\s+((?:-{1,2}[\\w=,.-]+\\s+)*)(${SHELL_WORD})`, 'g');
@@ -80,9 +76,11 @@ function assertionsInFragment(fragment, positiveMeansAbsent) {
80
76
  return out;
81
77
  }
82
78
  /**
83
- * All absence assertions in the spec's VERIFY block. Scans the fenced commands:
84
- * `if` blocks whose body reaches `exit <nonzero>` contribute their condition's
85
- * POSITIVE probes; other lines contribute their NEGATED probes.
79
+ * All absence assertions in the spec's VERIFY block. An `if` line contributes
80
+ * its condition's POSITIVE probes only when a LATER line reaches
81
+ * `exit <nonzero>`: the body scan starts at the next command, so a one-line
82
+ * `if …; then exit 1; fi` yields nothing. Every other line contributes its
83
+ * NEGATED probes. Empty when the spec has no fenced VERIFY block.
86
84
  */
87
85
  export function findAbsenceAssertions(spec) {
88
86
  const cmds = parseVerifyBlock(spec);
@@ -93,8 +91,10 @@ export function findAbsenceAssertions(spec) {
93
91
  for (let i = 0; i < lines.length; i++) {
94
92
  const ifm = /^if\s+(.+?)(?:;\s*then\b.*)?$/.exec(lines[i]);
95
93
  if (ifm) {
96
- // Collect the block body up to the matching fi (flat scan — generated
97
- // VERIFY blocks don't nest ifs; a nested one just extends the body).
94
+ // Collect the block body up to the matching `fi`, counting nested
95
+ // `if`s. A nested if is never scanned as a condition of its own
96
+ // its lines just extend the outer body, so an `exit 1` inside it
97
+ // arms the OUTER condition.
98
98
  let depth = 1;
99
99
  let body = '';
100
100
  let j = i + 1;
@@ -138,7 +138,8 @@ function namesTarget(haystack, a) {
138
138
  return false;
139
139
  return new RegExp(`\\b${escapeRe(base)}\\b`, 'i').test(haystack);
140
140
  }
141
- /** Absence assertions that collide with the plan: the deterministic D lever. */
141
+ /** Every absence assertion that collides with the plan. disk, sibling and
142
+ * contract are tested independently, so one assertion can yield three. */
142
143
  export function findAbsenceConflicts(spec, ctx) {
143
144
  const out = [];
144
145
  for (const a of findAbsenceAssertions(spec)) {
@@ -160,8 +161,8 @@ export function findAbsenceConflicts(spec, ctx) {
160
161
  }
161
162
  return out;
162
163
  }
163
- /** The forced critique-rewrite defect text (skip-escape pattern: MANDATORY,
164
- * self-contained, names the reconciliation). */
164
+ /** The defect block handed to the critique rewrite. Self-contained: it names
165
+ * each conflict, why it is one, and the reconciliation to apply. */
165
166
  export function absenceProbeText(conflicts) {
166
167
  const what = {
167
168
  disk: 'ALREADY EXISTS in the worktree (a prior task shipped it)',
@@ -182,9 +183,10 @@ export function absenceProbeText(conflicts) {
182
183
  "exact artifact — then say so in the check's comment."
183
184
  ].join('\n');
184
185
  }
185
- /** Parse SIBLING titles out of the scope-fence text (buildScopeFence's listing),
186
- * excluding the "(THIS STEP)" line a task may legitimately assert about its
187
- * own deliverables. '' / undefined (bare /task, no plan) yields none. */
186
+ /** Parse SIBLING titles out of `buildScopeFence`'s listing, whose rows read
187
+ * `[N] head` and `[N] (THIS STEP) head`. The "(THIS STEP)" row is dropped a
188
+ * task may legitimately assert about its own deliverables. '' and undefined
189
+ * (a bare /task with no plan) yield none. */
188
190
  export function siblingTitlesFromPlanContext(planContext) {
189
191
  if (!planContext)
190
192
  return [];
@@ -1,4 +1,5 @@
1
- /** Same read-only contract as the verify pass: observe, never edit. */
1
+ /** The observe-only contract handed to the child. The same string as
2
+ * verify-work's VERIFY_TOOLS, so both passes are told the same thing. */
2
3
  declare const RESOLUTION_TOOLS = "read,bash";
3
4
  /** Which card the picker tints RECOMMENDED. */
4
5
  export type ResolutionRecommendation = 'autofix' | 'accept';
@@ -11,18 +12,19 @@ export interface ResolutionOutcome {
11
12
  }
12
13
  /**
13
14
  * Build the resolution research child's prompt. Pure, so the wording is
14
- * unit-tested without spawning pi. The contract: investigate the real workspace
15
- * and end on exactly one RESOLUTION verdict line.
15
+ * unit-tested without spawning pi. The contract it states: investigate the real
16
+ * workspace and end on exactly one `VERIFY-RESOLUTION:` line.
16
17
  */
17
18
  export declare function buildResolutionPrompt(spec: string, failReason: string): string;
18
19
  /**
19
- * Parse the child's recommendation. Scans for the LAST
20
- * `VERIFY-RESOLUTION: AUTOFIX|ACCEPT` marker (the model reasons before
21
- * concluding, and bash output may echo these words, so a distinct token and
22
- * last-match-wins both matter).
20
+ * Parse the child's recommendation out of the LAST
21
+ * `VERIFY-RESOLUTION: AUTOFIX|ACCEPT` marker, case-insensitively. Last match
22
+ * wins: the model reasons before concluding, and a bash command it runs can
23
+ * print the token back, so an earlier occurrence is not the verdict.
23
24
  *
24
- * No marker → recommend AUTOFIX (conservative: re-do rather than bless), with a
25
- * rationale that says the research was inconclusive.
25
+ * No marker → AUTOFIX (re-do rather than bless), with a rationale saying the
26
+ * research was inconclusive. A marker with no trailing sentence gets a stock
27
+ * rationale, so `rationale` is never empty.
26
28
  */
27
29
  export declare function parseResolutionVerdict(text: string): ResolutionOutcome;
28
30
  export declare const ACCEPT_VALUE = "accept";
@@ -37,10 +39,10 @@ export interface ResolutionChoice {
37
39
  guidance?: string;
38
40
  }
39
41
  /**
40
- * The two cards for the picker, with the model-recommended one FIRST so the boxed
41
- * renderer tints it green (it marks index 0 as recommended). Values are the bare
42
- * tokens; remote buttons use the labels — {@link classifyResolutionAnswer}
43
- * accepts both.
42
+ * The two cards for the picker, model-recommended one FIRST because the boxed
43
+ * renderer marks index 0 as the recommended card (bridge.ts `askLocal` passes
44
+ * `recommended: i === 0`). Values are the bare tokens; remote buttons carry the
45
+ * labels — {@link classifyResolutionAnswer} accepts both.
44
46
  */
45
47
  export declare function resolutionOptions(recommend: ResolutionRecommendation): {
46
48
  label: string;
@@ -48,10 +50,11 @@ export declare function resolutionOptions(recommend: ResolutionRecommendation):
48
50
  recommended: boolean;
49
51
  }[];
50
52
  /**
51
- * Map a picker answer to an action. Handles the card value tokens, the remote
52
- * button labels, an empty/undefined dismissal (cancel), and arbitrary free text
53
- * typed via the fallback which becomes an AUTOFIX with that text as guidance
54
- * (the user is steering the re-run rather than blessing the artifact).
53
+ * Map a picker answer to an action. undefined or blank is a dismissal (cancel).
54
+ * A LEADING `accept`/`autofix` word matches, which covers both the bare card
55
+ * values and the remote button labels. Anything else becomes an AUTOFIX carrying
56
+ * that text as guidance including a sentence that mentions "accept" further
57
+ * along, since the user is steering the re-run, not blessing the artifact.
55
58
  */
56
59
  export declare function classifyResolutionAnswer(answer: string | undefined): ResolutionChoice;
57
60
  export interface ResolutionDeps {
@@ -67,9 +70,10 @@ export interface ResolutionDeps {
67
70
  }
68
71
  /**
69
72
  * Research a verify FAIL and return which action to recommend. Never throws
70
- * (except a user cancel, which propagates so the loop's USER_CANCELLED handler
71
- * reports a clean "cancelled — resume"). A child crash defaults to recommending
72
- * AUTOFIX the picker is still shown, only the default tint changes.
73
+ * except on a user cancel, which propagates so the loop's USER_CANCELLED handler
74
+ * reports a clean "cancelled — resume". A child crash returns AUTOFIX with a
75
+ * "could not run" rationale; since AUTOFIX is the unattended path, a crash here
76
+ * costs an implementation re-run rather than a prompt.
73
77
  */
74
78
  export declare function researchResolution(deps: ResolutionDeps): Promise<ResolutionOutcome>;
75
79
  export { RESOLUTION_TOOLS };