@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,7 +1,7 @@
1
1
  /**
2
2
  * env-notes — a per-run cache of ENVIRONMENT FACTS shared across gate children.
3
3
  *
4
- * The failure this serves (mx5 run 7, F8): every gate child re-discovers the
4
+ * The failure this serves: every gate child re-discovers the
5
5
  * same environment facts from scratch — where the DB credentials live, which
6
6
  * services are reachable, which tools are installed — burning minutes of
7
7
  * archaeology per child through the serial model bottleneck.
@@ -19,18 +19,21 @@
19
19
  * defect") still governs every verdict — the block injected into prompts says
20
20
  * so explicitly. The cache only kills re-discovery time.
21
21
  *
22
- * PROVENANCE + RE-VALIDATION (run 8, F7): a verify child once grepped component
23
- * names in a MINIFIED bundle (identifiers mangled 0 hits by construction),
24
- * wrote "build tree-shakes ALL route componentspre-existing issue" to the
25
- * cache, and ten later tasks inherited it verbatim as a standing "pre-existing,
26
- * unrelated" excuse to wave off a genuinely broken deliverable nobody
27
- * re-checked. Two guards close that class: (a) each note is stamped host-side
28
- * with the ORIGIN task that recorded it (a note is second-hand hearsay, not the
29
- * reader's own observation); (b) the injected block demands the reader
30
- * RE-VALIDATE a note in the CURRENT tree before citing it to excuse a failure,
31
- * flags EXCUSE-CLASS notes ("pre-existing", "unrelated", "tree-shaken") for
32
- * exactly that scrutiny, and forbids treating a grep of a generated artifact as
33
- * evidence of absence. Provenance is mechanical; re-validation is prompt-level.
22
+ * PROVENANCE + RE-VALIDATION. A shared cache has a failure mode a per-child one
23
+ * does not: a WRONG fact propagates. The shape to fear is a verify child grepping
24
+ * component names in a MINIFIED bundleidentifiers there are mangled, so zero
25
+ * hits is guaranteed regardless of the truth concluding "the build tree-shakes
26
+ * all route components, pre-existing issue", and every later task inheriting that
27
+ * verbatim as a standing excuse to wave off a genuinely broken deliverable.
28
+ * Nobody re-checks a fact that is already written down.
29
+ *
30
+ * Two guards close it. (a) Each note is stamped host-side with the ORIGIN task
31
+ * that recorded it, so it reads as second-hand hearsay rather than the reader's
32
+ * own observation. (b) The injected block demands the reader RE-VALIDATE a note
33
+ * in the CURRENT tree before citing it to excuse a failure, marks EXCUSE-CLASS
34
+ * notes for exactly that scrutiny, and states outright that a zero-hit grep of a
35
+ * generated artifact is not evidence of absence. Provenance is mechanical;
36
+ * re-validation is prompt-level.
34
37
  */
35
38
  import { makeLedger } from './ledger.js';
36
39
  const ENV_NOTES_FILE = 'env-notes.md';
@@ -45,8 +48,10 @@ const MAX_NOTE_LENGTH = 240;
45
48
  */
46
49
  const ORIGIN_SEP = '\t';
47
50
  /**
48
- * Parse the stored file into fact+origin records. Legacy lines written before
49
- * provenance (no separator) parse with an empty origin, so old caches still read.
51
+ * Parse the stored file into fact+origin records. A line with no separator parses
52
+ * with an empty origin rather than being dropped, so a cache written before
53
+ * provenance existed still reads — and `buildEnvNotesBlock` renders those as
54
+ * "origin unrecorded" instead of silently claiming an author.
50
55
  */
51
56
  export function parseEnvNotes(raw) {
52
57
  const out = [];
@@ -82,8 +87,10 @@ export async function readEnvNotes(cwd) {
82
87
  return ledger.readRaw(cwd);
83
88
  }
84
89
  /**
85
- * Pull `ENV-NOTE: <fact>` lines out of a child's answer text. Deduplicated,
86
- * length-capped; verdict markers can never match (different prefix).
90
+ * Pull `ENV-NOTE: <fact>` lines out of a child's answer text: trimmed,
91
+ * deduplicated case-insensitively, and dropped when empty or over
92
+ * MAX_NOTE_LENGTH. Run: a `VERDICT:` line and even a near-miss `ENV-NOTES:` line
93
+ * match nothing, so a verdict cannot leak into the fact cache.
87
94
  */
88
95
  export function extractEnvNotes(text) {
89
96
  const notes = [];
@@ -101,17 +108,22 @@ export function extractEnvNotes(text) {
101
108
  return notes;
102
109
  }
103
110
  /**
104
- * EXCUSE-CLASS wording: a note that waves a problem off as someone else's or a
105
- * prior condition ("pre-existing mismatch", "unrelated to this task",
106
- * "tree-shaken", "not applicable"). These are the notes that propagate across
107
- * slices as standing excuses (mx5 run-8 F7) — every one of the run-8 cache's
108
- * dozen such notes was either the false tree-shake fact or the schema mismatch
109
- * the final gate later proved was a REAL defect. Pure text, stack-agnostic; the
110
- * flag never drops or fails a note, it only marks it as needing live
111
- * re-validation before it may EXCUSE a failure. FP is harmless by construction:
112
- * a benign fact re-validates and is used, the marker only bites a citation-to-
113
- * wave-off. Benign status facts ("5 pre-existing warnings") do not match — a
114
- * "pre-existing" match requires a co-located problem word.
111
+ * EXCUSE-CLASS wording: a note that waves a problem off as someone else's or as a
112
+ * prior condition. These are the notes that propagate across slices as standing
113
+ * excuses, and the ones most likely to be masking a real defect rather than
114
+ * describing the environment.
115
+ *
116
+ * Pure text, stack-agnostic. The flag never drops or fails a note it only marks
117
+ * it as needing live re-validation before it may EXCUSE a failure, so a false
118
+ * positive is harmless: a benign fact re-validates and is used, and the marker
119
+ * only bites a citation-to-wave-off.
120
+ *
121
+ * Run against the shapes it has to separate: "unrelated to this task",
122
+ * "tree-shaken by the build", "pre-existing mismatch in the schema", "not
123
+ * applicable here" and "affects all routes" all flag, while the benign status
124
+ * fact "5 pre-existing warnings" does NOT — a "pre-existing" match needs a
125
+ * co-located problem word — and neither do ordinary facts like "postgres
126
+ * reachable on 5432".
115
127
  */
116
128
  const EXCUSE_PATTERNS = [
117
129
  /\bunrelated\b/i,
@@ -130,9 +142,14 @@ export function isExcuseNote(fact) {
130
142
  /**
131
143
  * Append newly discovered facts to the cache, deduplicated against what is
132
144
  * already there (case-insensitive fact match), keeping the newest MAX_NOTES.
133
- * Each new fact is stamped with the `origin` task that recorded it; a fact
134
- * already present keeps its ORIGINAL origin (provenance traces to who first
135
- * established it). Failures are swallowed the cache is a sharpener, never a
145
+ * Each new fact is stamped with the `origin` task that recorded it; a fact already
146
+ * present keeps its ORIGINAL origin, so provenance traces to whoever first
147
+ * established it. Confirmed by re-appending the same fact under a different task:
148
+ * one entry survives, still carrying the first writer.
149
+ *
150
+ * Tabs in an emitted fact are normalised to spaces before storage, which is what
151
+ * keeps the separator unambiguous. The cap holds too — sixty further facts leave
152
+ * MAX_NOTES stored. Failures are swallowed: the cache is a sharpener, never a
136
153
  * blocker.
137
154
  */
138
155
  export async function appendEnvNotes(cwd, notes, origin = '') {
@@ -2,10 +2,10 @@
2
2
  * entry is a name no `.env.example` is expected to carry. */
3
3
  export declare const AMBIENT_ENV: Set<string>;
4
4
  /** The same rule by MECHANISM rather than by name: a variable INJECTED by a
5
- * platform (CI runner, package manager, freedesktop base dirs). STEP 0 found
6
- * `GITHUB_ENV` (written by GitHub Actions), `npm_execpath` and `XDG_CACHE_HOME`
7
- * classified as required in real trees; a template that declared them would be
8
- * wrong, so the exclusion is the prefix, not a growing list of names. */
5
+ * platform — a CI runner, a package manager, freedesktop base dirs. `GITHUB_ENV`,
6
+ * `npm_execpath` and `XDG_CACHE_HOME` all read as "required" to a naive scan in
7
+ * real trees, and a template that declared any of them would be wrong. So the
8
+ * exclusion is the PREFIX, not a list of names that would have to keep growing. */
9
9
  export declare const AMBIENT_PREFIXES: string[];
10
10
  /** Rule 4: is this variable the platform's to supply? */
11
11
  export declare function isAmbient(name: string): boolean;
@@ -1,26 +1,31 @@
1
1
  /**
2
2
  * env-template-closure — a shipped source file requires an env var the shipped
3
- * template never mentions (nexttask 10).
3
+ * template never mentions.
4
4
  *
5
- * The failure this closes (mx5 run 19, `dfbdd6f`, validated): `src/server/seed.ts`
6
- * reads `process.env.ADMIN_PHONE` / `ADMIN_PASSWORD` with no default, the tracked
7
- * `.env.example` declares only `DATABASE_URL` + `APP_URL`, and `bun run seed` was
8
- * one of the run's final-gate commands. It exited 1; the gate's autofix wrote the
9
- * two vars into `.env`, which is GITIGNORED (nexttask 4) so the committed tree
10
- * still cannot seed and nothing at run end ever said why. Coverage credits the
11
- * CONSUMING side (seed.ts exists, is owned, passes its own VERIFY); the template is
12
- * a separate artifact nobody re-reads after TASK_0001.
5
+ * The failure this closes: a seed script reads `process.env.ADMIN_PHONE` and
6
+ * `ADMIN_PASSWORD` with no default while the tracked `.env.example` declares only
7
+ * `DATABASE_URL` and `APP_URL`. The seed command then exits 1, and an autofix
8
+ * "resolves" it by writing the two vars into `.env` which is GITIGNORED, so the
9
+ * COMMITTED tree still cannot seed and nothing at run end says why.
10
+ *
11
+ * Coverage cannot see it: it credits the CONSUMING side, because the script exists,
12
+ * is owned, and passes its own VERIFY. The template is a separate artifact nobody
13
+ * re-reads after the task that wrote it.
14
+ *
15
+ * That exact shape, run against a real repo, produces the two findings and no
16
+ * others — `DATABASE_URL` is declared and stays silent.
13
17
  *
14
18
  * THE RULE. Every REQUIRED env read in TRACKED source must appear in the TRACKED
15
19
  * env template. One-directional: a variable DECLARED but never read is silence, not
16
- * a finding (dace-pro ships 13 declared / 7 required and must stay clean).
20
+ * a finding a template carrying entries nothing reads yields zero findings, which
21
+ * is what keeps a deliberately over-declared template clean.
17
22
  *
18
23
  * REQUIRED is mechanical. A read steps aside when it:
19
24
  * 1. carries a default — `?? …`, `|| …`, `os.getenv('X', d)`, `environ.get('X', d)`;
20
25
  * 2. is compared, not consumed — `===`, `!==`, `==`, `!=` on either side;
21
26
  * 3. is an assignment TARGET — `process.env.DATABASE_URL = testDbUrl`, which is
22
- * what every one of mx5's seven test files does and is the single largest FP
23
- * source in the corpus;
27
+ * what a test file typically does, and is the readiest source of false
28
+ * positives;
24
29
  * 4. names an AMBIENT variable — a short fixed allowlist (below) of things the
25
30
  * platform, not the project, supplies.
26
31
  *
@@ -32,14 +37,19 @@
32
37
  * untracked scratch file can neither declare nor require anything.
33
38
  * • generated/vendored trees (`dist/`, `build/`, `node_modules/`, …) are not
34
39
  * authored source and are skipped; they only ever mirror a read we already saw.
35
- * • NO TEMPLATE IN THE TREE ⇒ THE CHECK IS INERT (as `repo-health-check` does
36
- * with a missing manifest). This must never invent a file the project chose
37
- * not to have.
40
+ * • NO TEMPLATE IN THE TREE ⇒ THE CHECK IS INERT, the way `repo-health-check`
41
+ * treats a missing manifest. Confirmed: a repo with a required read and no
42
+ * template at all yields zero findings, and so does a directory that is not a
43
+ * git repo. This must never invent a file the project chose not to have.
44
+ *
45
+ * Not npm-shaped: JS/TS (`process.env` / `Bun.env`), Python (`os.environ[…]`,
46
+ * `os.environ.get`, `os.getenv`) and Go (`os.Getenv`) all read the same way. Go's
47
+ * `os.LookupEnv` is the explicit may-be-absent API and gets its own step-aside,
48
+ * `optional-api`.
38
49
  *
39
- * Not npm-shaped (`memory/gate-blind-on-non-npm-projects.md`): JS/TS
40
- * (`process.env` / `Bun.env`), Python (`os.environ[…]`, `os.environ.get`,
41
- * `os.getenv`) and Go (`os.Getenv`) read the same way. Go's `os.LookupEnv` is the
42
- * explicit may-be-absent API and is treated as its own step-aside.
50
+ * Every rule above was run: each of the four step-asides fires with its own label,
51
+ * comparison is caught on either side, all three languages produce a REQUIRED read,
52
+ * `os.LookupEnv` steps aside, and both dynamic forms extract nothing at all.
43
53
  */
44
54
  import { spawnSync } from 'node:child_process';
45
55
  import { readFileSync } from 'node:fs';
@@ -58,9 +68,8 @@ export const AMBIENT_ENV = new Set([
58
68
  'TMPDIR',
59
69
  'LANG',
60
70
  // Windows/OS equivalents of the above, and the package manager's own vars —
61
- // every one of these was OBSERVED as a "required" read during STEP 0's
62
- // hand-read (gofer-rag `npm_execpath`, the pi-task corpus's `LOCALAPPDATA` /
63
- // `XDG_CACHE_HOME`), and none of them belongs in a project's template.
71
+ // every one of these reads as "required" to a naive scan (`npm_execpath`,
72
+ // `LOCALAPPDATA`, `XDG_CACHE_HOME`), and none belongs in a project's template.
64
73
  'APPDATA',
65
74
  'LOCALAPPDATA',
66
75
  'USERPROFILE',
@@ -73,10 +82,10 @@ export const AMBIENT_ENV = new Set([
73
82
  'COMSPEC'
74
83
  ]);
75
84
  /** The same rule by MECHANISM rather than by name: a variable INJECTED by a
76
- * platform (CI runner, package manager, freedesktop base dirs). STEP 0 found
77
- * `GITHUB_ENV` (written by GitHub Actions), `npm_execpath` and `XDG_CACHE_HOME`
78
- * classified as required in real trees; a template that declared them would be
79
- * wrong, so the exclusion is the prefix, not a growing list of names. */
85
+ * platform — a CI runner, a package manager, freedesktop base dirs. `GITHUB_ENV`,
86
+ * `npm_execpath` and `XDG_CACHE_HOME` all read as "required" to a naive scan in
87
+ * real trees, and a template that declared any of them would be wrong. So the
88
+ * exclusion is the PREFIX, not a list of names that would have to keep growing. */
80
89
  export const AMBIENT_PREFIXES = ['npm_', 'GITHUB_', 'RUNNER_', 'CI_', 'XDG_', 'BUN_', 'NODE_'];
81
90
  /** Rule 4: is this variable the platform's to supply? */
82
91
  export function isAmbient(name) {
@@ -160,7 +169,7 @@ const MATCHERS = [
160
169
  * that opens with one? (`process.env.X\n ?? 'y'` is one expression.)
161
170
  *
162
171
  * A ternary CONDITION counts: `process.env.npm_execpath ? a : b` names both
163
- * outcomes, so nothing is required (gofer-rag, hand-read in STEP 0). `?.` is
172
+ * outcomes, so nothing is required. `?.` is
164
173
  * optional chaining, not a ternary, and must not match. */
165
174
  function hasDefault(before, after, nextLine) {
166
175
  // The read IS the fallback: `X ?? process.env.BRAVE_API_KEY` (brave-warning.ts)
@@ -183,14 +192,14 @@ function hasDefault(before, after, nextLine) {
183
192
  * `if (c) …` Playwright cache when unset
184
193
  *
185
194
  * The discriminator is the SIGN of the guard, and it is exactly what separates
186
- * those from the lead: mx5's seed.ts writes `const phone = process.env.ADMIN_PHONE`
195
+ * those from the lead: a seed script writes `const phone = process.env.ADMIN_PHONE`
187
196
  * … `if (!phone) throw`. A NEGATED guard means the variable is required and the
188
197
  * program stops without it; a POSITIVE guard means it is an override. So a bare
189
198
  * `if (` / `while (` head steps aside, `if (!` does not, and an assign-then-guard
190
199
  * is resolved by looking ahead for the FIRST guard on that variable.
191
200
  */
192
201
  const GUARD_HEAD_RE = /\b(?:if|while)\s*\(\s*$/;
193
- /** How far an assign-then-guard may reach. mx5's is 4 lines; 10 is slack. */
202
+ /** How far an assign-then-guard may reach. A few lines is typical; 10 is slack. */
194
203
  const GUARD_LOOKAHEAD = 10;
195
204
  function isProbeHead(before) {
196
205
  return GUARD_HEAD_RE.test(before);
@@ -202,7 +211,7 @@ function assignedTo(before) {
202
211
  }
203
212
  /**
204
213
  * What the guard's own body does. A NEGATED guard only means "required" when the
205
- * program STOPS without the variable — `if (!phone) throw` (mx5, the lead). When
214
+ * program STOPS without the variable — `if (!phone) throw`. When
206
215
  * it merely returns or falls through — `if (!process.env.PI_REMOTE_PUSH_DEBUG)
207
216
  * return` (push.ts, a debug flag) — the variable is optional and the negation
208
217
  * proves nothing. Same syntax, opposite meaning; the body is the discriminator.
@@ -243,7 +252,7 @@ function locallySupplied(text, name) {
243
252
  * it as an override, so every read of it in that file is a probe. Without this,
244
253
  * the CONSUMING read inside the guarded branch — `if (process.env.PI_BIN) return
245
254
  * {command: process.env.PI_BIN}` (pi-invocation.ts), `process.env.GOFER_PYTHON ?
246
- * [process.env.GOFER_PYTHON] : [...]` (gofer) — reads as required. */
255
+ * [process.env.PYTHON_BIN] : [...]` — reads as required. */
247
256
  function locallyProbed(text, name) {
248
257
  const e = `(?:process|Bun)\\.env\\s*\\.\\s*${name}`;
249
258
  return (new RegExp(`\\b(?:if|while)\\s*\\(\\s*${e}\\b`).test(text)
@@ -260,7 +269,7 @@ function isCompared(before, after) {
260
269
  }
261
270
  /** Rule 3: the read is a WRITE — `process.env.X = …` (but not `==`/`===`), or
262
271
  * `delete process.env.X`. Both mean the file SUPPLIES the variable rather than
263
- * consuming it; mx5's seven test files are the assignment case and gofer's
272
+ * consuming it; a suite of test files is the assignment case and a
264
273
  * `wdio.packaged.conf.ts` (`delete process.env.GOFER_GDFORMAT`) is the delete
265
274
  * case — a scrub of a developer override, the opposite of a requirement. */
266
275
  function isAssigned(before, after) {
@@ -290,8 +299,7 @@ export function scanSource(file, text) {
290
299
  // the RESULT is seen (`os.Getenv("X") == ""`).
291
300
  const after = matcher.call ? raw.replace(/^\s*\)/, '') : raw;
292
301
  // …and past any WRAPPING call's brackets, so `Number(process.env.X)
293
- // || 32` (gofer-rag, the largest FP class the STEP-0 hand-read
294
- // found) reads as defaulted. Stepping aside when the `||` in fact
302
+ // || 32` the largest false-positive class — reads as defaulted. Stepping aside when the `||` in fact
295
303
  // defaults an enclosing expression is a false NEGATIVE, which this
296
304
  // check spends freely; a false rank-0 gate failure it does not.
297
305
  // …and past a trailing accessor chain, so `process.env.X?.trim() ||
@@ -8,16 +8,19 @@
8
8
  * from the four research workers. `enrichment.ts` stays a pure parser; the I/O
9
9
  * lives here.
10
10
  *
11
- * There were TWO copies of this assembly: {@link gatherExternalContext} (the
12
- * research phase, raw workers) and an 87-line inline block in `phaseAutoAnswer`
13
- * (the grill auto-answer, focused workers). They agreed on everything that
14
- * shows up in the output the 8-step shape, the "npm blocks lead" ordering,
15
- * the `### docs:` / `### url:` headings, the service loop's `no_key` / `error`
16
- * handling, the block terminator — and disagreed only on POLICY. So the shape
17
- * is {@link buildExternalContext} once, the disagreements are
18
- * {@link ExternalContextPolicy}, and the worker variant is
19
- * {@link ExternalContextLookups} an adapter, expressible only since the
20
- * focused-extractor seam landed.
11
+ * TWO call paths share this assembly: the research phase via
12
+ * {@link gatherExternalContext} (raw workers) and the grill auto-answer via
13
+ * {@link buildExternalContext} directly (focused workers). Everything that shows
14
+ * up in the OUTPUT is identical between them the "npm blocks lead" ordering, the
15
+ * `### docs:` / `### url:` headings, the service loop's `no_key` / `error`
16
+ * handling, the trailing blank-line terminator — and they differ only on POLICY.
17
+ *
18
+ * So the shape lives here once, the differences are {@link ExternalContextPolicy},
19
+ * and the raw-vs-focused worker choice is {@link ExternalContextLookups}, an
20
+ * adapter the focused-extractor seam made expressible.
21
+ *
22
+ * Run against a mixed source, the emitted headings come out in exactly that order:
23
+ * `### npm:` then `### docs:` then `### url:` then `### service:`.
21
24
  */
22
25
  import { type NpmVersionInfo } from '../workers/npm-version.js';
23
26
  import type { SearchCoreInput, SearchCoreResult } from '../workers/search-core.js';
@@ -48,8 +51,9 @@ export interface ExternalTargetResult {
48
51
  * whole page markdown, truncated), `phaseAutoAnswer` binds the FOCUSED ones (a
49
52
  * child's one-question answer). Everything else about the block is identical.
50
53
  *
51
- * A rejected lookup is caught by the builder and yields no blocks for that
52
- * target, so adapters may throw freely.
54
+ * A rejected lookup is caught by the builder and yields no blocks for that target,
55
+ * so adapters may throw freely. Confirmed: one adapter rejecting mid-fan-out
56
+ * leaves the other targets' blocks intact and contributes nothing of its own.
53
57
  */
54
58
  export interface ExternalContextLookups {
55
59
  docs(pkg: string): Promise<ExternalTargetResult | null>;
@@ -58,10 +62,11 @@ export interface ExternalContextLookups {
58
62
  search?: (input: SearchCoreInput) => Promise<SearchCoreResult>;
59
63
  }
60
64
  /**
61
- * The six places the two call paths genuinely disagreed. Each is a knob rather
62
- * than a default, because every one of them is a deliberate, measured choice on
63
- * at least one path — the auto-answer block is capped and records nothing
64
- * because it runs per grill question, in front of a waiting user.
65
+ * The five places the two call paths genuinely disagree. Each is a knob rather
66
+ * than a default, because every one is a deliberate choice on at least one path:
67
+ * the auto-answer block is capped and records nothing because it runs per grill
68
+ * question, in front of a waiting user, while research is uncapped and trails its
69
+ * sub-step.
65
70
  */
66
71
  export interface ExternalContextPolicy {
67
72
  /**
@@ -74,9 +79,9 @@ export interface ExternalContextPolicy {
74
79
  /**
75
80
  * A cheap live version lookup for every named dep that did NOT get a docs
76
81
  * target, so a version block exists for ALL of them. Omit to disable, as the
77
- * auto-answer path does. Without this on the research path, deps past the
78
- * docs cap had no live version and a "which version?" question fell back to
79
- * the model's stale training data how tailwindcss got pinned to an old major.
82
+ * auto-answer path does. Without it, any dep past the docs cap carries no live
83
+ * version at all, and a "which version?" question falls back to whatever the
84
+ * model remembers which is how a dependency gets pinned to a stale major.
80
85
  */
81
86
  versionLookup?: (pkg: string) => Promise<NpmVersionInfo | null>;
82
87
  /** Sub-step label recorded via `deps.recordSubStep`. Omit to record nothing. */
@@ -89,8 +94,10 @@ export interface ExternalContextPolicy {
89
94
  earlyReturnOnNoTargets?: boolean;
90
95
  }
91
96
  /**
92
- * Assemble the `EXTERNAL CONTEXT\n…\n\n` block for `source`, or `''` when there
93
- * is nothing to enrich (no targets, or every lookup failed).
97
+ * Assemble the `EXTERNAL CONTEXT\n…\n\n` block for `source`, or `''` when there is
98
+ * nothing to enrich no targets, or every lookup failed. Both were run: a source
99
+ * naming nothing returns `''`, and so does one whose only target is a service
100
+ * search that errored.
94
101
  */
95
102
  export declare function buildExternalContext(source: string, deps: GatherDeps, lookups: ExternalContextLookups, policy?: ExternalContextPolicy): Promise<string>;
96
103
  /**
@@ -8,16 +8,19 @@
8
8
  * from the four research workers. `enrichment.ts` stays a pure parser; the I/O
9
9
  * lives here.
10
10
  *
11
- * There were TWO copies of this assembly: {@link gatherExternalContext} (the
12
- * research phase, raw workers) and an 87-line inline block in `phaseAutoAnswer`
13
- * (the grill auto-answer, focused workers). They agreed on everything that
14
- * shows up in the output the 8-step shape, the "npm blocks lead" ordering,
15
- * the `### docs:` / `### url:` headings, the service loop's `no_key` / `error`
16
- * handling, the block terminator — and disagreed only on POLICY. So the shape
17
- * is {@link buildExternalContext} once, the disagreements are
18
- * {@link ExternalContextPolicy}, and the worker variant is
19
- * {@link ExternalContextLookups} an adapter, expressible only since the
20
- * focused-extractor seam landed.
11
+ * TWO call paths share this assembly: the research phase via
12
+ * {@link gatherExternalContext} (raw workers) and the grill auto-answer via
13
+ * {@link buildExternalContext} directly (focused workers). Everything that shows
14
+ * up in the OUTPUT is identical between them the "npm blocks lead" ordering, the
15
+ * `### docs:` / `### url:` headings, the service loop's `no_key` / `error`
16
+ * handling, the trailing blank-line terminator — and they differ only on POLICY.
17
+ *
18
+ * So the shape lives here once, the differences are {@link ExternalContextPolicy},
19
+ * and the raw-vs-focused worker choice is {@link ExternalContextLookups}, an
20
+ * adapter the focused-extractor seam made expressible.
21
+ *
22
+ * Run against a mixed source, the emitted headings come out in exactly that order:
23
+ * `### npm:` then `### docs:` then `### url:` then `### service:`.
21
24
  */
22
25
  import { docsRaw } from '../workers/docs-core.js';
23
26
  import { fetchRaw } from '../workers/fetch-core.js';
@@ -28,8 +31,10 @@ import { formatServiceBlock, formatFreshnessSkippedBlock } from './service-block
28
31
  /** How much of a docs/url body survives into the block, for the raw-worker lookups. */
29
32
  const RAW_BODY_LIMIT = 4000;
30
33
  /**
31
- * Assemble the `EXTERNAL CONTEXT\n…\n\n` block for `source`, or `''` when there
32
- * is nothing to enrich (no targets, or every lookup failed).
34
+ * Assemble the `EXTERNAL CONTEXT\n…\n\n` block for `source`, or `''` when there is
35
+ * nothing to enrich no targets, or every lookup failed. Both were run: a source
36
+ * naming nothing returns `''`, and so does one whose only target is a service
37
+ * search that errored.
33
38
  */
34
39
  export async function buildExternalContext(source, deps, lookups, policy = {}) {
35
40
  const searchFn = lookups.search ?? defaultSearch;
@@ -13,11 +13,10 @@ export interface FailureClass {
13
13
  }
14
14
  export declare function classifyFailure(err: unknown, aborted: boolean): FailureClass;
15
15
  /**
16
- * Persist, flash and announce a failure and RETURN the classification.
16
+ * Persist, flash and announce a failure, and return the classification.
17
17
  *
18
- * It used to return `void`, so the name it had just computed died here and the
19
- * caller learned how the run ended by re-reading the task file's front matter and
20
- * narrowing it to a boolean. Handing the value back is what lets `TaskRunner.run`
21
- * say `RunEnd` instead.
18
+ * `TaskRunner.run` builds its `RunEnd` from the returned `state` and `reason`.
19
+ * The front-matter write here is what a later resume reads, not the channel
20
+ * this process uses to learn how the run ended.
22
21
  */
23
22
  export declare function handleFailure(err: unknown, ctx: ExtensionCommandContext, cwd: string, id: string, aborted: boolean): Promise<FailureClass>;
@@ -75,20 +75,19 @@ export function classifyFailure(err, aborted) {
75
75
  };
76
76
  }
77
77
  /**
78
- * Persist, flash and announce a failure and RETURN the classification.
78
+ * Persist, flash and announce a failure, and return the classification.
79
79
  *
80
- * It used to return `void`, so the name it had just computed died here and the
81
- * caller learned how the run ended by re-reading the task file's front matter and
82
- * narrowing it to a boolean. Handing the value back is what lets `TaskRunner.run`
83
- * say `RunEnd` instead.
80
+ * `TaskRunner.run` builds its `RunEnd` from the returned `state` and `reason`.
81
+ * The front-matter write here is what a later resume reads, not the channel
82
+ * this process uses to learn how the run ended.
84
83
  */
85
84
  export async function handleFailure(err, ctx, cwd, id, aborted) {
86
85
  const c = classifyFailure(err, aborted);
87
86
  await updateTaskFrontMatter(cwd, id, { state: c.state, reason: c.reason });
88
87
  flashTerminalWidget(ctx, c.state, id, c.flash);
89
88
  ctx.ui.notify(`${id} ${c.notify}`, c.level);
90
- // Mirror to remote viewers ctx.ui.notify is terminal-only, so without this
91
- // the remote view shows nothing when a task fails.
89
+ // Mirror to remote viewers. `ctx.ui.notify` reaches the terminal UI only, so
90
+ // without this call the remote view shows nothing when a task fails.
92
91
  publishLifecycleNotice(`${id} ${c.notify}`, c.level);
93
92
  return c;
94
93
  }
@@ -1,17 +1,21 @@
1
1
  /**
2
- * Project file inventory — runs `git ls-files` once per /task run so research
3
- * workers can skip their own discovery loops and jump straight to targeted
4
- * read/grep on known paths. Returns '' on failure (non-git repo, git missing,
5
- * timeout) so callers can fall back to the pre-inventory behavior.
2
+ * Project file inventory — `git ls-files`, capped, with the task directory
3
+ * stripped. `phaseResearch` computes it once and puts it in the header every
4
+ * research worker gets; `refineExistingFilesBlock` also uses it to pick the
5
+ * paths orientation pre-reads.
6
+ *
7
+ * Returns '' on failure: a non-git tree exits 128, and a missing binary reaches
8
+ * `runChildDefault`'s `error` handler as exit 1. Both callers treat '' as "no
9
+ * inventory" and carry on.
6
10
  */
7
11
  /**
8
- * Drop the committed task directory from the inventory. `git ls-files` lists
9
- * tracked files regardless of `.ignore`, so once tasks are committed they would
10
- * otherwise be handed to every research worker (and feed orientation). The user
11
- * wants tasks committable but invisible to workers and the local model, so we
12
- * strip `.pi-tasks/` here the inventory's single chokepoint. (`git ls-files`
13
- * always emits posix-style paths, so the forward-slash prefix is correct on all
14
- * platforms.)
12
+ * Drop the committed task directory from the inventory. `git ls-files` lists a
13
+ * TRACKED file even when `.gitignore` matches it confirmed against a real
14
+ * repo where `.pi-tasks/` is both ignored and committed so once tasks are
15
+ * committed they reach every research worker and feed orientation unless they
16
+ * are stripped here. This is the only filter on the inventory path.
17
+ *
18
+ * `git ls-files` prints forward slashes, so the prefix matches as written.
15
19
  */
16
20
  export declare function stripTasksDir(raw: string): string;
17
21
  /** Cap output to maxLines real (non-blank) paths; tag truncation when cut. */
@@ -1,20 +1,24 @@
1
1
  /**
2
- * Project file inventory — runs `git ls-files` once per /task run so research
3
- * workers can skip their own discovery loops and jump straight to targeted
4
- * read/grep on known paths. Returns '' on failure (non-git repo, git missing,
5
- * timeout) so callers can fall back to the pre-inventory behavior.
2
+ * Project file inventory — `git ls-files`, capped, with the task directory
3
+ * stripped. `phaseResearch` computes it once and puts it in the header every
4
+ * research worker gets; `refineExistingFilesBlock` also uses it to pick the
5
+ * paths orientation pre-reads.
6
+ *
7
+ * Returns '' on failure: a non-git tree exits 128, and a missing binary reaches
8
+ * `runChildDefault`'s `error` handler as exit 1. Both callers treat '' as "no
9
+ * inventory" and carry on.
6
10
  */
7
11
  import { makeGit } from '../shared/git-runner.js';
8
12
  import { TASKS_DIR_NAME } from './task-types.js';
9
13
  const DEFAULT_MAX_LINES = 2000;
10
14
  /**
11
- * Drop the committed task directory from the inventory. `git ls-files` lists
12
- * tracked files regardless of `.ignore`, so once tasks are committed they would
13
- * otherwise be handed to every research worker (and feed orientation). The user
14
- * wants tasks committable but invisible to workers and the local model, so we
15
- * strip `.pi-tasks/` here the inventory's single chokepoint. (`git ls-files`
16
- * always emits posix-style paths, so the forward-slash prefix is correct on all
17
- * platforms.)
15
+ * Drop the committed task directory from the inventory. `git ls-files` lists a
16
+ * TRACKED file even when `.gitignore` matches it confirmed against a real
17
+ * repo where `.pi-tasks/` is both ignored and committed so once tasks are
18
+ * committed they reach every research worker and feed orientation unless they
19
+ * are stripped here. This is the only filter on the inventory path.
20
+ *
21
+ * `git ls-files` prints forward slashes, so the prefix matches as written.
18
22
  */
19
23
  export function stripTasksDir(raw) {
20
24
  const prefix = `${TASKS_DIR_NAME}/`;
@@ -24,19 +28,18 @@ export function stripTasksDir(raw) {
24
28
  .join('\n');
25
29
  }
26
30
  /**
27
- * `git ls-files`, or '' on ANY failure — non-git tree, missing git, cancelled run.
28
- * The empty string is the caller's fall-back-to-pre-inventory signal, so every
29
- * unhappy path has to collapse to it.
31
+ * `git ls-files`, or '' on ANY failure — non-git tree, missing git, cancelled
32
+ * run. '' is the signal both callers branch on, so every unhappy path has to
33
+ * collapse to it.
30
34
  *
31
- * Runs on the shared GitRunner (`shared/git-runner.ts`), which brings the abort
32
- * discipline this used to hand-roll: the listener is detached when the child
33
- * settles normally, so a run-long orchestrator signal does not accumulate one
34
- * retained child per invocation (GitHub issue #9).
35
+ * Runs on the shared GitRunner, whose child detaches its abort listener when it
36
+ * settles: one AbortController is shared across a whole run, so a listener left
37
+ * attached per call would retain each finished child.
35
38
  *
36
- * The `signal.aborted` check is what preserves this function's OWN contract on
37
- * cancellation. A killed child closes with a null exit code, which the runner
38
- * reports as 0 — so without it a cancelled run would hand back a truncated
39
- * inventory as if it were complete, where the hand-rolled version returned ''.
39
+ * The `signal.aborted` check is what holds the contract on cancellation. A
40
+ * killed child closes with a null exit code and `runChild` reports `code ?? 0`,
41
+ * so without the check a cancelled run would return partial stdout as if the
42
+ * listing were complete.
40
43
  */
41
44
  async function runGitLsFiles(cwd, signal) {
42
45
  const git = makeGit(cwd, signal);