@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,25 +1,25 @@
1
1
  /**
2
- * Deterministic detector for the F-1 laundering shape: a CONTEXT bullet that asserts
2
+ * Deterministic detector for the laundering shape: a CONTEXT bullet that asserts
3
3
  * external API USAGE SEMANTICS under an attribution cue that no EXTERNAL CONTEXT block
4
4
  * can actually support.
5
5
  *
6
- * THE SHAPE, from mx5 run 15 (TASK_0027.md, verbatim):
6
+ * THE SHAPE:
7
7
  *
8
8
  * - The `hono` dependency is pinned at `^4.12.31` in package.json, and the external
9
9
  * context confirms `hc<AppType>` pattern with base URL `/api` for same-origin
10
10
  * relative paths works correctly (per Hono RPC docs LIVE data).
11
11
  *
12
- * worker:context has tools `read,grep` only (phases.ts:623) it cannot consult any
13
- * documentation — so the base-URL claim was necessarily from model memory. It shipped
14
- * into TASK_0027's CONSTRAINTS and ACCEPTANCE, the implementation obeyed it exactly
15
- * (`hc<AppType>('/api')` plus `api.api.auth.login.$post()`), and every request went to
16
- * `/api/api/...` ⇒ 404 ⇒ the product's entire API surface was dead.
12
+ * The `worker:context` row in phases.ts gives that worker `tools: 'read,grep'` and
13
+ * nothing else no fetch, no docs channel — so a base-URL claim like that one is
14
+ * necessarily from model memory. It then ships into a task's CONSTRAINTS and
15
+ * ACCEPTANCE, the implementation obeys it exactly, and every request goes to the
16
+ * wrong path.
17
17
  *
18
18
  * WHY THE OBVIOUS TEST DOES NOT WORK. "Flag a bullet whose package has no EXTERNAL
19
19
  * CONTEXT block" misses this case: EXTERNAL CONTEXT *did* carry a `### npm: hono` block.
20
20
  * That block contains version numbers and nothing else, so it cannot support a claim
21
21
  * about what a base URL MEANS — yet it lends the sentence an air of having been checked.
22
- * That is the whole mechanism (F-1e): one citable fact, the pinned version, fused in a
22
+ * That is the whole mechanism: one citable fact, the pinned version, fused in a
23
23
  * single sentence with an uncitable one under a shared attribution. The true half
24
24
  * launders the false half.
25
25
  *
@@ -30,27 +30,35 @@
30
30
  * ### url: fetched page content -> CAN source a semantics claim
31
31
  * ### service: 3 search-result SNIPPETS -> cannot source a semantics claim
32
32
  *
33
- * The `service` exclusion is not a judgement call — it is the LIVE-DATA RULE's own scope.
34
- * That rule makes a service block authoritative for "current API surface, deprecation
35
- * status, and replacement systems", i.e. versions/status/names. A service block is a
36
- * title + URL + one-line description per result (service-blocks.ts:10); it cannot carry
37
- * what a parameter MEANS. This matters concretely: TASK_0027's enrichment produced
38
- * exactly one service block, `### service: Hono RPC client` (extractEnrichTargets on the
39
- * verbatim refined task yields services=[Hono RPC client], urls=[], packages=[any,api,hc]).
40
- * Were `service` treated as source-capable for semantics, the subject string "Hono RPC
41
- * client" would match the package `hono` and the fatal bullet would pass unflagged — the
42
- * detector would be unable to catch the very defect it exists for.
33
+ * The `service` exclusion is not a judgement call — it is the LIVE-DATA RULE's own
34
+ * scope. That rule (prompts.ts) makes a service block authoritative for "current
35
+ * API surface, deprecation status, and replacement systems", i.e. versions, status
36
+ * and names. And a service block is only ever a title, a URL and a one-line
37
+ * description per result see `formatServiceBlock` so it cannot carry what a
38
+ * parameter MEANS.
39
+ *
40
+ * This matters concretely, and was checked: with a single
41
+ * `### service: Hono RPC client` block as the only external context, the fatal
42
+ * bullet IS flagged. Were `service` treated as source-capable, that subject would
43
+ * match the package `hono` and the bullet would pass — leaving the detector unable
44
+ * to catch the one defect it exists for.
43
45
  *
44
46
  * A bullet is FLAGGED iff all three hold:
45
- * 1. it carries an attribution cue ("per ... LIVE data", "the external context
46
- * confirms", "docs confirm", "per the official docs", ...);
47
- * 2. it asserts API usage semantics — how something is called, what a parameter means,
48
- * what a default is, what behaviour results — as opposed to a version or a status;
47
+ * 1. it carries an attribution cue ("per... LIVE data", "the external context
48
+ * confirms", "docs confirm", "per the official docs",...);
49
+ * 2. it asserts API usage semantics — how something is called, what a parameter
50
+ * means, what a default is, what behaviour results — as opposed to a version
51
+ * or a status;
49
52
  * 3. no `### url:` or `### docs:` block exists for any package the bullet names.
50
53
  *
51
- * Pure and side-effect free; unit-tested in context-attribution.test.ts against the real
52
- * run-15 bullets, including the three legitimate attributed bullets (TASK_0007, _0012,
53
- * _0031) that must NOT be flagged.
54
+ * All six branches were run against the laundering bullet above. It is FLAGGED with
55
+ * an npm-only block, with a service-only block, and with no external context at
56
+ * all; it is NOT flagged once a `### docs:` or `### url:` block for that package
57
+ * exists. And the same context leaves alone a version claim made under an
58
+ * attribution cue, a semantics claim made with NO cue, and a plain "is pinned at"
59
+ * statement of fact.
60
+ *
61
+ * Pure and side-effect free; also unit-tested in context-attribution.test.ts.
54
62
  */
55
63
  /** Block kinds whose body is retrieved prose/declarations, so they can carry semantics. */
56
64
  const SOURCE_CAPABLE_KINDS = new Set(['docs', 'url']);
@@ -118,7 +126,7 @@ function firstMatch(text, patterns) {
118
126
  /**
119
127
  * Split a CONTEXT section into bullets WITH their line ranges. Continuation lines are
120
128
  * folded into the bullet above so a hard-wrapped claim is judged as one sentence — which
121
- * is exactly how the fatal run-15 bullet was written.
129
+ * is exactly how the fatal bullet was written.
122
130
  */
123
131
  export function splitBulletSpans(context) {
124
132
  const spans = [];
@@ -1,27 +1,26 @@
1
1
  /**
2
- * Deterministic classifier for a SILENT worker:context — a rep whose CONTEXT section
3
- * carries zero parseable bullets. The open question this answers (STEP 0 of the
4
- * worker:context ZERO-BULLETS thread) is whether a silent rep is a genuine LOSS (the
5
- * architectural context was there to surface and the worker dropped all of it) or a
6
- * LEGITIMATE empty answer (the task truly had nothing worth a bullet). Only the former
7
- * is a defect worth a lever.
8
- *
9
- * WHAT THE RECORDED EVIDENCE SHOWED (48 reps, three runs, 2026-07-21/22). Every silent
10
- * rep 5/48 fell into one of two failure shapes, NONE legitimately empty:
11
- *
12
- * LOOP_DEGRADE (3/5): the worker thrashed the SAME grep until the loop-killer fired
13
- * (exit 143), leaving only the degrade banner in place of a section. Verbatim:
14
- * "(degraded: research CONTEXT worker stuck in a loop — called grep(...) ×5 ...)"
15
- *
16
- * GENERATION_GARBAGE (2/5): the worker exited 0 in ~3.6s and emitted a hallucinated
17
- * non-bullet fragment instead of context. Verbatim: "Users deleted" and
18
- * "[SYSTEM NOTE This message received a positive feedback reward/+20 ...]"
19
- *
20
- * The fixture (mx5 pre-TASK_0027 tree) is IDENTICAL across all reps and non-silent reps
21
- * reliably emit 11–21 architectural bullets from it, so the input-empty rival is refuted:
22
- * the content was always there; a silent rep dropped it. Both shapes are therefore genuine
23
- * loss. This classifier keys on those shapes so the same verdict is reproducible and so a
24
- * PHASE-1 gate can reuse it to decide when a retry is warranted.
2
+ * Deterministic classifier for a SILENT worker:context — a run whose CONTEXT
3
+ * section carries zero parseable bullets. The question it answers is whether that
4
+ * silence is a genuine LOSS (architectural context was there to surface and the
5
+ * worker dropped all of it) or a LEGITIMATE empty answer (there was nothing worth
6
+ * a bullet). Only the first is worth re-running for.
7
+ *
8
+ * TWO SILENT SHAPES ARE LOSSES, and both are recognisable from the output alone:
9
+ *
10
+ * LOOP_DEGRADE: the worker thrashed the same call until the loop-killer fired,
11
+ * leaving the degrade banner in place of a section. research-worker.ts writes
12
+ * that banner as "stuck in a loop called <tool>(<args>) ×<n> in the last <m>
13
+ * calls…", which is the substring this keys on.
14
+ *
15
+ * GENERATION_GARBAGE: the worker exited 0 and emitted a non-bullet fragment
16
+ * instead of context a stray sentence, or a hallucinated system note.
17
+ *
18
+ * The third silent shape, an honest "nothing to surface" declaration, is NOT a
19
+ * loss and must not trigger a retry. Separating the three is the whole job.
20
+ *
21
+ * This is wired: research-worker gates its silent-retry on
22
+ * `verdict.silent && verdict.genuineLoss`, and keeps the retry only if
23
+ * `countBullets` says it produced any.
25
24
  */
26
25
  /** Why a CONTEXT section came out with no bullets — or that it did not (productive). */
27
26
  export type SilenceCause = 'productive' | 'loop-degrade' | 'generation-garbage' | 'legitimately-empty';
@@ -37,15 +36,26 @@ export interface SilenceVerdict {
37
36
  /** Bullet lines in an emitted CONTEXT section: leading `-` or `*` markers. */
38
37
  export declare function countBullets(contextText: string): number;
39
38
  /**
40
- * Classify one worker:context output. `workerLog` is optional and only consulted for the
41
- * loop banner, which the degrade machinery writes to the debug log even on the reps where
42
- * it never reached the persisted section (e.g. a mid-loop SIGTERM before any write).
39
+ * Classify one worker:context output.
40
+ *
41
+ * `workerLog` is optional and only consulted for the loop banner, which the degrade
42
+ * machinery writes to the debug log even when it never reached the persisted
43
+ * section — a mid-loop SIGTERM before any write. Confirmed by running it: a
44
+ * garbage-looking section plus a log carrying the banner classifies as
45
+ * `loop-degrade`, not `generation-garbage`. The production call site passes no
46
+ * log, so that path is currently reachable only by a caller that supplies one.
43
47
  */
44
48
  export declare function classifyContextSilence(contextText: string, workerLog?: string): SilenceVerdict;
45
49
  /**
46
- * Wilson score interval for a binomial proportion — the CI STEP 0 reports on the silent
47
- * and genuine-loss rates. Normal-approximation (Wald) intervals are badly wrong at the
48
- * small counts and near-boundary rates this measurement lives at; Wilson is not.
50
+ * Wilson score interval for a binomial proportion.
51
+ *
52
+ * A normal-approximation (Wald) interval is useless exactly where this kind of
53
+ * measurement lives — at small counts and rates near 0 or 1. At 0 successes of 12,
54
+ * Wald collapses to the zero-width [0, 0], claiming certainty from no evidence,
55
+ * while Wilson gives roughly [0, 0.24]. Checked both ways, including 12 of 12,
56
+ * which Wilson bounds below 1 rather than pinning at it.
57
+ *
58
+ * No production caller: this is a reporting helper, exercised by its own tests.
49
59
  */
50
60
  export declare function wilsonInterval(successes: number, n: number, z?: number): {
51
61
  lo: number;
@@ -1,27 +1,26 @@
1
1
  /**
2
- * Deterministic classifier for a SILENT worker:context — a rep whose CONTEXT section
3
- * carries zero parseable bullets. The open question this answers (STEP 0 of the
4
- * worker:context ZERO-BULLETS thread) is whether a silent rep is a genuine LOSS (the
5
- * architectural context was there to surface and the worker dropped all of it) or a
6
- * LEGITIMATE empty answer (the task truly had nothing worth a bullet). Only the former
7
- * is a defect worth a lever.
2
+ * Deterministic classifier for a SILENT worker:context — a run whose CONTEXT
3
+ * section carries zero parseable bullets. The question it answers is whether that
4
+ * silence is a genuine LOSS (architectural context was there to surface and the
5
+ * worker dropped all of it) or a LEGITIMATE empty answer (there was nothing worth
6
+ * a bullet). Only the first is worth re-running for.
8
7
  *
9
- * WHAT THE RECORDED EVIDENCE SHOWED (48 reps, three runs, 2026-07-21/22). Every silent
10
- * rep — 5/48 — fell into one of two failure shapes, NONE legitimately empty:
8
+ * TWO SILENT SHAPES ARE LOSSES, and both are recognisable from the output alone:
11
9
  *
12
- * LOOP_DEGRADE (3/5): the worker thrashed the SAME grep until the loop-killer fired
13
- * (exit 143), leaving only the degrade banner in place of a section. Verbatim:
14
- * "(degraded: research CONTEXT worker stuck in a loop — called grep(...) ×5 ...)"
10
+ * LOOP_DEGRADE: the worker thrashed the same call until the loop-killer fired,
11
+ * leaving the degrade banner in place of a section. research-worker.ts writes
12
+ * that banner as "stuck in a loop — called <tool>(<args>) ×<n> in the last <m>
13
+ * calls…", which is the substring this keys on.
15
14
  *
16
- * GENERATION_GARBAGE (2/5): the worker exited 0 in ~3.6s and emitted a hallucinated
17
- * non-bullet fragment instead of context. Verbatim: "Users deleted" and
18
- * "[SYSTEM NOTE This message received a positive feedback reward/+20 ...]"
15
+ * GENERATION_GARBAGE: the worker exited 0 and emitted a non-bullet fragment
16
+ * instead of context a stray sentence, or a hallucinated system note.
19
17
  *
20
- * The fixture (mx5 pre-TASK_0027 tree) is IDENTICAL across all reps and non-silent reps
21
- * reliably emit 11–21 architectural bullets from it, so the input-empty rival is refuted:
22
- * the content was always there; a silent rep dropped it. Both shapes are therefore genuine
23
- * loss. This classifier keys on those shapes so the same verdict is reproducible and so a
24
- * PHASE-1 gate can reuse it to decide when a retry is warranted.
18
+ * The third silent shape, an honest "nothing to surface" declaration, is NOT a
19
+ * loss and must not trigger a retry. Separating the three is the whole job.
20
+ *
21
+ * This is wired: research-worker gates its silent-retry on
22
+ * `verdict.silent && verdict.genuineLoss`, and keeps the retry only if
23
+ * `countBullets` says it produced any.
25
24
  */
26
25
  /** Bullet lines in an emitted CONTEXT section: leading `-` or `*` markers. */
27
26
  export function countBullets(contextText) {
@@ -31,9 +30,14 @@ const LOOP_BANNER = /stuck in a loop/i;
31
30
  /** Honest "nothing to surface" — the ONLY non-loss silent shape. */
32
31
  const EMPTY_DECLARATION = /^\s*(none|n\/a|no relevant (context|architectural)|nothing\b)/i;
33
32
  /**
34
- * Classify one worker:context output. `workerLog` is optional and only consulted for the
35
- * loop banner, which the degrade machinery writes to the debug log even on the reps where
36
- * it never reached the persisted section (e.g. a mid-loop SIGTERM before any write).
33
+ * Classify one worker:context output.
34
+ *
35
+ * `workerLog` is optional and only consulted for the loop banner, which the degrade
36
+ * machinery writes to the debug log even when it never reached the persisted
37
+ * section — a mid-loop SIGTERM before any write. Confirmed by running it: a
38
+ * garbage-looking section plus a log carrying the banner classifies as
39
+ * `loop-degrade`, not `generation-garbage`. The production call site passes no
40
+ * log, so that path is currently reachable only by a caller that supplies one.
37
41
  */
38
42
  export function classifyContextSilence(contextText, workerLog = '') {
39
43
  const bulletCount = countBullets(contextText);
@@ -76,9 +80,15 @@ export function classifyContextSilence(contextText, workerLog = '') {
76
80
  };
77
81
  }
78
82
  /**
79
- * Wilson score interval for a binomial proportion — the CI STEP 0 reports on the silent
80
- * and genuine-loss rates. Normal-approximation (Wald) intervals are badly wrong at the
81
- * small counts and near-boundary rates this measurement lives at; Wilson is not.
83
+ * Wilson score interval for a binomial proportion.
84
+ *
85
+ * A normal-approximation (Wald) interval is useless exactly where this kind of
86
+ * measurement lives — at small counts and rates near 0 or 1. At 0 successes of 12,
87
+ * Wald collapses to the zero-width [0, 0], claiming certainty from no evidence,
88
+ * while Wilson gives roughly [0, 0.24]. Checked both ways, including 12 of 12,
89
+ * which Wilson bounds below 1 rather than pinning at it.
90
+ *
91
+ * No production caller: this is a reporting helper, exercised by its own tests.
82
92
  */
83
93
  export function wilsonInterval(successes, n, z = 1.959963984540054 // 95%
84
94
  ) {
@@ -4,14 +4,32 @@
4
4
  * the planning and gate children; the single-task widget (TaskRunner) calls it
5
5
  * directly, because its state is the whole-run `WidgetState`, not one child's.
6
6
  */
7
- import type { ExtensionCommandContext } from '@earendil-works/pi-coding-agent';
8
7
  import type { ContextSnapshot } from '../shared/child-process.js';
9
- /** The parent session's context window, or 0 when the model doesn't expose it. */
10
- export declare function getParentContextWindow(ctx: ExtensionCommandContext): number;
11
8
  /**
12
- * Fold a raw context snapshot into a display snapshot: prefer the child's
13
- * own contextWindow, else the last known one, else the parent session's; then
14
- * derive percent against it falling back to the child's reported percent when
15
- * no window is known at all.
9
+ * The parent session's context window, or 0 when the model doesn't expose it.
10
+ *
11
+ * The parameter is the STRUCTURAL MINIMUM this reads, deliberately, rather than
12
+ * one of pi's context interfaces. Naming `ExtensionCommandContext` here would
13
+ * exclude the plain context a TOOL is handed — and that is a real caller:
14
+ * `workers/pi-worker.ts` reads the window through this to arm the churn rule.
15
+ * Both pi contexts carry a `model` whose `contextWindow` is a number, so both
16
+ * satisfy the shape.
17
+ *
18
+ * Returns 0 for a context with no model, and for a model with no window.
19
+ */
20
+ export declare function getParentContextWindow(ctx: {
21
+ model?: {
22
+ contextWindow?: number;
23
+ };
24
+ }): number;
25
+ /**
26
+ * Fold a raw context snapshot into a display snapshot: prefer the child's own
27
+ * contextWindow, else the last known one, else the parent session's; then derive
28
+ * percent against it, falling back to the child's own reported percent when no
29
+ * window is known at all.
30
+ *
31
+ * Run through all four: a child reporting 4000 uses it; a child reporting 0 with a
32
+ * previous 8000 uses that; with neither, the parent's; and with nothing anywhere
33
+ * the reported percent survives untouched. The derived percent clamps at 100.
16
34
  */
17
35
  export declare function resolveContextUsage(snapshot: ContextSnapshot, prev: ContextSnapshot | undefined, parentContextWindow: number): ContextSnapshot;
@@ -4,15 +4,30 @@
4
4
  * the planning and gate children; the single-task widget (TaskRunner) calls it
5
5
  * directly, because its state is the whole-run `WidgetState`, not one child's.
6
6
  */
7
- /** The parent session's context window, or 0 when the model doesn't expose it. */
7
+ /**
8
+ * The parent session's context window, or 0 when the model doesn't expose it.
9
+ *
10
+ * The parameter is the STRUCTURAL MINIMUM this reads, deliberately, rather than
11
+ * one of pi's context interfaces. Naming `ExtensionCommandContext` here would
12
+ * exclude the plain context a TOOL is handed — and that is a real caller:
13
+ * `workers/pi-worker.ts` reads the window through this to arm the churn rule.
14
+ * Both pi contexts carry a `model` whose `contextWindow` is a number, so both
15
+ * satisfy the shape.
16
+ *
17
+ * Returns 0 for a context with no model, and for a model with no window.
18
+ */
8
19
  export function getParentContextWindow(ctx) {
9
- return (ctx.model?.contextWindow ?? 0);
20
+ return ctx.model?.contextWindow ?? 0;
10
21
  }
11
22
  /**
12
- * Fold a raw context snapshot into a display snapshot: prefer the child's
13
- * own contextWindow, else the last known one, else the parent session's; then
14
- * derive percent against it falling back to the child's reported percent when
15
- * no window is known at all.
23
+ * Fold a raw context snapshot into a display snapshot: prefer the child's own
24
+ * contextWindow, else the last known one, else the parent session's; then derive
25
+ * percent against it, falling back to the child's own reported percent when no
26
+ * window is known at all.
27
+ *
28
+ * Run through all four: a child reporting 4000 uses it; a child reporting 0 with a
29
+ * previous 8000 uses that; with neither, the parent's; and with nothing anywhere
30
+ * the reported percent survives untouched. The derived percent clamps at 100.
16
31
  */
17
32
  export function resolveContextUsage(snapshot, prev, parentContextWindow) {
18
33
  const cw = snapshot.contextWindow > 0 ?
@@ -10,9 +10,11 @@ export declare function readContracts(cwd: string): Promise<string>;
10
10
  /**
11
11
  * Normalise for substring matching: collapse all whitespace runs to one space and
12
12
  * lowercase. Quoting across a line wrap or with reflowed spacing still matches the
13
- * source; casing differences do not defeat the anti-synthesis guard. Exported as
14
- * the ONE grounding normaliser every "verbatim quote from the source doc" guard
15
- * shares (contracts, decompose source anchors), so the rule can't drift.
13
+ * source, and casing differences do not defeat the anti-synthesis guard.
14
+ *
15
+ * Exported as the ONE grounding normaliser every "verbatim quote from the source
16
+ * doc" guard shares, so the rule cannot drift: decompose-fidelity and requirements
17
+ * both import it from here alongside this module's own use.
16
18
  */
17
19
  export declare function normalise(s: string): string;
18
20
  /**
@@ -21,7 +23,9 @@ export declare function normalise(s: string): string;
21
23
  * CONTRACT: "<verbatim quote>" [anchor: <where>]
22
24
  * The quote (between the first pair of double quotes) is the pinned fact; the
23
25
  * optional `[anchor: …]` trailer records provenance. A line without a quoted span
24
- * is skipped — an unquoted "contract" is a summary, which this registry rejects.
26
+ * is skipped — an unquoted "contract" is a summary, which this registry rejects
27
+ * and so is a quote shorter than MIN_QUOTE_LENGTH or longer than
28
+ * MAX_CONTRACT_LENGTH. All three skips were run.
25
29
  */
26
30
  export declare function parseContractLines(text: string): ContractEntry[];
27
31
  /**
@@ -2,13 +2,13 @@
2
2
  * contracts — a per-run registry of CROSS-SLICE INTERFACE FACTS, recorded once at
3
3
  * decompose time and read (never written) by every downstream slice.
4
4
  *
5
- * The failure this serves (mx5 run 8, F3 the dominant shipped-defect class): the
6
- * SOURCE design pins an interface contract (a SPLIT route table: `POST
7
- * /api/listings/:id/photos` but `GET/DELETE /api/photos/:id`). One slice's refine
8
- * FABRICATED a uniform mount table ("/api/photos → photosRoutes") with no anchor in
9
- * the doc; the consumer slices followed the spec, the assembly slice followed the
10
- * fabrication, and the seam between them shipped broken while each slice was locally
11
- * "right". Class: refine synthesizes plausible interface specifics instead of citing.
5
+ * The failure this serves: a source design pins an interface contract that is not
6
+ * uniform say a split route table, `POST /api/listings/:id/photos` alongside
7
+ * `GET/DELETE /api/photos/:id`. One slice's refine then FABRICATES the tidy version
8
+ * it expected ("/api/photos → photosRoutes") with no anchor in the doc. Consumer
9
+ * slices follow the spec, the assembly slice follows the fabrication, and the seam
10
+ * between them ships broken while every slice is locally "right". The class is
11
+ * refine synthesizing plausible interface specifics instead of citing them.
12
12
  *
13
13
  * Mechanism (mirrors env-notes.ts): interface facts that MORE THAN ONE task will
14
14
  * touch — endpoint paths, exported signatures, file layouts, env var names, whatever
@@ -17,12 +17,16 @@
17
17
  * file (no artifact corruption). It lives under `.pi-tasks/`, surviving discardEdits
18
18
  * and the git-state guard.
19
19
  *
20
- * HARD DESIGN RULE (this is exactly how F3 happened): a registry entry is a VERBATIM
21
- * QUOTE from the source doc plus a source anchor — NEVER a model-synthesized summary.
22
- * The anti-synthesis guard is deterministic: a candidate quote is kept only if it is
23
- * an actual substring of the source document (normalised for whitespace). A quote the
24
- * model paraphrased or invented is not in the doc, so it is dropped — a fabricated
25
- * contract can never enter the registry.
20
+ * HARD DESIGN RULE: a registry entry is a VERBATIM QUOTE from the source doc plus a
21
+ * source anchor — NEVER a model-synthesized summary. The anti-synthesis guard is
22
+ * deterministic: a candidate quote is kept only if it is an actual substring of the
23
+ * source document, normalised for whitespace and case. A quote the model
24
+ * paraphrased or invented is not in the doc, so it is dropped.
25
+ *
26
+ * Run on the shape above: fed both real route lines AND the fabricated
27
+ * "/api/photos → photosRoutes", the guard keeps the two that are in the doc and
28
+ * drops the invention. Reflowed whitespace and different casing still match, so
29
+ * quoting across a line wrap does not defeat it.
26
30
  *
27
31
  * Stack-agnostic: an "interface fact" is any pinned boundary string; the guard is
28
32
  * pure substring matching over the source text, with no assumption about its shape.
@@ -59,9 +63,11 @@ export async function readContracts(cwd) {
59
63
  /**
60
64
  * Normalise for substring matching: collapse all whitespace runs to one space and
61
65
  * lowercase. Quoting across a line wrap or with reflowed spacing still matches the
62
- * source; casing differences do not defeat the anti-synthesis guard. Exported as
63
- * the ONE grounding normaliser every "verbatim quote from the source doc" guard
64
- * shares (contracts, decompose source anchors), so the rule can't drift.
66
+ * source, and casing differences do not defeat the anti-synthesis guard.
67
+ *
68
+ * Exported as the ONE grounding normaliser every "verbatim quote from the source
69
+ * doc" guard shares, so the rule cannot drift: decompose-fidelity and requirements
70
+ * both import it from here alongside this module's own use.
65
71
  */
66
72
  export function normalise(s) {
67
73
  return s.replace(/\s+/g, ' ').trim().toLowerCase();
@@ -72,7 +78,9 @@ export function normalise(s) {
72
78
  * CONTRACT: "<verbatim quote>" [anchor: <where>]
73
79
  * The quote (between the first pair of double quotes) is the pinned fact; the
74
80
  * optional `[anchor: …]` trailer records provenance. A line without a quoted span
75
- * is skipped — an unquoted "contract" is a summary, which this registry rejects.
81
+ * is skipped — an unquoted "contract" is a summary, which this registry rejects
82
+ * and so is a quote shorter than MIN_QUOTE_LENGTH or longer than
83
+ * MAX_CONTRACT_LENGTH. All three skips were run.
76
84
  */
77
85
  export function parseContractLines(text) {
78
86
  const entries = [];
@@ -1,23 +1,27 @@
1
1
  /**
2
2
  * coverage-loop — the MONOTONIC replacement rule for /task-auto's decompose
3
- * coverage gate (mx5 run 12).
3
+ * coverage gate.
4
4
  *
5
- * The failure this closes: the coverage-retry loop regenerated the whole plan on
6
- * every INCOMPLETE verdict, and adopted the regeneration on nothing but a size
7
- * floor (`retry.length * 2 >= current.length`). A regeneration is a fresh
8
- * stochastic roll of the ENTIRE plan, so one that DROPPED a previously-covered
9
- * feature-area but kept the title count replaced the better plan anyway — and,
10
- * because the loop shipped whatever the LAST round produced, the dropped area was
11
- * gone with only a toast. Live: a complete full-stack plan (31 requirements
12
- * mapped, frontend pages present) was overwritten by a backend-only one and
13
- * shipped, driven by 3 NEGATIVE requirements no task could ever "own" that kept
14
- * the verdict INCOMPLETE forever.
5
+ * The failure this closes: a coverage retry regenerates the WHOLE plan, so it is a
6
+ * fresh stochastic roll rather than an edit. Adopt it on a size floor alone and a
7
+ * retry that DROPPED a previously-covered area but kept the title count replaces
8
+ * the better plan — and since the loop ships whatever the last round produced, the
9
+ * dropped area is gone with only a toast.
10
+ *
11
+ * The shape that makes this bite: a requirement no task can ever "own" — a
12
+ * prohibition, say keeps the verdict INCOMPLETE forever, so the loop keeps
13
+ * rolling until a worse plan happens to come up last.
15
14
  *
16
15
  * The rule here makes replacement monotone: coverage can only hold or grow across
17
16
  * rounds. A retry is adopted ONLY when it drops no requirement the current plan
18
- * already owns (its owned-set is a superset). Because adoption is monotone, the
19
- * working plan at exhaustion is the best-covered one seen so "ship the working
20
- * plan" is automatically "ship the best", never "ship the last".
17
+ * already owns its owned-set must be a superset. Because adoption is monotone,
18
+ * the working plan at exhaustion is the best-covered one seen, so "ship the
19
+ * working plan" is automatically "ship the best" and never "ship the last".
20
+ *
21
+ * Each rule was run. A retry dropping one owned requirement is rejected naming
22
+ * it; a strict superset is adopted; a retry that grows while covering nothing new
23
+ * is rejected as "no coverage gain"; and with no requirement signal at all, a
24
+ * retry leaving MORE areas uncovered is rejected while one leaving fewer is taken.
21
25
  *
22
26
  * Spec-shape-agnostic: the only inputs are title counts and the set of
23
27
  * requirement INDICES a task owns (from the host-side coverage map). No feature
@@ -47,13 +51,13 @@ export interface CoveragePlan {
47
51
  * DETERMINISTIC owned-set for the monotonic guard — grounded in requirement↔title
48
52
  * token overlap, NOT the coverage-map model's `TASK n` verdict.
49
53
  *
50
- * Why this exists (live A/B, Qwen3.6-27B, mx5-shaped CLI spec): the model
54
+ * Why this exists: the model
51
55
  * over-credits ownership — it mapped a "--json output" requirement to a generic
52
56
  * "scaffold + argument parser" task, so a plan with NO --json task still reported
53
57
  * owning it. A guard that trusts those numbers is blind to the very drop it must
54
- * catch (treatment held only 1/5 trials). Grounding coverage in whether a task
58
+ * catch. Grounding coverage in whether a task
55
59
  * TITLE actually shares a distinctive token with the requirement makes the
56
- * drop-signal independent of the model's rubber-stamp (treatment → 5/5).
60
+ * drop-signal independent of the model's rubber-stamp.
57
61
  *
58
62
  * A requirement is "covered" when some title shares a DISTINCTIVE token with it —
59
63
  * distinctive meaning the token is not shared across more than half the ownable
@@ -103,7 +107,7 @@ export declare function decideAdoption(current: CoveragePlan, retry: CoveragePla
103
107
  * title list the coverage-map child was prompted with. Hold the two apart and the
104
108
  * index silently addresses the wrong plan.
105
109
  *
106
- * That is not hypothetical. The coverage loop used to keep `best` (the scored plan)
110
+ * That is not hypothetical: a loop that keeps `best` (the scored plan)
107
111
  * and a separate `let accounting`, updated on adoption as
108
112
  * `accounting = cand.accounting ?? accounting`. `cand.accounting` is null whenever
109
113
  * the coverage-map child throws or its output fails to parse — a fault that is