@mjasnikovs/pi-task 0.38.28 → 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 +25 -7
  104. package/dist/task/context-usage.js +21 -6
  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 +37 -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 +180 -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 +33 -36
  231. package/dist/task/research-worker.js +39 -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 +86 -54
  338. package/dist/workers/pi-worker-core.js +112 -112
  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 +23 -10
  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
@@ -1,71 +1,40 @@
1
1
  /**
2
- * Work verification for /task-auto.
2
+ * Work verification: the model half of the post-implementation gate.
3
3
  *
4
- * The root failure this addresses: pi-task never *runs* any verification. Each
5
- * task's composed spec carries a VERIFY block (and ACCEPTANCE criteria), but that
6
- * block is only authored and presence-checked never executed. The task is then
7
- * marked `completed` at handoff. So a task whose implementation does not actually
8
- * work (a SPA that won't build, a route wired to a dead stub, a CI file nobody
9
- * runs) is indistinguishable from one that does.
4
+ * A composed spec carries a VERIFY block and ACCEPTANCE criteria, but authoring
5
+ * that block and presence-checking it proves nothing. This pass RUNS it. It hands
6
+ * the just-committed spec (GOAL / CONSTRAINTS / ACCEPTANCE / VERIFY) to a fresh
7
+ * child with a `read` and a `bash` tool in the real workspace, and turns the
8
+ * child's verdict line into a PASS / FAIL / UNOBSERVED outcome.
10
9
  *
11
- * This pass closes that gap WITHOUT assuming any particular shape of project. It
12
- * does NOT hardcode `build`, an HTTP probe, a server boot, or a test command —
13
- * many tasks have none of those. Instead it hands the just-committed spec (GOAL /
14
- * ACCEPTANCE / VERIFY) to a fresh child of the SAME local model, gives it a `read`
15
- * and a `bash` tool in the real workspace, and lets the model do its job: run the
16
- * verification the spec already declares, observe the REAL output, and report a
17
- * PASS / FAIL verdict. If the spec's VERIFY is legitimately a no-op (config-only
18
- * change, re-read of a file), the model says so and that is a PASS.
10
+ * Nothing about a project's shape is hardcoded no `build`, no HTTP probe, no
11
+ * server boot, no test command. The spec names the checks; the child runs them.
12
+ * When a spec's VERIFY is legitimately a no-op (a docs or config change), saying
13
+ * so is a PASS (rule 6).
19
14
  *
20
- * It must verify the REAL deliverable AS SHIPPED, not a run the verifier itself
21
- * prepared into passing. The failure class is broader than a bad VERIFY block: the
22
- * child has `bash`, so it can quietly make almost anything go green export an env
23
- * var, source a config file, run a different command, rebuild in a scratch dir,
24
- * fabricate the artifact by hand — and then report PASS, masking a defect a fresh
25
- * checkout or CI run would hit. (This is exactly what sank an mx5 run: the verify
26
- * child `export`ed the test DB URL its own shell, watched the suite go green, and
27
- * passed a project whose documented command failed unaided.) The prompt therefore
28
- * anchors the child to ONE principle: run the project's own commands verbatim in the
29
- * tree as found, and treat any preparation/repair/substitution it had to perform to
30
- * reach green as ITSELF the defect — while still distinguishing a genuinely-absent
31
- * EXTERNAL service (an environment gap, not a code fault) from the project mis-wiring
32
- * how it connects. This generalises across languages and toolchains and assumes no
33
- * tests, build, or particular runtime.
15
+ * The prompt anchors the child to ONE principle: run the project's own commands
16
+ * verbatim in the tree as found, and treat any preparation, repair or
17
+ * substitution it had to perform to reach green as ITSELF the defect. A child
18
+ * holding `bash` can make almost anything go green export an env var, source a
19
+ * config file, rebuild in a scratch dir, fabricate the artifact by hand — and
20
+ * then report PASS on a defect a fresh checkout would hit. Rule 5 keeps the one
21
+ * genuine exception, an EXTERNAL service absent from this machine, and makes the
22
+ * child PROBE for that service first: reachable means the real verification must
23
+ * run against it.
34
24
  *
35
- * A/B-proven on the live local model (Qwen3.6-35B), 5 runs/arm on a work-around-to-pass
36
- * fixture (documented command fails unaided; greppable env file makes it pass): the old
37
- * prompt false-passed 2/5; the new prompt caught it 5/5, each time naming the unwired
38
- * config. Guards (3 runs/arm): a healthy project still PASSes 3/3 (no false-fail), a
39
- * genuinely-broken shipped build FAILs 3/3, and a genuine external-service gap — which
40
- * the OLD prompt wrongly blamed on the code 3/3 — now correctly PASSes 3/3.
25
+ * It runs as a GATE right after the implementation turn, before the task is
26
+ * checked off or committed, for both /task and /task-auto they build these
27
+ * children through the same gate-deps.ts. A FAIL does not end the run:
28
+ * task-gates.ts routes it through verify-resolution.ts into an unattended AUTOFIX
29
+ * re-run or the human picker.
41
30
  *
42
- * The sibling failure class is GREP-THEATER (mx5 run 2, TASK_0002): the composed VERIFY
43
- * block was grep-only, so the child "verified" a schema.sql containing INVALID SQL by
44
- * grepping for its own broken text while a live PostgreSQL sat reachable in the same
45
- * container, never touched. The prompt now (a) says a grep-only VERIFY block does not cap
46
- * the obligation to execute/apply an executable artifact, and (b) requires PROBING a
47
- * declared external service before invoking the absent-service exception — reachable ⇒
48
- * the real verification must run against it. A/B on the faithful fixture (invalid
49
- * `generate always as` schema, grep-only VERIFY, unadvertised trust-auth PostgreSQL on
50
- * the default port, DATABASE_URL unset — exactly the mx5 shape): old prompt false-PASSed
51
- * 4/5; new prompt FAILed 5/5, each naming the real syntax error. Guards: explicit-URL
52
- * variant old 5/5 / new 5/5 correct-FAIL (no regression), valid schema 3/3 PASS (no
53
- * paranoia), unreachable-DB 2/3 PASS via the env-gap exception + 1 conservative FAIL
54
- * that still named the genuine SQL defect (safe direction — only false-PASS trashes work).
31
+ * Tools: `read` + `bash`, no `edit`/`write`. Observing is the CONTRACT, not the
32
+ * capability `bash` writes — so gate-child.ts runs this kind `guarded` and
33
+ * `mutationCheck` below discards a verdict computed on a tree the child moved.
55
34
  *
56
- * It runs as a GATE right after the implementation turn, BEFORE the task is
57
- * checked off or committed. A FAIL stops the /task-auto run exactly like an
58
- * implementation failure: the task is left unchecked and uncommitted so
59
- * /task-auto-resume re-runs it, rather than blessing work that does not run.
60
- *
61
- * Tools: `read` + `bash` only. No `edit`/`write` — verification observes, it does
62
- * not fix (fixing committed work is the enforcement pass's job, and a verify pass
63
- * that also edits would blur "did it work" with "make it work"). `bash` is what
64
- * makes this real: it is the difference between reading the VERIFY block and
65
- * RUNNING it.
66
- *
67
- * Gated by the `verifyWork` config flag. With the flag off, or with no spec to
68
- * verify, this is a pass (ok: true).
35
+ * The `verifyWork` config flag gates the whole pass, in gate-deps.ts. Inside here
36
+ * a missing or empty spec is a pass (ok: true) but `repoHealth` runs FIRST and
37
+ * can FAIL before the spec is looked at.
69
38
  */
70
39
  import { USER_CANCELLED } from './child-runner.js';
71
40
  import { buildEnvNotesBlock, ENV_NOTE_EMIT_INSTRUCTION, extractEnvNotes } from './env-notes.js';
@@ -82,9 +51,9 @@ import { crossTaskDeletionVerifyFindings } from './task-provenance.js';
82
51
  * - `read` lets it inspect a file the VERIFY output points at (a build error's
83
52
  * source line, a config it just validated) to characterise a failure precisely.
84
53
  * - No `edit`/`write`: this pass reports a verdict, it does not change the tree.
85
- * Keeping it read-only means a verify run can never itself introduce a change
86
- * that needs re-verifying, and never scaffolds the junk-file runaway that the
87
- * enforce pass had to drop `write` to stop.
54
+ * That is a CONTRACT, not a capability `bash` can write so the git-state
55
+ * guard backs it up and `mutationCheck` throws away a verdict reached on a
56
+ * mutated tree. The enforce pass, whose job IS editing, runs `read,edit`.
88
57
  */
89
58
  const VERIFY_TOOLS = 'read,bash';
90
59
  /**
@@ -105,10 +74,10 @@ export const VERIFY_FAIL_PREFIX = {
105
74
  * The class of a FAIL — from the typed field when it is there, else from the
106
75
  * prefix the registry above owns.
107
76
  *
108
- * The prefix test survives in exactly ONE place instead of three. It has to
109
- * survive somewhere: `GateDeps.verify` is a seam, a debt read back off disk is a
110
- * bare string with no outcome attached, and the run-level gate mints its own
111
- * `static checks:` line through a different path entirely.
77
+ * The prefix test has to survive somewhere: `GateDeps.verify` is a seam, a debt
78
+ * read back off disk is a bare string with no outcome attached, and final-gate.ts
79
+ * mints its `static checks:` line through a different path entirely. This is the
80
+ * only place in src/ that tests a reason against a prefix.
112
81
  */
113
82
  export function verifyFailClass(o) {
114
83
  if (o.failClass)
@@ -130,10 +99,11 @@ export function isStaticClass(cls) {
130
99
  }
131
100
  /**
132
101
  * Slice the delivered spec (GOAL / CONSTRAINTS / ACCEPTANCE / VERIFY) out of a
133
- * task file body. The composed spec lives under a `## spec` header and runs until
134
- * the next top-level `## ` section (`## phase timings`). Returns null when no spec
135
- * section is present (e.g. a task that never reached compose), which the caller
136
- * treats as a pass there is nothing to verify against.
102
+ * task file body. The compose and critique phases write the section named `spec`,
103
+ * so the composed spec lives under `## spec` and runs to the next line matching
104
+ * `## ` plus non-space (`## phase timings`); a `### ` subheading stays inside.
105
+ * Returns null when there is no spec section or it is blank (a task that never
106
+ * reached compose), which the caller treats as a pass — nothing to verify against.
137
107
  */
138
108
  export function extractSpecForVerification(taskBody) {
139
109
  const lines = taskBody.split('\n');
@@ -197,17 +167,14 @@ function probeAdapter(row) {
197
167
  }
198
168
  /** Identity transform for the rows whose probe already returns finding lines. */
199
169
  const asLines = (raw) => raw;
200
- /**
201
- * The table. ROW ORDER IS THE NOTICE-BLOCK ORDER IN THE PROMPT do not reorder
202
- * without re-running the byte-identity check.
203
- */
170
+ /** The table. ROW ORDER IS THE NOTICE-BLOCK ORDER IN THE PROMPT: `buildVerifyPrompt`
171
+ * flatMaps this array to build the notices, so reordering rows reorders the prompt. */
204
172
  const PROBE_ADAPTERS = [
205
173
  /**
206
- * Deterministic self-verification probe (see substitution-probe.ts): the
207
- * TEST-THE-COPY class is caught 5/5 only when the prompt carries both the rule
208
- * (3b) AND a concrete finding naming the suspect file the rule alone got 2/5
209
- * attention on the local model. The findings are pure git shape (test files the
210
- * task itself changed), so the mandate is language- and framework-agnostic.
174
+ * Deterministic self-verification probe (see substitution-probe.ts): test
175
+ * files this task itself authored or changed, with their added-line counts.
176
+ * Pure git shape, so the mandate is language- and framework-agnostic. Rule 3b
177
+ * lives in the numbered narrative, so this row carries no `rule` text.
211
178
  */
212
179
  probeAdapter({
213
180
  key: 'substitution',
@@ -229,17 +196,11 @@ const PROBE_ADAPTERS = [
229
196
  }),
230
197
  /**
231
198
  * Deterministic prohibition probe (see prohibition-probe.ts): spec-forbidden
232
- * paths the task's diff modified anyway. Same probe+rule design, same reason:
233
- * the VIOLATION-EXCUSAL class (mx5 run 7: child saw "Do NOT modify server-side
234
- * code" violated, waived it as "additive, tests pass", PASSed) needs both the
235
- * no-waiver rule (4b) AND the concrete diff fact the baseline child usually
236
- * never runs `git diff` at all, so without the finding it cannot even SEE the
237
- * violation. A/B on the live local model (violated-but-working fixture,
238
- * everything green, forbidden file modified additively): old prompt 5/5
239
- * false-PASS (several runs affirmatively claimed the forbidden file was
240
- * untouched); rule+finding 5/5 FAIL naming the constraint. Guard: honest-clean
241
- * fixture (prohibition in spec, probe silent) 5/5 PASS — no paranoia.
242
- * Reverted-violation ≡ clean at the diff level (no entry → no finding).
199
+ * paths the task's diff modified anyway, paired with the no-waiver rule 4b.
200
+ * The finding matters because a child left to itself rarely runs `git diff`,
201
+ * so it cannot even SEE the violation. Findings are computed from the diff's
202
+ * changed-file list, so a fully REVERTED violation leaves no entry there and
203
+ * produces no finding.
243
204
  */
244
205
  probeAdapter({
245
206
  key: 'prohibition',
@@ -274,11 +235,11 @@ const PROBE_ADAPTERS = [
274
235
  ]
275
236
  }),
276
237
  /**
277
- * Deterministic cross-task deletion probe (see task-provenance.ts, mx5 run 12
278
- * PROMPT 2): tracked files the task's diff DELETES whose introducing task (git
279
- * provenance) differs from the current task. The only row whose probe does NOT
280
- * return finding lines — the structured value also rides on a FAIL outcome so
281
- * an ACCEPT records each deletion as a durable debt.
238
+ * Deterministic cross-task deletion probe (see task-provenance.ts): tracked
239
+ * files the task's diff DELETES whose introducing task (git provenance)
240
+ * differs from the current task. The only row whose probe does NOT return
241
+ * finding lines — the structured value also rides on a FAIL outcome so an
242
+ * ACCEPT records each deletion as a durable debt.
282
243
  */
283
244
  probeAdapter({
284
245
  key: 'crossTaskDeletion',
@@ -314,9 +275,9 @@ const PROBE_ADAPTERS = [
314
275
  ]
315
276
  }),
316
277
  /**
317
- * Deterministic probe-gaming probe (see probe-gaming.ts, run-8 F6): added lines
318
- * whose stated purpose is to make a CHECK pass instead of meeting the
319
- * requirement it stands for ("return 401 so the verification test passes").
278
+ * Deterministic probe-gaming probe (see probe-gaming.ts): added lines whose
279
+ * stated purpose is to make a CHECK pass instead of meeting the requirement it
280
+ * stands for ("return 401 so the verification test passes").
320
281
  */
321
282
  probeAdapter({
322
283
  key: 'probeGaming',
@@ -357,11 +318,10 @@ const PROBE_ADAPTERS = [
357
318
  /**
358
319
  * DETERMINISTIC skip-escape finding, computed purely from the spec's own VERIFY
359
320
  * block (see skip-escape.ts): a required check wrapped in a skip-announcing `||`
360
- * fallback. Injected so rule 5c fires reliably the model does not self-discover
361
- * a graceful skip-escape (A/B: rule alone ~1-3/5), but acts on a finding naming
362
- * the exact line, per the proven probe+rule pattern. Pure text analysis over
363
- * `deps.spec`, so this row needs no dep and reports no stage: it is the one probe
364
- * that is never absent and never costs a git call.
321
+ * fallback, injected so rule 5c has an exact line to name. Pure text analysis
322
+ * over `deps.spec`, so this row binds no dep and declares no stage — it is the
323
+ * one probe that is never absent and never costs a git call, and the one key
324
+ * excluded from `BoundProbeKey`.
365
325
  */
366
326
  probeAdapter({
367
327
  key: 'skipEscape',
@@ -384,10 +344,10 @@ const PROBE_ADAPTERS = [
384
344
  ]
385
345
  }),
386
346
  /**
387
- * Deterministic sandbox-path-leak probe (see foreign-path.ts, mx5 run 13 PROMPT
388
- * 4 item 1): absolute paths this task committed that exist only inside the
389
- * authoring child's own environment — `/workspace/src/shared` in a vite alias —
390
- * while the real file sits at `src/shared` here.
347
+ * Deterministic sandbox-path-leak probe (see foreign-path.ts): absolute paths
348
+ * this task committed that exist only inside the authoring child's own
349
+ * environment — `/workspace/src/shared` in a vite alias — while the real file
350
+ * sits at `src/shared` here.
391
351
  */
392
352
  probeAdapter({
393
353
  key: 'foreignPath',
@@ -425,11 +385,11 @@ const PROBE_ADAPTERS = [
425
385
  ]
426
386
  }),
427
387
  /**
428
- * Deterministic neutered-check-script probe (see script-escape.ts, mx5 run 13
429
- * PROMPT 4 item 4): check-class scripts in a manifest THIS task changed whose
430
- * exit status cannot be non-zero (`… || true`, an inverted-grep launder). The
431
- * damage is second-order — the script still "passes" — which is exactly why the
432
- * child cannot discover it by running the check.
388
+ * Deterministic neutered-check-script probe (see script-escape.ts): check-class
389
+ * scripts in a manifest THIS task changed whose exit status cannot be non-zero
390
+ * (`… || true`, an inverted-grep launder). The damage is second-order — the
391
+ * script still "passes" — which is exactly why the child cannot discover it by
392
+ * running the check.
433
393
  */
434
394
  probeAdapter({
435
395
  key: 'scriptEscape',
@@ -464,10 +424,9 @@ const PROBE_ADAPTERS = [
464
424
  ]
465
425
  }),
466
426
  /**
467
- * Deterministic test-runner glob-collision probe (see runner-globs.ts, mx5 runs
468
- * 7 AND 13, PROMPT 4 item 2): the manifest declares two runners whose file sets
469
- * are not provably disjoint, so the scanning one imports the other's specs and
470
- * dies during COLLECTION.
427
+ * Deterministic test-runner glob-collision probe (see runner-globs.ts): the
428
+ * manifest declares two runners whose file sets are not provably disjoint, so
429
+ * the scanning one imports the other's specs and dies during COLLECTION.
471
430
  */
472
431
  probeAdapter({
473
432
  key: 'runnerGlob',
@@ -500,8 +459,9 @@ const PROBE_ADAPTERS = [
500
459
  /**
501
460
  * Deterministic test-assembly probe (see test-assembly.ts): authored test files
502
461
  * that rebuild production WIRING — importing the leaf modules the shipped entry
503
- * composes and assembling their own copy instead of the real assembly — under
504
- * rule 3f (F4 test-the-copy, 3rd recurrence). Pure import-graph shape.
462
+ * composes and assembling their own copy instead of the real assembly. Pure
463
+ * import-graph shape; rule 3f lives in the numbered narrative, so this row
464
+ * carries no `rule` text.
505
465
  */
506
466
  probeAdapter({
507
467
  key: 'testAssembly',
@@ -538,8 +498,8 @@ export const BOUND_PROBE_KEYS = PROBE_ADAPTERS.filter(a => a.bound).map(a => a.k
538
498
  * workspace, judge against ACCEPTANCE, and end on exactly one verdict line.
539
499
  *
540
500
  * `findings` is the probe bag: one key per PROBE_ADAPTERS row (see the table
541
- * above for what each channel means and the A/B evidence behind it). A key that
542
- * is absent or empty emits no block — the probes are independently optional.
501
+ * above for what each channel means). A key that is absent or empty emits no
502
+ * block — the probes are independently optional.
543
503
  */
544
504
  export function buildVerifyPrompt(spec, findings = {}, context = {}) {
545
505
  const { envNotes, contracts } = context;
@@ -747,9 +707,11 @@ export function buildVerifyPrompt(spec, findings = {}, context = {}) {
747
707
  ].join('\n');
748
708
  }
749
709
  /**
750
- * Parse the child's verdict. Scans for the LAST `WORK-VERIFIED: PASS|FAIL|UNOBSERVED`
751
- * marker (the model discusses before concluding, and bash output may echo the word
752
- * "VERIFY", so a distinct token and last-match win matter).
710
+ * Parse the child's verdict out of the LAST `WORK-VERIFIED: PASS|FAIL|UNOBSERVED`
711
+ * marker, case-insensitively. Last match wins: the model discusses before
712
+ * concluding, and a bash command it runs can print the token back, so an earlier
713
+ * occurrence is not the verdict. A marker with no trailing text gets a stock
714
+ * detail, so FAIL and UNOBSERVED are never bare.
753
715
  *
754
716
  * UNOBSERVED (rule 5c) is a distinct third outcome: a spec-required behavioral check
755
717
  * could not run because its observation tooling is absent, so the behavior is neither
@@ -780,18 +742,19 @@ export function parseVerifyVerdict(text) {
780
742
  return { pass: false, detail: last[2].trim() || 'unspecified failure' };
781
743
  }
782
744
  /**
783
- * Run the verification pass for one task. A missing spec is a pass. Otherwise run
784
- * the child against the real workspace and turn its verdict into an ok/blocked
785
- * outcome. Never throws (except a user cancel, which propagates so the loop's
786
- * USER_CANCELLED handler reports a clean "cancelled resume").
745
+ * Run the verification pass for one task. `repoHealth` runs first and can FAIL on
746
+ * its own; after it, a missing or empty spec is a pass. Otherwise the child runs
747
+ * against the real workspace and its verdict becomes an ok/blocked outcome. Never
748
+ * throws except on a user cancel, which propagates so the loop's USER_CANCELLED
749
+ * handler reports a clean "cancelled — resume".
787
750
  */
788
751
  export async function runWorkVerification(deps) {
789
752
  // DETERMINISTIC gate FIRST: run the project's own whole-repo static analysis and
790
- // let its exit code decide, before spending a model turn. This catches the class
791
- // the model gate misses — a task whose composed VERIFY block never lints (proven
792
- // 5/5 false-PASS live) because it does not depend on that block. A fail is the
793
- // ordinary verify-FAIL outcome, so it flows into the existing resolution picker.
794
- // Absent dep, or a no-op result (no tooling to run), falls through to the model.
753
+ // let its exit code decide, before spending a model turn. It catches what the
754
+ // model gate structurally cannot — a task whose composed VERIFY block never
755
+ // lints precisely because it does not read that block. A fail is the ordinary
756
+ // verify-FAIL outcome, so it flows into the existing resolution picker. Absent
757
+ // dep, or an ok result, falls through to the spec check and the model.
795
758
  const stage = (label) => {
796
759
  try {
797
760
  deps.onStage?.(label);
@@ -847,10 +810,10 @@ export async function runWorkVerification(deps) {
847
810
  contracts = '';
848
811
  }
849
812
  }
850
- // A child that emits NO verdict never judged the work (budget/context death mid-
851
- // investigation seen live: an 11-minute verify wandered, died verdict-less, and
852
- // the resulting FAIL burned a full implementation re-run on an unjudged artifact).
853
- // That is a verify-side fault, so retry the VERIFY once before reporting a FAIL.
813
+ // A child that emits NO verdict never judged the work it died mid-investigation
814
+ // on budget or context. That is a verify-side fault, and the resulting FAIL would
815
+ // otherwise spend a full implementation re-run on an artifact nobody judged, so
816
+ // the VERIFY is retried once before the FAIL is reported.
854
817
  for (let attempt = 1;; attempt++) {
855
818
  let text;
856
819
  try {
@@ -52,22 +52,22 @@ export interface AutoLoaderState {
52
52
  startedAt: number;
53
53
  lastLine?: string;
54
54
  contextUsage?: ContextSnapshot;
55
- /** Which /task-auto stage this loader is for. Defaults to 'planning' (the
56
- * numbered clarify/decompose steps); 'enforce' is the per-task guideline
57
- * pass and 'verify' is the per-task work-verification pass, neither of which
58
- * has step numbering. 'recommend' is the read-only research that picks the
59
- * recommended action after a verify FAIL. 'lint-fix' is the bounded fix pass
60
- * for a repo-health verify FAIL; 'final-fix' the bounded fix pass for a
61
- * final-integration-gate FAIL. */
55
+ /** Which stage this loader is for. Defaults to 'planning', the numbered
56
+ * clarify/decompose steps the ONLY kind that carries step numbering. The
57
+ * other five mirror `GateChildKind` in gate-child.ts: 'enforce' is the
58
+ * guideline pass, 'verify' the work-verification pass, 'recommend' the
59
+ * research that picks the recommended action after a verify FAIL, 'lint-fix'
60
+ * the bounded fix pass for a repo-health verify FAIL, and 'final-fix' the
61
+ * bounded fix pass for a final-integration-gate FAIL. */
62
62
  kind?: 'planning' | 'enforce' | 'verify' | 'recommend' | 'lint-fix' | 'final-fix';
63
- /** Command shown in the head line. Defaults to '/task-auto', which is what
64
- * every existing producer is; /task-plan reuses this same loader and only
65
- * needs its own name on it. */
63
+ /** Command shown in the head line. Defaults to '/task-auto'; plan-orchestrator
64
+ * is the one producer that overrides it, with '/task-plan'. */
66
65
  command?: string;
67
66
  }
68
67
  export declare function buildAutoLoaderLines(s: AutoLoaderState, theme?: WidgetTheme): string[];
69
- /** Structured mirror of buildAutoLoaderLines. Only the numbered planning stage
70
- * carries done/total; the enforce/verify/recommend/lint-fix passes are unnumbered. */
68
+ /** Structured mirror of buildAutoLoaderLines. Only the planning kind (or an
69
+ * absent one) carries done/total; the other five kinds are unnumbered, and the
70
+ * browser draws its progress bar only when both are present. */
71
71
  export declare function buildAutoLoaderData(s: AutoLoaderState): WidgetData;
72
72
  /**
73
73
  * Start the planning loader widget (same cadence/look as the phase widget).
@@ -85,7 +85,8 @@ export interface ImplState {
85
85
  contextUsage?: ContextSnapshot;
86
86
  }
87
87
  export declare function buildImplLines(s: ImplState, theme?: WidgetTheme): string[];
88
- /** Structured mirror of buildImplLines (the host implementation turn no step
89
- * numbering, so no progress bar; just the phase badge and elapsed clock). */
88
+ /** Structured mirror of buildImplLines. The host implementation turn has no step
89
+ * numbering, so `done`/`total` stay unset and the browser draws no progress bar
90
+ * just the phase badge and the elapsed clock. */
90
91
  export declare function buildImplData(s: ImplState): WidgetData;
91
92
  export declare function flashTerminalWidget(ctx: ExtensionCommandContext, state: Exclude<TaskState, 'pending' | 'in_progress' | 'completed'>, taskId: string, reason: string | undefined): void;
@@ -60,8 +60,10 @@ export function formatContextDetail(usage, theme) {
60
60
  return formatContextTokens(tokens);
61
61
  return null;
62
62
  }
63
- /** The current-action string for the structured widget (the browser ellipsizes
64
- * it to one line, so send it lightly capped rather than terminal-truncated). */
63
+ /** The current-action string for the structured widget. The browser's
64
+ * `.widget-action` is `white-space: nowrap` + `text-overflow: ellipsis`, so it
65
+ * ellipsizes to one line itself — send it capped at 200 rather than truncated to
66
+ * the terminal's narrower WIDGET_LAST_LINE_MAX. */
65
67
  function widgetAction(lastLine) {
66
68
  if (!lastLine)
67
69
  return undefined;
@@ -115,11 +117,12 @@ export function buildWidgetData(s) {
115
117
  export function startWidget(ctx, getState) {
116
118
  if (!ctx.hasUI)
117
119
  return () => { };
118
- // `ctx.ui` THROWS once the ctx goes stale (/reload, session replacement), so
119
- // the theme read belongs INSIDE the guard, not one line above it. render()
120
- // runs from a timer, where an unguarded throw is an uncaughtException that
121
- // kills the whole pi process and a swallowed one would throw again on
122
- // every tick, so a stale ctx latches and stops the timer. Issue #15.
120
+ // pi's `ctx.ui` getter calls `runner.assertActive()`, which THROWS once the
121
+ // ctx goes stale (/reload, session replacement) so the theme read belongs
122
+ // INSIDE the guard, not one line above it. render() runs from a timer, and a
123
+ // throw out of a timer callback is an uncaughtException that terminates the
124
+ // process. Merely swallowing it would throw again every tick, so the stale
125
+ // flag latches and the timer is cleared.
123
126
  let stale = false;
124
127
  const render = () => {
125
128
  if (stale)
@@ -138,9 +141,9 @@ export function startWidget(ctx, getState) {
138
141
  setTaskWidget(plain, s ? buildWidgetData(s) : null);
139
142
  };
140
143
  // The timer is created BEFORE the first render so `timer` is always bound
141
- // when render's catch reaches for it: a ctx already stale on the very first
142
- // paint now stops the loop there, instead of arming an interval that wakes
143
- // up and returns early forever.
144
+ // when render's catch reaches for it. Calling render() first instead would
145
+ // hit the `const timer` temporal dead zone "Cannot access 'timer' before
146
+ // initialization" on a ctx that is already stale at the first paint.
144
147
  const timer = setInterval(render, WIDGET_REFRESH_MS);
145
148
  timer.unref?.();
146
149
  render();
@@ -175,8 +178,9 @@ export function buildAutoLoaderLines(s, theme) {
175
178
  lines.push(trailer);
176
179
  return lines;
177
180
  }
178
- /** Structured mirror of buildAutoLoaderLines. Only the numbered planning stage
179
- * carries done/total; the enforce/verify/recommend/lint-fix passes are unnumbered. */
181
+ /** Structured mirror of buildAutoLoaderLines. Only the planning kind (or an
182
+ * absent one) carries done/total; the other five kinds are unnumbered, and the
183
+ * browser draws its progress bar only when both are present. */
180
184
  export function buildAutoLoaderData(s) {
181
185
  const phase = s.kind === 'enforce' ? 'enforcing guidelines'
182
186
  : s.kind === 'verify' ? 'verifying work'
@@ -226,9 +230,9 @@ export function startAutoLoader(ctx, getState) {
226
230
  setTaskWidget(plain, s ? buildAutoLoaderData(s) : null);
227
231
  };
228
232
  // The timer is created BEFORE the first render so `timer` is always bound
229
- // when render's catch reaches for it: a ctx already stale on the very first
230
- // paint now stops the loop there, instead of arming an interval that wakes
231
- // up and returns early forever.
233
+ // when render's catch reaches for it. Calling render() first instead would
234
+ // hit the `const timer` temporal dead zone "Cannot access 'timer' before
235
+ // initialization" on a ctx that is already stale at the first paint.
232
236
  const timer = setInterval(render, WIDGET_REFRESH_MS);
233
237
  timer.unref?.();
234
238
  render();
@@ -258,8 +262,9 @@ export function buildImplLines(s, theme) {
258
262
  lines.push(trailer);
259
263
  return lines;
260
264
  }
261
- /** Structured mirror of buildImplLines (the host implementation turn no step
262
- * numbering, so no progress bar; just the phase badge and elapsed clock). */
265
+ /** Structured mirror of buildImplLines. The host implementation turn has no step
266
+ * numbering, so `done`/`total` stay unset and the browser draws no progress bar
267
+ * just the phase badge and the elapsed clock. */
263
268
  export function buildImplData(s) {
264
269
  const d = {
265
270
  title: `${s.taskId} · ${titleForDisplay(s)}`,
@@ -1,38 +1,30 @@
1
1
  /**
2
- * Deterministic synthesized-wiring scanner for a composed spec (run-8 F3, gen side).
2
+ * Deterministic synthesized-wiring scanner for a composed spec, wired as the
3
+ * `synthesized-wiring` critique probe.
3
4
  *
4
- * F3 (the dominant run-8 shipped defect): refine/compose invent a "uniform" wiring
5
- * table — one module → one mount prefix, `/api/<x>` → `<x>Routes` for every module
6
- * though the design pins ENDPOINTS, not mounts, and one module's pinned endpoints do
7
- * NOT all sit under a single prefix (photos: `POST /api/listings/:id/photos` AND
8
- * `GET/DELETE /api/photos/:id`). Mounting that module at `/api/photos` double-prefixes
9
- * the upload; consumers follow the pinned paths, assembly follows the invented table,
10
- * the seam ships broken. See [[contract-registry-f3]] (#4, the verify-side + registry
11
- * lever) — this is its GENERATION-side complement.
12
- *
13
- * A/B-measured on the live 27B (F3 critique trap): the CROSS-SLICE CONTRACTS registry
14
- * is NECESSARY but the prompt+registry alone is a WEAK catcher (A/B arms 0/8, +registry
15
- * only 1/8) — the model's attention goes to the obvious VERIFY weakness and it rarely
16
- * does the path-composition reasoning even with the facts in front of it. The reliable
17
- * lever is the SAME probe+rule pattern as [[skip-escape-scanner-f2]] / [[verify-
18
- * substitution-ab]]: a deterministic finding that NAMES the exact synthesized mappings
19
- * and juxtaposes the verbatim pinned facts, forcing focused reconciliation.
5
+ * The failure it catches: a spec states a "uniform" wiring table — one module to one
6
+ * mount prefix, `/api/<x>` → `<x>Routes` while the design pins ENDPOINTS, not
7
+ * mounts. When a module's pinned endpoints do NOT all sit under a single prefix
8
+ * (`POST /api/listings/:id/photos` AND `GET /api/photos/:id`), mounting it at
9
+ * `/api/photos` double-prefixes the upload. Consumers follow the pinned paths,
10
+ * assembly follows the invented table, and the seam ships broken.
20
11
  *
21
12
  * This scanner does NOT decide which mapping is wrong — that needs routing-composition
22
- * knowledge (a forbidden stack assumption). It surfaces every mapping that (a) is not a
23
- * verbatim substring of the design/registry (so it is INFERRED, not cited) AND (b) touches
24
- * a pinned cross-slice boundary (an operand appears in the registry) — i.e. it reshapes a
25
- * shared contract. The 4 coincidentally-correct mappings are surfaced too, but framed as
26
- * "reconcile each; keep the conforming ones" — the LLM decides, informed. Pure text/
27
- * substring analysis; no stack, framework, or routing assumptions. Empty registry (single
28
- * `/task`, or no shared boundary) no-op.
13
+ * knowledge, which would be a stack assumption. It surfaces every mapping that (a) is
14
+ * not a verbatim substring of the design or registry, so it is INFERRED rather than
15
+ * cited, AND (b) touches a pinned cross-slice boundary, meaning an operand appears in
16
+ * the registry. Conforming mappings are surfaced too, framed as "reconcile each; keep
17
+ * the conforming ones" — the model decides, informed. Pure text and substring analysis;
18
+ * no stack, framework, or routing assumptions. An empty registry (a single `/task`, or
19
+ * a design pinning no shared boundary) is a no-op.
29
20
  */
30
21
  export interface WiringClaim {
31
- /** The offending mapping line, verbatim (trimmed). */
22
+ /** The offending mapping line, trimmed and minus any leading list bullet.
23
+ * Backticks are KEPT here — only `from`/`to` have them stripped. */
32
24
  line: string;
33
- /** Left operand (the mapped-from token, e.g. a mount prefix). */
25
+ /** Left operand (the mapped-from token, e.g. a mount prefix), backticks stripped. */
34
26
  from: string;
35
- /** Right operand (the mapped-to token, e.g. a module name). */
27
+ /** Right operand (the mapped-to token, e.g. a module name), backticks stripped. */
36
28
  to: string;
37
29
  }
38
30
  /**
@@ -50,15 +42,16 @@ export declare function findSynthesizedWiring(spec: string, grounding: string, r
50
42
  */
51
43
  export declare function wiringProbeText(findings: WiringClaim[], registry: string): string;
52
44
  /**
53
- * Render findings as a critique-rewrite defect block (fed into the FOCUS list): the
54
- * rewrite must reconcile each mapping against the pinned facts and correct only the
55
- * one(s) that break. Mirrors skipEscapeDefectText's shape.
45
+ * The same text under the name the critique-rewrite defect path uses. One rendering
46
+ * serves both readers, so the probe the model sees and the defect the rewrite is
47
+ * handed can never drift apart.
56
48
  */
57
49
  export declare function wiringDefectText(findings: WiringClaim[], registry: string): string;
58
50
  /**
59
51
  * Concatenate the design/spec docs the given texts @-reference (best-effort, readable
60
52
  * files only) as extra grounding for findSynthesizedWiring — so a mapping the design
61
- * states verbatim is treated as CITED, not synthesized. Unreadable/absent mentions are
62
- * skipped; returns '' when nothing resolves.
53
+ * states verbatim is treated as CITED, not synthesized. Each path is read once across
54
+ * all texts; unreadable or absent mentions are skipped; returns '' when nothing
55
+ * resolves.
63
56
  */
64
57
  export declare function readReferencedDocs(cwd: string, ...texts: string[]): string;