@mjasnikovs/pi-task 0.38.29 → 0.38.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (373) hide show
  1. package/dist/config/config.d.ts +70 -70
  2. package/dist/config/config.js +26 -35
  3. package/dist/config/extension-list.d.ts +6 -5
  4. package/dist/config/extension-list.js +3 -2
  5. package/dist/config/reasoning-args.d.ts +9 -7
  6. package/dist/config/reasoning-args.js +12 -10
  7. package/dist/config/reasoning.d.ts +44 -105
  8. package/dist/config/reasoning.js +27 -704
  9. package/dist/config/register.d.ts +34 -48
  10. package/dist/config/register.js +41 -51
  11. package/dist/config/tool-list.d.ts +16 -16
  12. package/dist/config/tool-list.js +1 -1
  13. package/dist/index.js +2 -0
  14. package/dist/remote/bridge.d.ts +19 -10
  15. package/dist/remote/bridge.js +3 -2
  16. package/dist/remote/broadcast.js +3 -1
  17. package/dist/remote/events.js +12 -11
  18. package/dist/remote/history.d.ts +1 -1
  19. package/dist/remote/protocol.d.ts +6 -3
  20. package/dist/remote/protocol.js +2 -1
  21. package/dist/remote/push.d.ts +16 -16
  22. package/dist/remote/push.js +27 -27
  23. package/dist/remote/register.d.ts +3 -3
  24. package/dist/remote/register.js +17 -19
  25. package/dist/remote/server.d.ts +9 -8
  26. package/dist/remote/server.js +15 -14
  27. package/dist/remote/session-state.d.ts +5 -4
  28. package/dist/remote/session-state.js +8 -5
  29. package/dist/remote/sw.d.ts +7 -6
  30. package/dist/remote/sw.js +7 -6
  31. package/dist/remote/tailscale.d.ts +4 -2
  32. package/dist/remote/tailscale.js +4 -2
  33. package/dist/remote/ui-highlight.js +6 -5
  34. package/dist/remote/ui-render.js +4 -4
  35. package/dist/remote/ui-script.js +24 -24
  36. package/dist/remote/ui-styles.d.ts +1 -1
  37. package/dist/remote/ui-styles.js +10 -13
  38. package/dist/remote/ui-tools.js +9 -6
  39. package/dist/shared/child-extensions.d.ts +29 -17
  40. package/dist/shared/child-extensions.js +29 -17
  41. package/dist/shared/child-output.d.ts +30 -24
  42. package/dist/shared/child-output.js +25 -17
  43. package/dist/shared/child-process.d.ts +47 -40
  44. package/dist/shared/child-process.js +50 -59
  45. package/dist/shared/command-watchdog.d.ts +85 -16
  46. package/dist/shared/command-watchdog.js +115 -21
  47. package/dist/shared/fs-text.d.ts +16 -10
  48. package/dist/shared/fs-text.js +16 -10
  49. package/dist/shared/git-runner.d.ts +25 -25
  50. package/dist/shared/git-runner.js +25 -25
  51. package/dist/shared/leaked-tool-call.d.ts +17 -11
  52. package/dist/shared/leaked-tool-call.js +23 -15
  53. package/dist/shared/model-endpoint.d.ts +29 -16
  54. package/dist/shared/model-endpoint.js +33 -21
  55. package/dist/shared/pi-invocation.d.ts +7 -4
  56. package/dist/shared/pi-invocation.js +12 -7
  57. package/dist/shared/pkg-version.d.ts +13 -5
  58. package/dist/shared/pkg-version.js +13 -5
  59. package/dist/shared/reasoning-capability.d.ts +35 -24
  60. package/dist/shared/reasoning-capability.js +35 -24
  61. package/dist/shared/stream-watchdog.d.ts +60 -44
  62. package/dist/shared/stream-watchdog.js +62 -45
  63. package/dist/task/accept-debt.d.ts +41 -43
  64. package/dist/task/accept-debt.js +73 -65
  65. package/dist/task/api-synthesis.d.ts +24 -21
  66. package/dist/task/api-synthesis.js +32 -26
  67. package/dist/task/apis-contract.d.ts +32 -64
  68. package/dist/task/apis-contract.js +32 -64
  69. package/dist/task/artifact-closure.d.ts +27 -13
  70. package/dist/task/artifact-closure.js +95 -67
  71. package/dist/task/auto-commit.d.ts +46 -35
  72. package/dist/task/auto-commit.js +51 -38
  73. package/dist/task/auto-io.d.ts +45 -25
  74. package/dist/task/auto-io.js +57 -29
  75. package/dist/task/auto-orchestrator.d.ts +26 -24
  76. package/dist/task/auto-orchestrator.js +192 -165
  77. package/dist/task/auto-prompts.d.ts +36 -24
  78. package/dist/task/auto-prompts.js +40 -26
  79. package/dist/task/autofix-ledger.d.ts +27 -25
  80. package/dist/task/autofix-ledger.js +29 -26
  81. package/dist/task/batch-test-task.d.ts +20 -12
  82. package/dist/task/batch-test-task.js +67 -60
  83. package/dist/task/boot-probe.d.ts +60 -44
  84. package/dist/task/boot-probe.js +91 -72
  85. package/dist/task/cancel-input.d.ts +30 -16
  86. package/dist/task/cancel-input.js +20 -11
  87. package/dist/task/cancel-points.d.ts +27 -20
  88. package/dist/task/cancel-points.js +30 -22
  89. package/dist/task/child-runner.d.ts +124 -55
  90. package/dist/task/child-runner.js +298 -90
  91. package/dist/task/child-status.d.ts +23 -16
  92. package/dist/task/child-status.js +23 -16
  93. package/dist/task/clamp-output.js +12 -5
  94. package/dist/task/command-run.d.ts +31 -28
  95. package/dist/task/command-run.js +44 -35
  96. package/dist/task/command-shrink.d.ts +25 -18
  97. package/dist/task/command-shrink.js +37 -31
  98. package/dist/task/command-watchdog.d.ts +9 -6
  99. package/dist/task/command-watchdog.js +21 -15
  100. package/dist/task/context-attribution.d.ts +34 -26
  101. package/dist/task/context-attribution.js +34 -26
  102. package/dist/task/context-silence.d.ts +39 -29
  103. package/dist/task/context-silence.js +35 -25
  104. package/dist/task/context-usage.d.ts +16 -9
  105. package/dist/task/context-usage.js +16 -9
  106. package/dist/task/contracts.d.ts +8 -4
  107. package/dist/task/contracts.js +25 -17
  108. package/dist/task/coverage-loop.d.ts +22 -18
  109. package/dist/task/coverage-loop.js +35 -30
  110. package/dist/task/critique-probes.d.ts +13 -14
  111. package/dist/task/critique-probes.js +50 -39
  112. package/dist/task/debug-log.d.ts +13 -5
  113. package/dist/task/debug-log.js +32 -20
  114. package/dist/task/decompose-fidelity.d.ts +11 -9
  115. package/dist/task/decompose-fidelity.js +38 -33
  116. package/dist/task/decompose-granularity.d.ts +41 -38
  117. package/dist/task/decompose-granularity.js +41 -38
  118. package/dist/task/deep-render-check.d.ts +22 -14
  119. package/dist/task/deep-render-check.js +40 -31
  120. package/dist/task/dropped-input.d.ts +12 -7
  121. package/dist/task/dropped-input.js +5 -2
  122. package/dist/task/enforce-attribution.d.ts +38 -47
  123. package/dist/task/enforce-attribution.js +46 -52
  124. package/dist/task/enforce-guidelines.d.ts +31 -20
  125. package/dist/task/enforce-guidelines.js +32 -21
  126. package/dist/task/enrichment.d.ts +7 -2
  127. package/dist/task/enrichment.js +26 -14
  128. package/dist/task/env-notes.d.ts +16 -7
  129. package/dist/task/env-notes.js +48 -31
  130. package/dist/task/env-template-closure.d.ts +4 -4
  131. package/dist/task/env-template-closure.js +42 -34
  132. package/dist/task/external-context.d.ts +28 -21
  133. package/dist/task/external-context.js +17 -12
  134. package/dist/task/failure-classifier.d.ts +4 -5
  135. package/dist/task/failure-classifier.js +30 -8
  136. package/dist/task/file-inventory.d.ts +15 -11
  137. package/dist/task/file-inventory.js +25 -22
  138. package/dist/task/final-gate-fix.d.ts +74 -86
  139. package/dist/task/final-gate-fix.js +97 -116
  140. package/dist/task/final-gate-progress.d.ts +29 -46
  141. package/dist/task/final-gate-progress.js +40 -51
  142. package/dist/task/final-gate.d.ts +64 -97
  143. package/dist/task/final-gate.js +192 -199
  144. package/dist/task/fix-child.d.ts +21 -27
  145. package/dist/task/fix-child.js +21 -27
  146. package/dist/task/foreign-path.d.ts +6 -5
  147. package/dist/task/foreign-path.js +0 -0
  148. package/dist/task/frozen-conflict.d.ts +9 -10
  149. package/dist/task/frozen-conflict.js +61 -64
  150. package/dist/task/frozen-path-guard.d.ts +35 -14
  151. package/dist/task/frozen-path-guard.js +56 -39
  152. package/dist/task/gate-child.d.ts +27 -28
  153. package/dist/task/gate-child.js +36 -35
  154. package/dist/task/gate-deps.d.ts +34 -27
  155. package/dist/task/gate-deps.js +169 -159
  156. package/dist/task/gate-tally.d.ts +77 -80
  157. package/dist/task/gate-tally.js +65 -68
  158. package/dist/task/git-state-guard.d.ts +15 -11
  159. package/dist/task/git-state-guard.js +76 -66
  160. package/dist/task/impl-widget.d.ts +25 -16
  161. package/dist/task/impl-widget.js +27 -17
  162. package/dist/task/implementation-guards.d.ts +26 -0
  163. package/dist/task/implementation-guards.js +177 -0
  164. package/dist/task/implementation-thinking.d.ts +33 -31
  165. package/dist/task/implementation-thinking.js +5 -6
  166. package/dist/task/implementation-turn.d.ts +39 -31
  167. package/dist/task/implementation-turn.js +41 -28
  168. package/dist/task/inline-markdown.d.ts +20 -7
  169. package/dist/task/inline-markdown.js +15 -6
  170. package/dist/task/launch-config-gap.js +25 -39
  171. package/dist/task/launch-contract.d.ts +18 -21
  172. package/dist/task/launch-contract.js +28 -30
  173. package/dist/task/launch-manifest.d.ts +6 -2
  174. package/dist/task/launch-manifest.js +35 -34
  175. package/dist/task/ledger.js +16 -14
  176. package/dist/task/lint-fix.d.ts +6 -8
  177. package/dist/task/lint-fix.js +67 -69
  178. package/dist/task/loop-detector.d.ts +27 -8
  179. package/dist/task/loop-detector.js +38 -14
  180. package/dist/task/mid-run-input.d.ts +17 -15
  181. package/dist/task/mid-run-input.js +17 -15
  182. package/dist/task/orchestrator.d.ts +24 -28
  183. package/dist/task/orchestrator.js +89 -66
  184. package/dist/task/orientation.d.ts +18 -23
  185. package/dist/task/orientation.js +24 -31
  186. package/dist/task/owned-freeze-conflict.d.ts +21 -20
  187. package/dist/task/owned-freeze-conflict.js +52 -85
  188. package/dist/task/owned-freeze-reassign.d.ts +40 -60
  189. package/dist/task/owned-freeze-reassign.js +41 -61
  190. package/dist/task/parsers.d.ts +4 -2
  191. package/dist/task/parsers.js +4 -4
  192. package/dist/task/phases.d.ts +41 -48
  193. package/dist/task/phases.js +196 -252
  194. package/dist/task/plan-io.d.ts +6 -7
  195. package/dist/task/plan-io.js +6 -7
  196. package/dist/task/plan-orchestrator.d.ts +10 -8
  197. package/dist/task/plan-orchestrator.js +14 -10
  198. package/dist/task/plan-prompts.d.ts +6 -5
  199. package/dist/task/plan-prompts.js +6 -5
  200. package/dist/task/plan-readonly.d.ts +4 -5
  201. package/dist/task/plan-readonly.js +4 -5
  202. package/dist/task/plan-rounds.d.ts +17 -29
  203. package/dist/task/plan-rounds.js +21 -34
  204. package/dist/task/plan-session.d.ts +58 -72
  205. package/dist/task/plan-session.js +61 -83
  206. package/dist/task/probe-gaming.d.ts +28 -27
  207. package/dist/task/probe-gaming.js +0 -0
  208. package/dist/task/prohibition-probe.d.ts +14 -16
  209. package/dist/task/prompts.d.ts +3 -4
  210. package/dist/task/prompts.js +17 -26
  211. package/dist/task/qa-transcript.d.ts +15 -22
  212. package/dist/task/qa-transcript.js +15 -21
  213. package/dist/task/question-box.d.ts +17 -13
  214. package/dist/task/question-box.js +19 -15
  215. package/dist/task/question-dedup.d.ts +6 -7
  216. package/dist/task/question-dedup.js +13 -14
  217. package/dist/task/question-dialog.d.ts +22 -32
  218. package/dist/task/question-dialog.js +22 -32
  219. package/dist/task/question-source.d.ts +18 -44
  220. package/dist/task/question-source.js +22 -51
  221. package/dist/task/refuted-constraint.d.ts +11 -31
  222. package/dist/task/refuted-constraint.js +27 -51
  223. package/dist/task/regenerable-artifacts.d.ts +12 -31
  224. package/dist/task/regenerable-artifacts.js +12 -31
  225. package/dist/task/render-check.d.ts +11 -22
  226. package/dist/task/render-check.js +33 -46
  227. package/dist/task/repo-health-check.d.ts +10 -14
  228. package/dist/task/repo-health-check.js +17 -23
  229. package/dist/task/requirements.d.ts +38 -71
  230. package/dist/task/requirements.js +78 -126
  231. package/dist/task/research-fanout-budget.d.ts +51 -88
  232. package/dist/task/research-fanout-budget.js +51 -88
  233. package/dist/task/research-worker.d.ts +29 -39
  234. package/dist/task/research-worker.js +37 -61
  235. package/dist/task/resume-gap.d.ts +14 -15
  236. package/dist/task/root-cause-repair.d.ts +9 -9
  237. package/dist/task/root-cause-repair.js +28 -40
  238. package/dist/task/run-bracket.d.ts +10 -13
  239. package/dist/task/run-end.d.ts +12 -22
  240. package/dist/task/run-end.js +8 -16
  241. package/dist/task/run-final-gate.d.ts +19 -21
  242. package/dist/task/run-final-gate.js +62 -80
  243. package/dist/task/runner-globs.d.ts +12 -13
  244. package/dist/task/runner-globs.js +12 -13
  245. package/dist/task/runner-resolve.d.ts +9 -9
  246. package/dist/task/runner-resolve.js +22 -23
  247. package/dist/task/script-escape.d.ts +10 -12
  248. package/dist/task/script-escape.js +13 -14
  249. package/dist/task/serve-entry.d.ts +1 -1
  250. package/dist/task/serve-entry.js +22 -25
  251. package/dist/task/service-blocks.js +4 -2
  252. package/dist/task/shipped-source.d.ts +11 -29
  253. package/dist/task/shipped-source.js +11 -29
  254. package/dist/task/skip-escape.js +10 -14
  255. package/dist/task/spec-urls.d.ts +26 -65
  256. package/dist/task/spec-urls.js +26 -65
  257. package/dist/task/spec-validation.d.ts +17 -20
  258. package/dist/task/spec-validation.js +17 -20
  259. package/dist/task/stall-detector.d.ts +23 -30
  260. package/dist/task/stall-detector.js +23 -30
  261. package/dist/task/stream-watchdog.d.ts +14 -12
  262. package/dist/task/stream-watchdog.js +14 -12
  263. package/dist/task/substitution-probe.d.ts +17 -20
  264. package/dist/task/substitution-probe.js +17 -20
  265. package/dist/task/task-gates.d.ts +36 -41
  266. package/dist/task/task-gates.js +95 -106
  267. package/dist/task/task-io.d.ts +4 -4
  268. package/dist/task/task-io.js +4 -4
  269. package/dist/task/task-parsers.js +4 -3
  270. package/dist/task/task-provenance.d.ts +2 -2
  271. package/dist/task/task-provenance.js +11 -13
  272. package/dist/task/task-types.d.ts +4 -3
  273. package/dist/task/terminal-outcome.d.ts +14 -16
  274. package/dist/task/terminal-outcome.js +12 -14
  275. package/dist/task/test-assembly.d.ts +13 -20
  276. package/dist/task/test-assembly.js +13 -20
  277. package/dist/task/timings.d.ts +5 -3
  278. package/dist/task/timings.js +5 -3
  279. package/dist/task/title-label.d.ts +9 -4
  280. package/dist/task/title-label.js +9 -4
  281. package/dist/task/type-only-answer.d.ts +44 -52
  282. package/dist/task/type-only-answer.js +44 -52
  283. package/dist/task/unfailable-command.d.ts +18 -24
  284. package/dist/task/unfailable-command.js +21 -27
  285. package/dist/task/unknown-routing.d.ts +10 -4
  286. package/dist/task/unknown-routing.js +10 -4
  287. package/dist/task/user-directives.d.ts +5 -8
  288. package/dist/task/user-directives.js +5 -8
  289. package/dist/task/verify-quality.d.ts +18 -22
  290. package/dist/task/verify-quality.js +45 -46
  291. package/dist/task/verify-reconcile.d.ts +15 -10
  292. package/dist/task/verify-reconcile.js +45 -43
  293. package/dist/task/verify-resolution.d.ts +24 -20
  294. package/dist/task/verify-resolution.js +51 -50
  295. package/dist/task/verify-work.d.ts +59 -66
  296. package/dist/task/verify-work.js +101 -138
  297. package/dist/task/widget.d.ts +15 -14
  298. package/dist/task/widget.js +22 -17
  299. package/dist/task/wiring-claims.d.ts +25 -32
  300. package/dist/task/wiring-claims.js +30 -35
  301. package/dist/task/write-guard.d.ts +39 -39
  302. package/dist/task/write-guard.js +48 -51
  303. package/dist/task/yolo.d.ts +34 -30
  304. package/dist/task/yolo.js +42 -37
  305. package/dist/workers/abstention.d.ts +21 -41
  306. package/dist/workers/abstention.js +27 -48
  307. package/dist/workers/brave-search.d.ts +4 -3
  308. package/dist/workers/brave-search.js +5 -2
  309. package/dist/workers/brave-warning.d.ts +7 -4
  310. package/dist/workers/brave-warning.js +19 -7
  311. package/dist/workers/ddg-search.d.ts +6 -6
  312. package/dist/workers/ddg-search.js +18 -12
  313. package/dist/workers/docs-cache.js +5 -2
  314. package/dist/workers/docs-chunk.d.ts +30 -37
  315. package/dist/workers/docs-chunk.js +37 -41
  316. package/dist/workers/docs-core.d.ts +28 -44
  317. package/dist/workers/docs-core.js +25 -44
  318. package/dist/workers/docs-index.js +4 -3
  319. package/dist/workers/docs-lookup.d.ts +15 -22
  320. package/dist/workers/docs-lookup.js +12 -21
  321. package/dist/workers/docs-project.d.ts +15 -9
  322. package/dist/workers/docs-project.js +17 -10
  323. package/dist/workers/docs-resolve.d.ts +19 -20
  324. package/dist/workers/docs-resolve.js +35 -32
  325. package/dist/workers/docs-retrieve.d.ts +5 -6
  326. package/dist/workers/docs-retrieve.js +18 -15
  327. package/dist/workers/exa-search.d.ts +9 -6
  328. package/dist/workers/exa-search.js +23 -12
  329. package/dist/workers/fetch-core.d.ts +13 -16
  330. package/dist/workers/fetch-core.js +23 -23
  331. package/dist/workers/focused-extractor.d.ts +13 -12
  332. package/dist/workers/focused-extractor.js +27 -19
  333. package/dist/workers/html-clean.js +24 -14
  334. package/dist/workers/http-request.d.ts +28 -20
  335. package/dist/workers/http-request.js +22 -17
  336. package/dist/workers/npm-version.d.ts +28 -11
  337. package/dist/workers/npm-version.js +24 -15
  338. package/dist/workers/phantom-imports.d.ts +15 -12
  339. package/dist/workers/phantom-imports.js +30 -24
  340. package/dist/workers/pi-worker-core.d.ts +65 -96
  341. package/dist/workers/pi-worker-core.js +93 -181
  342. package/dist/workers/pi-worker-docs.d.ts +24 -19
  343. package/dist/workers/pi-worker-docs.js +67 -76
  344. package/dist/workers/pi-worker-fetch.d.ts +7 -3
  345. package/dist/workers/pi-worker-fetch.js +27 -19
  346. package/dist/workers/pi-worker-search.js +12 -8
  347. package/dist/workers/pi-worker.d.ts +9 -4
  348. package/dist/workers/pi-worker.js +21 -14
  349. package/dist/workers/reasoning-warning.d.ts +18 -17
  350. package/dist/workers/reasoning-warning.js +22 -20
  351. package/dist/workers/research-cache.js +50 -78
  352. package/dist/workers/search-core.js +7 -5
  353. package/dist/workers/search-types.d.ts +10 -9
  354. package/dist/workers/search-types.js +9 -8
  355. package/dist/workers/session-hint.d.ts +13 -14
  356. package/dist/workers/session-hint.js +8 -9
  357. package/dist/workers/shared.d.ts +21 -25
  358. package/dist/workers/shared.js +0 -0
  359. package/dist/workers/single-read-extension.d.ts +14 -7
  360. package/dist/workers/single-read-extension.js +14 -7
  361. package/dist/workers/single-read-guard.d.ts +27 -30
  362. package/dist/workers/single-read-guard.js +36 -36
  363. package/dist/workers/typeonly-log.d.ts +12 -9
  364. package/dist/workers/typeonly-log.js +29 -33
  365. package/dist/workers/worker-channels.d.ts +15 -23
  366. package/dist/workers/worker-channels.js +15 -23
  367. package/dist/workers/worker-failure.d.ts +38 -46
  368. package/dist/workers/worker-failure.js +31 -39
  369. package/dist/workers/worker-kill.d.ts +25 -26
  370. package/dist/workers/worker-kill.js +16 -19
  371. package/dist/workers/worker-profiles.d.ts +54 -56
  372. package/dist/workers/worker-profiles.js +63 -39
  373. package/package.json +10 -8
@@ -1,17 +1,16 @@
1
1
  /**
2
- * Project orientation core — a bounded snapshot of the few files every research
3
- * worker re-reads cold to learn "what is this project" (manifest, config, domain
4
- * types, schema, entrypoints, API surface). The four workers run as separate
5
- * child processes with no shared memory, so today each one independently
6
- * `read()`s the same hot files: across the recorded mx5 run package.json was
7
- * read 87×, src/types/index.ts 82×, and 55% of all worker reads were repeats of
8
- * a file another worker in the same task had already read.
2
+ * Project orientation core — a bounded snapshot of the few files a research worker
3
+ * re-reads cold to learn "what is this project" (manifest, config, domain types,
4
+ * schema, entrypoints, API surface). The four research workers are separate child
5
+ * processes with no shared memory, so without this each one reads the same hot
6
+ * files for itself.
9
7
  *
10
- * This module picks that orientation core from the file inventory (repo-agnostic,
11
- * by path convention), reads it ONCE in the parent, and the caller folds it into
12
- * the shared prompt header so every worker already has those files and skips
13
- * the cold read. It is purely additive: nothing is blocked, so a worker can still
14
- * read anything it wants; orientation only removes the need to.
8
+ * This module picks that core from the file inventory (repo-agnostic, by path
9
+ * convention) and reads it ONCE in the parent. The caller folds the block into a
10
+ * prompt: refine gets a tier-0/1 subset, and phases.ts prepends the full block to
11
+ * the two READ-HEAVY research workers (`worker:files`, `worker:apis`) not to all
12
+ * four. It is purely additive: nothing is blocked, so a worker can still read
13
+ * anything it wants; orientation only removes the need to.
15
14
  *
16
15
  * Bounded by design — the snapshot can never overflow the prompt regardless of
17
16
  * repo size: a hard total byte budget, a per-file cap (one huge file can't eat
@@ -20,23 +19,19 @@
20
19
  * core; reading takes an injectable reader so it can be exercised without a repo.
21
20
  */
22
21
  /**
23
- * Total bytes of file content the orientation block may contain (~10k tokens).
24
- * This is the real overflow guard: it bounds the block regardless of repo size,
25
- * and because the snapshot is prepended to each read-heavy worker it also caps
26
- * the prefill those workers pay. Selection stops as soon as adding a file would
27
- * exceed it.
22
+ * Total bytes the emitted orientation block may occupy. This is the real overflow
23
+ * guard: it bounds the block regardless of repo size, and because the snapshot is
24
+ * prepended to each read-heavy worker it also caps the prefill those workers pay.
25
+ * Selection stops as soon as adding a file would exceed it.
28
26
  */
29
27
  export declare const ORIENTATION_BYTE_BUDGET: number;
30
28
  /** A single file larger than this is skipped (read by the worker as before). */
31
29
  export declare const ORIENTATION_PER_FILE_MAX: number;
32
30
  /**
33
31
  * Backstop file-count cap — a guard against a pathological repo with hundreds of
34
- * tiny core files packing the byte budget into noise, NOT a normal-case limit.
35
- * It is deliberately set high enough that the byte budget binds first on real
36
- * repos (verified: mx5/aiz-server hit the budget at ~16 files; a 5000-file repo
37
- * yields only ~6 orientation candidates because leaf source is filtered out). An
38
- * earlier cap of 16 wrongly bound before the budget — e.g. it dropped 5 core
39
- * files on a 165-file repo while leaving 17KB of budget unused.
32
+ * tiny core files packing the byte budget into noise, NOT a normal-case limit. Set
33
+ * high enough that the byte budget binds first: whenever this cap is what stops
34
+ * selection, budget is left unspent and core files are dropped for no reason.
40
35
  */
41
36
  export declare const ORIENTATION_MAX_FILES = 40;
42
37
  /**
@@ -1,17 +1,16 @@
1
1
  /**
2
- * Project orientation core — a bounded snapshot of the few files every research
3
- * worker re-reads cold to learn "what is this project" (manifest, config, domain
4
- * types, schema, entrypoints, API surface). The four workers run as separate
5
- * child processes with no shared memory, so today each one independently
6
- * `read()`s the same hot files: across the recorded mx5 run package.json was
7
- * read 87×, src/types/index.ts 82×, and 55% of all worker reads were repeats of
8
- * a file another worker in the same task had already read.
2
+ * Project orientation core — a bounded snapshot of the few files a research worker
3
+ * re-reads cold to learn "what is this project" (manifest, config, domain types,
4
+ * schema, entrypoints, API surface). The four research workers are separate child
5
+ * processes with no shared memory, so without this each one reads the same hot
6
+ * files for itself.
9
7
  *
10
- * This module picks that orientation core from the file inventory (repo-agnostic,
11
- * by path convention), reads it ONCE in the parent, and the caller folds it into
12
- * the shared prompt header so every worker already has those files and skips
13
- * the cold read. It is purely additive: nothing is blocked, so a worker can still
14
- * read anything it wants; orientation only removes the need to.
8
+ * This module picks that core from the file inventory (repo-agnostic, by path
9
+ * convention) and reads it ONCE in the parent. The caller folds the block into a
10
+ * prompt: refine gets a tier-0/1 subset, and phases.ts prepends the full block to
11
+ * the two READ-HEAVY research workers (`worker:files`, `worker:apis`) not to all
12
+ * four. It is purely additive: nothing is blocked, so a worker can still read
13
+ * anything it wants; orientation only removes the need to.
15
14
  *
16
15
  * Bounded by design — the snapshot can never overflow the prompt regardless of
17
16
  * repo size: a hard total byte budget, a per-file cap (one huge file can't eat
@@ -20,23 +19,19 @@
20
19
  * core; reading takes an injectable reader so it can be exercised without a repo.
21
20
  */
22
21
  /**
23
- * Total bytes of file content the orientation block may contain (~10k tokens).
24
- * This is the real overflow guard: it bounds the block regardless of repo size,
25
- * and because the snapshot is prepended to each read-heavy worker it also caps
26
- * the prefill those workers pay. Selection stops as soon as adding a file would
27
- * exceed it.
22
+ * Total bytes the emitted orientation block may occupy. This is the real overflow
23
+ * guard: it bounds the block regardless of repo size, and because the snapshot is
24
+ * prepended to each read-heavy worker it also caps the prefill those workers pay.
25
+ * Selection stops as soon as adding a file would exceed it.
28
26
  */
29
27
  export const ORIENTATION_BYTE_BUDGET = 40 * 1024;
30
28
  /** A single file larger than this is skipped (read by the worker as before). */
31
29
  export const ORIENTATION_PER_FILE_MAX = 12 * 1024;
32
30
  /**
33
31
  * Backstop file-count cap — a guard against a pathological repo with hundreds of
34
- * tiny core files packing the byte budget into noise, NOT a normal-case limit.
35
- * It is deliberately set high enough that the byte budget binds first on real
36
- * repos (verified: mx5/aiz-server hit the budget at ~16 files; a 5000-file repo
37
- * yields only ~6 orientation candidates because leaf source is filtered out). An
38
- * earlier cap of 16 wrongly bound before the budget — e.g. it dropped 5 core
39
- * files on a 165-file repo while leaving 17KB of budget unused.
32
+ * tiny core files packing the byte budget into noise, NOT a normal-case limit. Set
33
+ * high enough that the byte budget binds first: whenever this cap is what stops
34
+ * selection, budget is left unspent and core files are dropped for no reason.
40
35
  */
41
36
  export const ORIENTATION_MAX_FILES = 40;
42
37
  /** Code/config/doc extensions worth pre-reading; everything else is ignored. */
@@ -100,10 +95,9 @@ function depth(p) {
100
95
  */
101
96
  export function orientationTier(path) {
102
97
  const lower = path.toLowerCase();
103
- // Never orient on vendored/build output or tests: a dependency's manifest or
104
- // a big *.test.ts would otherwise outrank the project's own files and eat the
105
- // budget (validated against the mx5 traces node_modules/hono/package.json
106
- // and zod-schemas.test.ts both crowded out genuinely hot project files). A
98
+ // Never orient on vendored/build output or tests: a dependency's package.json
99
+ // is tier 0 by basename and a `*.test.ts` under `src/types/` is tier 2, so
100
+ // either would outrank the project's own files and eat the budget. A
107
101
  // git-ls-files inventory won't list these anyway; this is belt-and-braces.
108
102
  if (/(^|\/)(node_modules|dist|build|out|vendor|\.git|coverage)\//.test(lower))
109
103
  return null;
@@ -167,10 +161,9 @@ export async function buildOrientation(inventoryPaths, readFile, opts = {}) {
167
161
  const supplied = new Set();
168
162
  const parts = [];
169
163
  // Budget the *emitted* block, not just the raw content: the per-file fence
170
- // (`--- path ---\n` + the `\n\n` join) and the fixed wrapper add up across
171
- // many files and would otherwise let the block overrun the budget (a 27-file
172
- // repo overran a content-only budget by >1KB). Seed `used` with the wrapper
173
- // so the final block is guaranteed ≤ byteBudget.
164
+ // (`--- path ---\n` + the `\n\n` join) and the fixed wrapper add up across many
165
+ // files, so a content-only budget lets the block overrun. Seeding `used` with
166
+ // the wrapper makes `Buffer.byteLength(block) <= byteBudget` an invariant.
174
167
  const HEADER = `PROJECT ORIENTATION (full contents of the project's core files — `
175
168
  + `already provided, do not re-read these)\n`;
176
169
  const TRAILER = '\n\n';
@@ -9,13 +9,11 @@ export interface CategoryFreeze {
9
9
  /**
10
10
  * One unsatisfiable pair, keyed by the REQUIREMENT rather than by the path.
11
11
  *
12
- * Grouping matters for the resolution's size. mx5 run 18's TASK_0023 carries
13
- * two owned build-contract clauses that between them name three frozen paths;
14
- * per-path findings would demand three separate ownership grants (and the same
15
- * pair twice over, because that spec states its freeze in CONSTRAINTS and again
16
- * in ACCEPTANCE). Per requirement, the rewrite is told which files that one
17
- * obligation names and grants only what it needs — which is what keeps
18
- * `inv-no-spec-inflation` satisfiable at all.
12
+ * Grouping this way bounds the resolution. A requirement naming several frozen
13
+ * files would otherwise yield one finding per file, and a spec that states its
14
+ * freeze in CONSTRAINTS and again in ACCEPTANCE would yield each of those twice.
15
+ * Per requirement, the resolution is told which files that ONE obligation names
16
+ * and grants only what it needs.
19
17
  */
20
18
  export interface OwnedFreezeConflict {
21
19
  /** The owned requirement line, verbatim. */
@@ -55,14 +53,13 @@ export interface OwnedFreezeOptions {
55
53
  /**
56
54
  * Is this repo-relative token an existing SOURCE file of the tree the spec
57
55
  * will run against? Supplied by the caller (compose knows its cwd; the
58
- * measured implementation is "tracked by git" — see `trackedSourceOracle`).
56
+ * usual implementation is "tracked by git" — see `trackedSourceOracle`).
59
57
  *
60
- * Two false-positive classes die here, both observed at STEP 0 on the real
61
- * TASK_0023 spec: route literals and build outputs (`/api`, `dist/`,
62
- * `dist/app.css` named by the very clause that is the true positive, but
63
- * not files anyone can edit), and files a task is about to CREATE, which a
64
- * freeze on the existing tree does not block. Omitted → every path-shaped
65
- * token counts (the broad reading, reported alongside at STEP 0).
58
+ * Two false-positive classes die here: build outputs (`dist/app.css` named
59
+ * by the same clause that names the real file, but not something anyone
60
+ * edits), and files a task is about to CREATE, which a freeze on the existing
61
+ * tree does not block. Omitted every path-shaped token counts, which is the
62
+ * broad reading.
66
63
  */
67
64
  isSource?: (p: string) => boolean;
68
65
  }
@@ -75,7 +72,7 @@ export interface OwnedFreezeOptions {
75
72
  */
76
73
  export declare function findOwnedFreezeConflicts(spec: string | null | undefined, opts?: OwnedFreezeOptions): OwnedFreezeConflict[];
77
74
  /**
78
- * The measured `isSource` oracle: a token counts only when git tracks it in
75
+ * The production `isSource` oracle: a token counts only when git tracks it in
79
76
  * `cwd`. Tracked ⇒ it exists, it is not a build output, and it is not ignored —
80
77
  * exactly the "source file" the category freezes talk about. `git` missing or
81
78
  * the tree not a repo ⇒ every token counts (the broad reading), so the detector
@@ -86,10 +83,14 @@ export declare function trackedSourceOracle(lsFiles: (p: string) => {
86
83
  exitCode: number;
87
84
  }): (p: string) => boolean;
88
85
  /**
89
- * The forced critique-rewrite defect text, in the shape the existing four
90
- * families use: MANDATORY, self-contained, naming the exact resolutions. Prose
91
- * surrender and silently dropping the requirement are called out as
92
- * non-resolutions because narrowing the clause is precisely what run 16 did and
93
- * freezing its file is precisely what run 18 did.
86
+ * A forced-rewrite defect block in the shape the CRITIQUE_PROBES entries use:
87
+ * MANDATORY, self-contained, naming the exact resolutions. Prose surrender and
88
+ * silently dropping the requirement are called out as non-resolutions — narrowing
89
+ * the clause and freezing its file are both ways a rewrite makes the
90
+ * contradiction disappear without satisfying the requirement.
91
+ *
92
+ * UNWIRED. Nothing in src/ or test/ calls this. The shipped resolution is the
93
+ * DETACH in `owned-freeze-reassign.ts`, which needs no model rewrite; this text
94
+ * is what a rewrite-based resolution would say if one were ever added.
94
95
  */
95
96
  export declare function ownedFreezeConflictProbeText(conflicts: OwnedFreezeConflict[]): string;
@@ -1,79 +1,43 @@
1
1
  /**
2
- * owned-freeze-conflict — the FIFTH unsatisfiable-pair family (nexttask 7):
3
- * an AUTHORITATIVE owned requirement whose file falls inside a CATEGORY freeze
4
- * written by the same spec.
2
+ * owned-freeze-conflict — an unsatisfiable spec pair: an AUTHORITATIVE owned
3
+ * requirement whose file falls inside a CATEGORY freeze written by the same spec.
5
4
  *
6
- * WHY frozen-conflict.ts does not see it (mx5 run 18, TASK_0023). The owned
7
- * channel worked: `.pi-tasks/requirements-owned.md` carried the design clause
8
- * "**Server:** `bun run --watch src/server/index.ts` serves `/api` + static
9
- * `dist/`." and the composed spec carried it verbatim under CONSTRAINTS, marked
10
- * AUTHORITATIVE. The same CONSTRAINTS block then said "Do not modify
11
- * `docker-compose.dev.yml`, …, or any source files outside of `package.json`",
12
- * and the spec's ACCEPTANCE/VERIFY converted the behavioural half of the clause
13
- * ("serves `/api` + static `dist/`") into a string-match on `package.json`. The
14
- * only file that could implement it — `src/server/index.ts` — was frozen. The
15
- * requirement was structurally unsatisfiable inside its owning task, VERIFY
16
- * PASSed honestly, and the app shipped with no static route.
5
+ * THE SHAPE. A spec carries a design clause verbatim under CONSTRAINTS, marked
6
+ * AUTHORITATIVE, whose behavioural half can only be satisfied inside one file —
7
+ * and the same spec freezes a category of files that covers that file. The task's
8
+ * own VERIFY can then only assert strings in the files it is allowed to touch, so
9
+ * it PASSes honestly while the requirement is never met.
17
10
  *
18
- * The existing detector misses this shape twice over (both visible in its own
19
- * header): its freeze side needs a NAMED path (`pathNamedIn`), and run 18's
20
- * freeze names a CATEGORY ("any source files outside of `package.json`"); its
21
- * statement side must match one of four measured phrasing families, and a plain
22
- * behavioural claim matches none of them.
11
+ * WHY frozen-conflict.ts does not see it. Its freeze side needs a NAMED path
12
+ * (`pathNamedIn`), and a category freeze names a CLASS instead. Its statement side
13
+ * must match one of a fixed set of registration phrasings, and a plain behavioural
14
+ * claim matches none of them.
23
15
  *
24
16
  * HIGH-PRECISION BY CONSTRUCTION — the statement side needs no NLP:
25
17
  * - owned requirement lines are MACHINE-MARKED. `appendOwnedConstraints`
26
- * stamps every one it appends with "owned requirement from the source
27
- * design (AUTHORITATIVE; …)"; when compose folded the quote in by itself
28
- * the marker is absent, so the caller may also pass the run's ledger
29
- * entries and the quote is matched verbatim against the spec text.
18
+ * (requirements.ts) stamps every bullet it appends with "owned requirement
19
+ * from the source design (AUTHORITATIVE; satisfy it in this task, do not
20
+ * narrow it)". When compose folded the quote in by itself the marker is
21
+ * absent, so the caller may also pass the run's ledger entries and the quote
22
+ * is matched verbatim against the spec text.
30
23
  * - the requirement names its path literally, so the intersection is lexical.
31
- * - category freezes are a small closed lexical set ("any source files
32
- * outside of X", "any files other than X", "only X may be modified",
33
- * "no files outside X").
24
+ * - category freezes are a small closed lexical set ("any source files outside
25
+ * of X", "any files other than X", "only X may be modified", "no files
26
+ * outside X").
34
27
  *
35
- * ── STATUS, 2026-08-05: WIRED but as a DETACH, not as a rewrite. ──────────
36
- *
37
- * `owned-freeze-reassign.ts` consumes this detector at the last spec-producing
38
- * step (`phases.ts`, right after `appendOwnedConstraints`) and resolves a finding
28
+ * WHERE IT RUNS, AND WHY IT CANNOT RUN EARLIER. `owned-freeze-reassign.ts`
29
+ * consumes this detector inside `critiquePhase`, immediately after
30
+ * `appendOwnedConstraints` the last spec-producing step. It resolves a finding
39
31
  * by BOOKKEEPING: the requirement leaves the task that cannot satisfy it and is
40
32
  * claimed later by the task whose refined prompt says it writes the frozen file.
41
- * The quote is never edited, so the deletion failure below cannot recur. A/B-1
42
- * (scripts/owned-freeze-reassign-ab.ts) PASSes on the corpus with five
43
- * invariants. The rewrite lever recorded below stays REFUTED and unwired.
44
- *
45
- * ── The critique-REWRITE seam FAILED its A/B, 2026-08-04. ────────────────────
46
- *
47
- * The detector is precise — 1 finding over 58 real composed specs, and it is the
48
- * true positive (scripts/owned-freeze-conflict-fp-suite.ts, PASS; STEP 0 in
49
- * scripts/owned-vs-freeze-baserate.ts). What failed is the LEVER built on it,
50
- * for two independent reasons, both measured:
33
+ * The quote itself is never edited.
51
34
  *
52
- * 1. THE SEAM IS BLIND IN PRODUCTION. `appendOwnedConstraints` — the BRACES that
53
- * stamp the machine-marked owned bullet this detector keys on — runs AFTER
54
- * `critiqueWithFallback`, inside the `critique` step (phases.ts). When
55
- * critique runs, the stamped line does not exist yet; compose's own folding
56
- * is a PARAPHRASE ("The server watch command must match the contract exactly:
57
- * `…` — serves `/api` + static `dist/`"), so neither the stamp nor the
58
- * verbatim quote is there to match. Live: 0/40 compose drafts carried a
59
- * detectable pair while 11/40 carried the clause semantically. A critique-
60
- * time probe cannot see the shape it was designed for.
61
- * 2. THE REWRITE RESOLVES IT BY DELETING THE REQUIREMENT. Forced through the
62
- * controlled critique seam on run 18's real TASK_0023 draft (n=20/arm):
63
- * pair-present 8/20 → 0/20, but the resolution was scoped ownership in only
64
- * 9/20 — the other 11/20 removed the AUTHORITATIVE clause outright and
65
- * rationalised it ("this references an existing file; no edits are required
66
- * or permitted"), with 0 of the 11 reassigning it to the task that owns the
67
- * file. VERIFY behaviour-observation was 6/20 in BOTH arms: the delivered
68
- * spec still verifies the requirement by grepping `package.json`.
35
+ * A critique-time probe cannot work, because `critiquePhase` calls
36
+ * `critiqueWithFallback` BEFORE `appendOwnedConstraints`: when critique runs, the
37
+ * stamped line does not exist yet, and compose's own folding is a paraphrase, so
38
+ * neither the stamp nor a verbatim quote is there to match.
69
39
  *
70
- * Removal of the pair is not satisfaction of the requirement the same lesson
71
- * as the run-16 lever's delivery metric, one level down. Anything built here
72
- * next has to act AFTER the braces, where the pair actually exists, and cannot
73
- * be a model rewrite: the braces are the last spec-producing step.
74
- *
75
- * It is a pure text function so the base rate, the FP suite and the live A/B all
76
- * measure the same object.
40
+ * It is a pure text function, so a test measures the same object production does.
77
41
  */
78
42
  import { PROHIBITION_RE } from './prohibition-probe.js';
79
43
  import { pathNamedIn } from './frozen-path-guard.js';
@@ -87,14 +51,14 @@ const OWNED_MARKER_RE = /owned\s+requirement\s+from\s+the\s+source\s+design/i;
87
51
  * Modification verbs, shared by the active and passive freeze families. Scoped
88
52
  * to modification exactly as `PROHIBITION_RE` is: a "do not CREATE any files
89
53
  * other than X" line is a creation ban and freezes no existing file, so it must
90
- * never be read as a category freeze (mx5 run 18 TASK_0009 ships that line).
54
+ * never be read as a category freeze.
91
55
  */
92
56
  const MOD_VERB = 'modif|touch|edit|chang|alter|rewrit|overwrit';
93
57
  /**
94
58
  * A category noun phrase with an exception: "any source files outside of X",
95
- * "any existing file other than X", "no files except X". `\w+` slots absorb the
96
- * qualifiers seen in the corpora (source/existing/other), bounded so the phrase
97
- * cannot span a whole paragraph.
59
+ * "any existing file other than X", "no files except X". The `\w+` slots absorb
60
+ * qualifiers like source/existing/other, and are bounded so the phrase cannot
61
+ * span a whole paragraph.
98
62
  */
99
63
  const CATEGORY_NOUN = String.raw `(?:any|no)\s+(?:\w+\s+){0,3}?files?\b`;
100
64
  const EXCEPT_KEYWORD = String.raw `(?:outside(?:\s+of)?|other\s+than|except(?:\s+for)?|besides|apart\s+from|beyond)`;
@@ -108,8 +72,8 @@ const ACTIVE_CATEGORY_RE = new RegExp(String.raw `\b(?:do\s+not|do\s+NOT|don'?t|
108
72
  + String.raw `(?:(?!\b(?:creat|add|introduc|generat)\w*\b)[\s\S]){0,200}?`
109
73
  + String.raw `\b${CATEGORY_NOUN}[^\n]{0,40}?\b${EXCEPT_KEYWORD}\b`, 'i');
110
74
  /**
111
- * Passive family: "No files other than `package.json` are modified." — run 18's
112
- * ACCEPTANCE line, identical in force to the CONSTRAINTS freeze above it.
75
+ * Passive family: "No files other than `package.json` are modified." — the shape
76
+ * an ACCEPTANCE line takes, identical in force to a CONSTRAINTS freeze.
113
77
  */
114
78
  const PASSIVE_CATEGORY_RE = new RegExp(String.raw `\b${CATEGORY_NOUN}[^\n]{0,40}?\b${EXCEPT_KEYWORD}\b`
115
79
  + String.raw `[^\n]{0,120}?\b(?:are|is|may|must|should|can|will)\s+(?:be\s+|been\s+)?(?:${MOD_VERB})\w*`, 'i');
@@ -147,8 +111,8 @@ function tokensWithOrigin(text) {
147
111
  continue;
148
112
  }
149
113
  // A leading `/` is a route literal or an absolute path — never a
150
- // repo-relative source file, and `/api` is named by the very clause
151
- // that is the true positive, so this one is not hypothetical.
114
+ // repo-relative source file. Behavioural clauses routinely name routes
115
+ // (`/api`) beside the file that serves them.
152
116
  if (token.startsWith('/'))
153
117
  continue;
154
118
  const n = token.replace(/^\.\//, '').replace(/\/+$/, '');
@@ -164,8 +128,7 @@ function tokensWithOrigin(text) {
164
128
  * Does the requirement claim anything about the files it names BEYOND quoting a
165
129
  * command that mentions them?
166
130
  *
167
- * This is what separates the two build-contract clauses of mx5 run 18's
168
- * TASK_0023, which are otherwise the same shape:
131
+ * This is what separates two build-contract clauses of the same shape:
169
132
  *
170
133
  * "**Client CSS:** `bunx @tailwindcss/cli -i src/client/index.css -o dist/app.css`"
171
134
  * "**Server:** `bun run --watch src/server/index.ts` — serves `/api` + static `dist/`."
@@ -191,7 +154,7 @@ function hasClaimOutsideCommand(requirement) {
191
154
  * The clause the exception keyword governs: from the keyword to the first
192
155
  * clause break (an em dash, a semicolon, or a sentence end). Everything else on
193
156
  * the line — notably the "— all engine modules (`document.ts`, …) must remain
194
- * untouched" tail of gofer-pixel's freeze — is NOT an exemption.
157
+ * untouched" tail of a freeze — is NOT an exemption.
195
158
  */
196
159
  function exemptClause(line) {
197
160
  const m = new RegExp(String.raw `\b${EXCEPT_KEYWORD}\b`, 'i').exec(line);
@@ -231,8 +194,8 @@ const basename = (p) => p.slice(p.lastIndexOf('/') + 1);
231
194
  * Is `p` inside the freeze — i.e. NOT one of the exempted paths, a file under
232
195
  * an exempted directory, or the same file spelled shorter?
233
196
  *
234
- * The last clause is load-bearing. gofer-pixel TASK_0011 exempts
235
- * `src/components/Canvas.tsx` while its owned requirement quotes the design's
197
+ * The last clause is load-bearing. A spec can exempt
198
+ * `src/components/Canvas.tsx` while its owned requirement quotes a design's
236
199
  * table cell, which says just `Canvas.tsx` — the same file, and the spec is
237
200
  * correctly formed. A bare basename is matched against the exempted paths'
238
201
  * basenames; a path WITH a directory must match exactly or by prefix, so
@@ -300,8 +263,8 @@ export function findOwnedFreezeConflicts(spec, opts = {}) {
300
263
  if (named.length === 0)
301
264
  continue;
302
265
  // One finding per requirement: the FIRST freeze that covers any of its
303
- // files. A spec that restates the same freeze under ACCEPTANCE (run 18
304
- // does) must not double the rewrite's work.
266
+ // files. A spec that restates the same freeze under ACCEPTANCE must not
267
+ // double the rewrite's work.
305
268
  for (const f of freezes) {
306
269
  const paths = named.filter(p => insideFreeze(p, [...f.exempt, ...granted]));
307
270
  if (paths.length === 0)
@@ -313,7 +276,7 @@ export function findOwnedFreezeConflicts(spec, opts = {}) {
313
276
  return out;
314
277
  }
315
278
  /**
316
- * The measured `isSource` oracle: a token counts only when git tracks it in
279
+ * The production `isSource` oracle: a token counts only when git tracks it in
317
280
  * `cwd`. Tracked ⇒ it exists, it is not a build output, and it is not ignored —
318
281
  * exactly the "source file" the category freezes talk about. `git` missing or
319
282
  * the tree not a repo ⇒ every token counts (the broad reading), so the detector
@@ -332,11 +295,15 @@ export function trackedSourceOracle(lsFiles) {
332
295
  };
333
296
  }
334
297
  /**
335
- * The forced critique-rewrite defect text, in the shape the existing four
336
- * families use: MANDATORY, self-contained, naming the exact resolutions. Prose
337
- * surrender and silently dropping the requirement are called out as
338
- * non-resolutions because narrowing the clause is precisely what run 16 did and
339
- * freezing its file is precisely what run 18 did.
298
+ * A forced-rewrite defect block in the shape the CRITIQUE_PROBES entries use:
299
+ * MANDATORY, self-contained, naming the exact resolutions. Prose surrender and
300
+ * silently dropping the requirement are called out as non-resolutions — narrowing
301
+ * the clause and freezing its file are both ways a rewrite makes the
302
+ * contradiction disappear without satisfying the requirement.
303
+ *
304
+ * UNWIRED. Nothing in src/ or test/ calls this. The shipped resolution is the
305
+ * DETACH in `owned-freeze-reassign.ts`, which needs no model rewrite; this text
306
+ * is what a rewrite-based resolution would say if one were ever added.
340
307
  */
341
308
  export function ownedFreezeConflictProbeText(conflicts) {
342
309
  const items = conflicts.map(c => `- the spec carries the AUTHORITATIVE owned requirement `
@@ -1,69 +1,49 @@
1
1
  /**
2
2
  * owned-freeze-reassign — the DETERMINISTIC resolution for the owned/freeze
3
- * unsatisfiable pair (nexttask 2): an AUTHORITATIVE owned requirement whose only
4
- * implementing file the same spec FREEZES. No model, no prose edit. The
5
- * requirement text is never altered — only which task's ledger entry carries it,
6
- * so "resolution by deletion" is structurally impossible.
7
- *
8
- * WHY NOT A REWRITE. Measured on mx5 run 18 (scripts/live-owned-freeze-conflict
9
- * -ab.ts, 20 trials/arm): forcing the pair through the critique seam drives
10
- * pair-present 8/20 → 0/20, but 11 of the 20 resolutions DELETE the
11
- * AUTHORITATIVE clause instead of moving it, and the delivered VERIFY still
12
- * greps `package.json` in both arms (6/20). Removal of the pair is not
13
- * satisfaction of the requirement.
3
+ * unsatisfiable pair: an AUTHORITATIVE owned requirement whose only implementing
4
+ * file the same spec FREEZES. No model, no prose edit. The requirement text is
5
+ * never altered — only which task's ledger entry carries it, so "resolution by
6
+ * deletion" is structurally impossible. That is the whole point: a model asked to
7
+ * remove a contradiction can satisfy the request by deleting the requirement, and
8
+ * removal of the pair is not satisfaction of the requirement.
14
9
  *
15
10
  * ── THE MECHANISM: DETACH, then CLAIM ───────────────────────────────────────
16
11
  *
17
12
  * Two steps, each run where the information it needs actually exists:
18
13
  *
19
- * DETACH at the conflicting task's own critique (right after the braces
20
- * stamp the bullet, which is the first moment the pair exists): the
21
- * entry is marked `pending: [frozen paths]` in the ledger and its
22
- * stamped bullet is dropped from this spec. It is now owned by
23
- * nobody; `ownedForTitle` skips it; the quote is still there, byte for
24
- * byte.
25
- * CLAIM at every LATER task's compose, before the belt block is built: if
26
- * that task's REFINED PROMPT shows a write intent on one of the
27
- * pending paths, the entry becomes that task's own — belt into its
28
- * compose, braces onto its spec.
29
- *
30
- * ── WHY NOT "PICK THE TARGET AT DETACH TIME", WHICH IS WHAT nexttask2.md ASKS ─
31
- *
32
- * nexttask2.md's branch 1 is "if exactly one OTHER task in the plan names path
33
- * `P` — its title or its spec's file list contains `P` — move the requirement
34
- * there". Measured over all 60 recorded composed specs on disk
35
- * (scripts/owned-freeze-reassign-baserate.ts), on the one conflict the corpus
36
- * contains (mx5 run 19 TASK_0015, path `src/server/index.ts`):
14
+ * DETACH at the conflicting task's own critique (`critiquePhase`, right after
15
+ * `appendOwnedConstraints` stamps the bullet, which is the first moment
16
+ * the pair exists): the entry is marked `pending: [frozen paths]` in the
17
+ * ledger and its stamped bullet is dropped from this spec. It is now
18
+ * owned by nobody; `ownedForTitle` skips it; the quote is still there,
19
+ * byte for byte.
20
+ * CLAIM at every LATER task's compose, before the belt block is built: if that
21
+ * task's REFINED PROMPT shows a write intent on one of the pending
22
+ * paths, the entry becomes that task's own — belt into its compose,
23
+ * braces onto its spec. First claimant wins.
37
24
  *
38
- * title-only 3 candidates TASK_0014 TASK_0016 TASK_0017
39
- * FILES-only 7 candidates TASK_0016 … TASK_0025
40
- * either 8 candidates → "exactly one" NEVER holds
25
+ * ── WHY NOT "PICK THE TARGET AT DETACH TIME" ─────────────────────────────────
41
26
  *
42
- * and, decisively, that measurement is against RECORDED SPECS, which production
43
- * does not have: at the conflicting task's compose the later tasks are still
44
- * bare plan titles. None of run 19's 26 plan titles contains the string
45
- * `src/server/index.ts` TASK_0017's reads "Client API layer typed
46
- * hono/client hc<AppType> in api.ts, small fetch/mutation hooks, SPA fallback
47
- * route on server". A path-lexical target rule at detach time is therefore
48
- * BLIND IN PRODUCTION (0 candidates), the same way the run-18 critique probe was.
27
+ * The obvious rule is "if exactly one OTHER task in the plan names path `P`, move
28
+ * the requirement there". It needs COMPOSED SPECS, and at the conflicting task's
29
+ * compose the later tasks are still bare plan titles. A plan title describes a
30
+ * slice of behaviour, not a file list, so a path-lexical target rule at detach
31
+ * time finds nothing to point at.
49
32
  *
50
- * The claimant knows what the planner did not. By its own compose, TASK_0017 has
51
- * a refined prompt that says "add an SPA fallback route to the existing server
52
- * `src/server/index.ts`". Over run 19's 26 refined prompts, `writeIntent` on that
53
- * path fires on exactly two: TASK_0014 (which created the file, already run) and
54
- * TASK_0017. Nothing else in the plan claims it — six other specs mention the
55
- * path, all of them to fence themselves off it.
33
+ * The claimant knows what the planner did not. By its own compose the later task
34
+ * has a REFINED prompt, which does say which files it will write and
35
+ * `writeIntent` reads exactly that, while its negation fence keeps every sibling
36
+ * that merely mentions the path in order to fence itself off it.
56
37
  *
57
- * ── WHY NOT nexttask2.md's BRANCH 2 (CARRY EVERYTHING CROSS-CUTTING) ────────
38
+ * ── WHY NOT CARRY IT AS CROSS-CUTTING ────────────────────────────────────────
58
39
  *
59
40
  * The cross-cutting channel is for prohibitions and product-wide rules
60
- * (`isCrossCuttingRequirement`; `accountCoverage` only routes those there). The
61
- * corpus conflict is a task-specific deliverable clause carrying it would push
62
- * "the server serves static `dist/`" into the 11 tasks that had not yet run,
63
- * none of which owns the server file. That is spec inflation dressed as a fix.
64
- * An entry nobody claims stays `pending` and is surfaced at the end of the run
65
- * (`unclaimedPendingRequirements`), which is a debt the run can see rather than
66
- * an obligation that quietly evaporated.
41
+ * (`isCrossCuttingRequirement`; `accountCoverage` only routes those there). A
42
+ * task-specific deliverable clause carried that way lands in every task that has
43
+ * not run yet, none of which owns the file spec inflation dressed as a fix. An
44
+ * entry nobody claims stays `pending` and `unclaimedPendingRequirements` surfaces
45
+ * it at the end of the run (run-final-gate.ts), so it becomes a debt the run can
46
+ * see rather than an obligation that quietly evaporated.
67
47
  */
68
48
  import { type OwnedFreezeOptions } from './owned-freeze-conflict.js';
69
49
  import { type OwnedRequirement } from './requirements.js';
@@ -96,11 +76,10 @@ export interface DetachResult {
96
76
  * Does this text CLAIM a write on `p` — a create/modify verb reaching a mention
97
77
  * of the path, not fenced by a negation?
98
78
  *
99
- * The negation half is not decoration. Every sibling task's refined prompt names
100
- * the files it must not touch ("Do not create or modify any other files outside
101
- * this slice (e.g., no changes to `src/server/index.ts`, …)" — mx5 run 19
102
- * TASK_0008). Without the fence check that spec claims the server file; with it,
103
- * run 19's 26 refined prompts yield exactly the two tasks that do write it.
79
+ * The negation half is not decoration. A refined prompt routinely names the files
80
+ * its task must NOT touch, in the same sentence as a write verb — "Do not create
81
+ * or modify any other files outside this slice (e.g. no changes to `X`)". Without
82
+ * the fence check, every such sibling claims `X`.
104
83
  */
105
84
  export declare function writeIntent(text: string, p: string): boolean;
106
85
  /**
@@ -124,8 +103,9 @@ export interface ClaimResult {
124
103
  * pending paths its refined prompt writes. Run at the START of compose, so the
125
104
  * claimed obligation rides the same belt block every owned requirement does.
126
105
  *
127
- * First claimant wins (`inv-single-owner`): the entry stops being pending the
128
- * moment it is claimed, so a later task cannot take it as well.
106
+ * First claimant wins: `delete entry.pending` runs before the entry is retitled,
107
+ * so a later task finds nothing pending to take. The test named
108
+ * `inv-single-owner` pins that.
129
109
  */
130
110
  export declare function claimPendingRequirements(args: {
131
111
  /** The claiming task's refined prompt — the text that says what it will write. */