@hominis/fireforge 0.45.0 → 0.46.1

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 (662) hide show
  1. package/CHANGELOG.md +409 -446
  2. package/dist/bin/fireforge.d.ts +1 -1
  3. package/dist/bin/fireforge.js +21 -15
  4. package/dist/build-info.json +4 -4
  5. package/dist/src/cli-usage-error.d.ts +46 -0
  6. package/dist/src/cli-usage-error.js +81 -0
  7. package/dist/src/cli.d.ts +7 -2
  8. package/dist/src/cli.js +47 -47
  9. package/dist/src/commands/bootstrap-checks.js +2 -1
  10. package/dist/src/commands/bootstrap.js +3 -4
  11. package/dist/src/commands/build.js +27 -17
  12. package/dist/src/commands/config.js +9 -9
  13. package/dist/src/commands/destructive-decision.d.ts +19 -0
  14. package/dist/src/commands/destructive-decision.js +31 -0
  15. package/dist/src/commands/discard.js +5 -5
  16. package/dist/src/commands/doctor-check-core.d.ts +4 -10
  17. package/dist/src/commands/doctor-check-core.js +0 -8
  18. package/dist/src/commands/doctor-external-toolchains.js +2 -2
  19. package/dist/src/commands/doctor-furnace-config-sync.d.ts +2 -2
  20. package/dist/src/commands/doctor-furnace-config-sync.js +20 -20
  21. package/dist/src/commands/doctor-furnace-jar.d.ts +1 -1
  22. package/dist/src/commands/doctor-furnace-jar.js +1 -1
  23. package/dist/src/commands/doctor-furnace.js +22 -22
  24. package/dist/src/commands/doctor-orphaned-harness.d.ts +10 -17
  25. package/dist/src/commands/doctor-orphaned-harness.js +14 -23
  26. package/dist/src/commands/doctor-patch-manifest.d.ts +2 -1
  27. package/dist/src/commands/doctor-patch-manifest.js +7 -6
  28. package/dist/src/commands/doctor-post-rebase-audit.js +3 -3
  29. package/dist/src/commands/doctor-source-pin.d.ts +12 -12
  30. package/dist/src/commands/doctor-source-pin.js +14 -14
  31. package/dist/src/commands/doctor-working-tree.d.ts +3 -3
  32. package/dist/src/commands/doctor-working-tree.js +3 -3
  33. package/dist/src/commands/doctor.d.ts +3 -1
  34. package/dist/src/commands/doctor.js +15 -16
  35. package/dist/src/commands/download.js +50 -37
  36. package/dist/src/commands/export-all.js +29 -12
  37. package/dist/src/commands/export-flow.d.ts +5 -5
  38. package/dist/src/commands/export-flow.js +29 -59
  39. package/dist/src/commands/export-placement-conflicts.d.ts +3 -3
  40. package/dist/src/commands/export-placement-conflicts.js +12 -12
  41. package/dist/src/commands/export-placement-gate.d.ts +2 -2
  42. package/dist/src/commands/export-placement-gate.js +7 -13
  43. package/dist/src/commands/export-placement-policy.d.ts +1 -1
  44. package/dist/src/commands/export-placement-policy.js +4 -6
  45. package/dist/src/commands/export-shared.d.ts +51 -32
  46. package/dist/src/commands/export-shared.js +17 -32
  47. package/dist/src/commands/export.js +14 -5
  48. package/dist/src/commands/furnace/apply.js +16 -16
  49. package/dist/src/commands/furnace/authoring-config.d.ts +13 -0
  50. package/dist/src/commands/furnace/authoring-config.js +19 -0
  51. package/dist/src/commands/furnace/chrome-doc-remove.d.ts +1 -1
  52. package/dist/src/commands/furnace/chrome-doc-remove.js +2 -2
  53. package/dist/src/commands/furnace/chrome-doc-templates.d.ts +14 -14
  54. package/dist/src/commands/furnace/chrome-doc-templates.js +17 -17
  55. package/dist/src/commands/furnace/chrome-doc-tests.d.ts +2 -2
  56. package/dist/src/commands/furnace/chrome-doc-tests.js +4 -4
  57. package/dist/src/commands/furnace/chrome-doc.d.ts +8 -8
  58. package/dist/src/commands/furnace/chrome-doc.js +18 -18
  59. package/dist/src/commands/furnace/create-browser-test.d.ts +1 -1
  60. package/dist/src/commands/furnace/create-browser-test.js +7 -12
  61. package/dist/src/commands/furnace/create-dry-run.d.ts +4 -4
  62. package/dist/src/commands/furnace/create-dry-run.js +6 -9
  63. package/dist/src/commands/furnace/create-features.d.ts +2 -2
  64. package/dist/src/commands/furnace/create-features.js +2 -2
  65. package/dist/src/commands/furnace/create-mochikit.d.ts +4 -4
  66. package/dist/src/commands/furnace/create-mochikit.js +7 -7
  67. package/dist/src/commands/furnace/create-templates.d.ts +31 -15
  68. package/dist/src/commands/furnace/create-templates.js +20 -19
  69. package/dist/src/commands/furnace/create-xpcshell.d.ts +5 -5
  70. package/dist/src/commands/furnace/create-xpcshell.js +8 -8
  71. package/dist/src/commands/furnace/create.d.ts +1 -1
  72. package/dist/src/commands/furnace/create.js +35 -29
  73. package/dist/src/commands/furnace/deploy.js +15 -6
  74. package/dist/src/commands/furnace/diff.js +7 -7
  75. package/dist/src/commands/furnace/index.js +1 -1
  76. package/dist/src/commands/furnace/init.js +17 -16
  77. package/dist/src/commands/furnace/list.js +2 -2
  78. package/dist/src/commands/furnace/override.d.ts +1 -1
  79. package/dist/src/commands/furnace/override.js +43 -34
  80. package/dist/src/commands/furnace/preview.js +17 -17
  81. package/dist/src/commands/furnace/refresh.js +15 -7
  82. package/dist/src/commands/furnace/remove-mutations.d.ts +9 -10
  83. package/dist/src/commands/furnace/remove-mutations.js +19 -19
  84. package/dist/src/commands/furnace/remove-state.d.ts +1 -1
  85. package/dist/src/commands/furnace/remove-state.js +1 -1
  86. package/dist/src/commands/furnace/remove.js +4 -8
  87. package/dist/src/commands/furnace/rename-browser-test.js +10 -15
  88. package/dist/src/commands/furnace/rename-xpcshell.d.ts +2 -2
  89. package/dist/src/commands/furnace/rename-xpcshell.js +3 -3
  90. package/dist/src/commands/furnace/rename.js +36 -36
  91. package/dist/src/commands/furnace/scan.js +3 -3
  92. package/dist/src/commands/furnace/status.js +19 -16
  93. package/dist/src/commands/furnace/sync.js +6 -6
  94. package/dist/src/commands/furnace/test-file-name.d.ts +28 -0
  95. package/dist/src/commands/furnace/test-file-name.js +39 -0
  96. package/dist/src/commands/furnace/validate.js +11 -12
  97. package/dist/src/commands/furnace/validation-output.d.ts +21 -9
  98. package/dist/src/commands/furnace/validation-output.js +3 -8
  99. package/dist/src/commands/import.js +22 -29
  100. package/dist/src/commands/lint-per-patch.d.ts +2 -2
  101. package/dist/src/commands/lint-per-patch.js +27 -12
  102. package/dist/src/commands/lint-per-run-checkjs.d.ts +14 -15
  103. package/dist/src/commands/lint-per-run-checkjs.js +14 -15
  104. package/dist/src/commands/lint-report.d.ts +3 -3
  105. package/dist/src/commands/lint-report.js +4 -4
  106. package/dist/src/commands/lint.d.ts +5 -4
  107. package/dist/src/commands/lint.js +36 -36
  108. package/dist/src/commands/manifest.d.ts +4 -4
  109. package/dist/src/commands/manifest.js +1 -1
  110. package/dist/src/commands/package.js +4 -6
  111. package/dist/src/commands/patch/compact.d.ts +2 -2
  112. package/dist/src/commands/patch/compact.js +19 -20
  113. package/dist/src/commands/patch/delete.d.ts +1 -1
  114. package/dist/src/commands/patch/delete.js +23 -33
  115. package/dist/src/commands/patch/entry-projection.d.ts +13 -0
  116. package/dist/src/commands/patch/entry-projection.js +24 -0
  117. package/dist/src/commands/patch/lint-ignore.d.ts +3 -12
  118. package/dist/src/commands/patch/lint-ignore.js +33 -44
  119. package/dist/src/commands/patch/move-files-create.d.ts +2 -2
  120. package/dist/src/commands/patch/move-files-create.js +29 -15
  121. package/dist/src/commands/patch/move-files-into.d.ts +2 -2
  122. package/dist/src/commands/patch/move-files-into.js +41 -37
  123. package/dist/src/commands/patch/move-files.js +5 -14
  124. package/dist/src/commands/patch/patch-context.d.ts +1 -1
  125. package/dist/src/commands/patch/rename.d.ts +4 -4
  126. package/dist/src/commands/patch/rename.js +35 -49
  127. package/dist/src/commands/patch/reorder.js +35 -48
  128. package/dist/src/commands/patch/split-plan.d.ts +7 -8
  129. package/dist/src/commands/patch/split-plan.js +10 -13
  130. package/dist/src/commands/patch/split.d.ts +2 -2
  131. package/dist/src/commands/patch/split.js +50 -48
  132. package/dist/src/commands/patch/staged-dependency-validate.d.ts +1 -1
  133. package/dist/src/commands/patch/staged-dependency-validate.js +3 -3
  134. package/dist/src/commands/patch/staged-dependency.d.ts +1 -1
  135. package/dist/src/commands/patch/staged-dependency.js +22 -28
  136. package/dist/src/commands/patch/tier.d.ts +2 -2
  137. package/dist/src/commands/patch/tier.js +20 -30
  138. package/dist/src/commands/patch-rename-map.d.ts +19 -0
  139. package/dist/src/commands/patch-rename-map.js +36 -0
  140. package/dist/src/commands/pending-resolution.d.ts +15 -0
  141. package/dist/src/commands/pending-resolution.js +25 -0
  142. package/dist/src/commands/re-export-adjacent.d.ts +25 -3
  143. package/dist/src/commands/re-export-adjacent.js +40 -24
  144. package/dist/src/commands/re-export-bulk-scan.d.ts +3 -3
  145. package/dist/src/commands/re-export-bulk-scan.js +23 -27
  146. package/dist/src/commands/re-export-drift.d.ts +10 -10
  147. package/dist/src/commands/re-export-drift.js +33 -33
  148. package/dist/src/commands/re-export-files.d.ts +2 -3
  149. package/dist/src/commands/re-export-files.js +52 -44
  150. package/dist/src/commands/re-export-lint.d.ts +29 -30
  151. package/dist/src/commands/re-export-lint.js +36 -29
  152. package/dist/src/commands/re-export-options.d.ts +1 -1
  153. package/dist/src/commands/re-export-options.js +1 -1
  154. package/dist/src/commands/re-export-register.d.ts +1 -1
  155. package/dist/src/commands/re-export-register.js +1 -1
  156. package/dist/src/commands/re-export-scan.d.ts +1 -1
  157. package/dist/src/commands/re-export-scan.js +12 -9
  158. package/dist/src/commands/re-export-single.d.ts +23 -4
  159. package/dist/src/commands/re-export-single.js +39 -31
  160. package/dist/src/commands/re-export.js +35 -17
  161. package/dist/src/commands/rebase/abort.js +9 -14
  162. package/dist/src/commands/rebase/continue.js +20 -19
  163. package/dist/src/commands/rebase/index.d.ts +1 -1
  164. package/dist/src/commands/rebase/index.js +5 -5
  165. package/dist/src/commands/rebase/patch-loop.d.ts +2 -2
  166. package/dist/src/commands/rebase/patch-loop.js +20 -24
  167. package/dist/src/commands/register.js +5 -5
  168. package/dist/src/commands/reset.js +1 -1
  169. package/dist/src/commands/resolve.d.ts +2 -2
  170. package/dist/src/commands/resolve.js +21 -13
  171. package/dist/src/commands/run.d.ts +0 -13
  172. package/dist/src/commands/run.js +38 -51
  173. package/dist/src/commands/setup-support.d.ts +16 -4
  174. package/dist/src/commands/setup-support.js +20 -20
  175. package/dist/src/commands/setup.js +4 -10
  176. package/dist/src/commands/source.js +9 -2
  177. package/dist/src/commands/status-check.d.ts +3 -3
  178. package/dist/src/commands/status-check.js +6 -6
  179. package/dist/src/commands/status-json.d.ts +14 -13
  180. package/dist/src/commands/status-json.js +9 -8
  181. package/dist/src/commands/status-output.d.ts +3 -3
  182. package/dist/src/commands/status-output.js +5 -5
  183. package/dist/src/commands/status-ownership.d.ts +3 -3
  184. package/dist/src/commands/status-ownership.js +3 -3
  185. package/dist/src/commands/status.js +25 -26
  186. package/dist/src/commands/test-build-phase.d.ts +3 -3
  187. package/dist/src/commands/test-build-phase.js +48 -24
  188. package/dist/src/commands/test-diagnose.d.ts +1 -1
  189. package/dist/src/commands/test-diagnose.js +20 -20
  190. package/dist/src/commands/test-modes.d.ts +4 -4
  191. package/dist/src/commands/test-modes.js +4 -5
  192. package/dist/src/commands/test-register.js +5 -3
  193. package/dist/src/commands/test-run.d.ts +11 -11
  194. package/dist/src/commands/test-run.js +40 -33
  195. package/dist/src/commands/test-stale-gate.d.ts +12 -12
  196. package/dist/src/commands/test-stale-gate.js +17 -17
  197. package/dist/src/commands/test-verdict.d.ts +19 -5
  198. package/dist/src/commands/test-verdict.js +26 -11
  199. package/dist/src/commands/test.d.ts +3 -3
  200. package/dist/src/commands/test.js +73 -36
  201. package/dist/src/commands/token-coverage.js +3 -3
  202. package/dist/src/commands/token-list.d.ts +26 -0
  203. package/dist/src/commands/token-list.js +153 -0
  204. package/dist/src/commands/token.js +26 -10
  205. package/dist/src/commands/tree.js +26 -21
  206. package/dist/src/commands/typecheck.d.ts +6 -6
  207. package/dist/src/commands/typecheck.js +16 -16
  208. package/dist/src/commands/verify.d.ts +3 -3
  209. package/dist/src/commands/verify.js +10 -10
  210. package/dist/src/commands/watch.js +11 -11
  211. package/dist/src/commands/wire.js +17 -16
  212. package/dist/src/core/ast-utils.d.ts +7 -7
  213. package/dist/src/core/ast-utils.js +8 -8
  214. package/dist/src/core/branding.d.ts +5 -12
  215. package/dist/src/core/branding.js +6 -5
  216. package/dist/src/core/browser-wire.d.ts +1 -1
  217. package/dist/src/core/browser-wire.js +10 -7
  218. package/dist/src/core/build-audit-platform.d.ts +32 -3
  219. package/dist/src/core/build-audit-platform.js +153 -13
  220. package/dist/src/core/build-audit-registration.d.ts +5 -5
  221. package/dist/src/core/build-audit-registration.js +10 -9
  222. package/dist/src/core/build-audit-resolve.d.ts +5 -5
  223. package/dist/src/core/build-audit-resolve.js +6 -6
  224. package/dist/src/core/build-audit-skip.d.ts +57 -0
  225. package/dist/src/core/build-audit-skip.js +112 -0
  226. package/dist/src/core/build-audit-transforms.d.ts +2 -2
  227. package/dist/src/core/build-audit-transforms.js +3 -3
  228. package/dist/src/core/build-audit.d.ts +21 -8
  229. package/dist/src/core/build-audit.js +142 -40
  230. package/dist/src/core/build-baseline-types.d.ts +19 -18
  231. package/dist/src/core/build-baseline-types.js +1 -1
  232. package/dist/src/core/build-baseline.d.ts +48 -31
  233. package/dist/src/core/build-baseline.js +20 -43
  234. package/dist/src/core/build-jar-escalation.d.ts +8 -8
  235. package/dist/src/core/build-jar-escalation.js +18 -17
  236. package/dist/src/core/build-overwrite-guard.d.ts +4 -4
  237. package/dist/src/core/build-overwrite-guard.js +14 -14
  238. package/dist/src/core/build-prepare.d.ts +4 -12
  239. package/dist/src/core/build-prepare.js +22 -26
  240. package/dist/src/core/config-mutate.js +4 -4
  241. package/dist/src/core/config-paths.d.ts +2 -6
  242. package/dist/src/core/config-paths.js +4 -2
  243. package/dist/src/core/config-state.d.ts +0 -6
  244. package/dist/src/core/config-state.js +3 -21
  245. package/dist/src/core/config-validate-build-audit.d.ts +8 -0
  246. package/dist/src/core/config-validate-build-audit.js +80 -0
  247. package/dist/src/core/config-validate-file-size.d.ts +1 -1
  248. package/dist/src/core/config-validate-file-size.js +3 -3
  249. package/dist/src/core/config-validate-patch-policy.d.ts +2 -2
  250. package/dist/src/core/config-validate-patch-policy.js +3 -3
  251. package/dist/src/core/config-validate-test-toolchains.d.ts +2 -2
  252. package/dist/src/core/config-validate-test-toolchains.js +4 -5
  253. package/dist/src/core/config-validate.js +22 -12
  254. package/dist/src/core/config.d.ts +12 -12
  255. package/dist/src/core/config.js +21 -25
  256. package/dist/src/core/coverage-extend.d.ts +16 -16
  257. package/dist/src/core/coverage-extend.js +20 -20
  258. package/dist/src/core/destructive.d.ts +14 -14
  259. package/dist/src/core/destructive.js +9 -9
  260. package/dist/src/core/diff-hunks.d.ts +2 -2
  261. package/dist/src/core/diff-hunks.js +7 -7
  262. package/dist/src/core/discard-baseline.d.ts +10 -10
  263. package/dist/src/core/discard-baseline.js +22 -23
  264. package/dist/src/core/display-state.d.ts +11 -11
  265. package/dist/src/core/display-state.js +12 -12
  266. package/dist/src/core/engine-changes.d.ts +2 -2
  267. package/dist/src/core/engine-changes.js +2 -2
  268. package/dist/src/core/engine-precondition.d.ts +5 -13
  269. package/dist/src/core/engine-precondition.js +5 -10
  270. package/dist/src/core/engine-session-lock.d.ts +18 -18
  271. package/dist/src/core/engine-session-lock.js +50 -54
  272. package/dist/src/core/export-moved-code-shape.d.ts +7 -7
  273. package/dist/src/core/export-moved-code-shape.js +10 -10
  274. package/dist/src/core/file-lock-owner.d.ts +103 -0
  275. package/dist/src/core/file-lock-owner.js +259 -0
  276. package/dist/src/core/file-lock.d.ts +14 -19
  277. package/dist/src/core/file-lock.js +90 -128
  278. package/dist/src/core/firefox-cache.d.ts +13 -1
  279. package/dist/src/core/firefox-cache.js +61 -36
  280. package/dist/src/core/firefox-download.d.ts +15 -0
  281. package/dist/src/core/firefox-download.js +38 -22
  282. package/dist/src/core/firefox-extract.d.ts +8 -7
  283. package/dist/src/core/firefox-extract.js +45 -27
  284. package/dist/src/core/firefox.d.ts +34 -36
  285. package/dist/src/core/firefox.js +13 -44
  286. package/dist/src/core/furnace-apply-dry-run.d.ts +1 -6
  287. package/dist/src/core/furnace-apply-dry-run.js +2 -8
  288. package/dist/src/core/furnace-apply-ftl.d.ts +5 -5
  289. package/dist/src/core/furnace-apply-ftl.js +8 -8
  290. package/dist/src/core/furnace-apply-helpers.d.ts +9 -20
  291. package/dist/src/core/furnace-apply-helpers.js +28 -39
  292. package/dist/src/core/furnace-apply-output.js +1 -1
  293. package/dist/src/core/furnace-apply-overwrite-warn.d.ts +9 -9
  294. package/dist/src/core/furnace-apply-overwrite-warn.js +13 -11
  295. package/dist/src/core/furnace-apply-undeploy-actions.d.ts +1 -1
  296. package/dist/src/core/furnace-apply-undeploy-actions.js +1 -1
  297. package/dist/src/core/furnace-apply.d.ts +4 -4
  298. package/dist/src/core/furnace-apply.js +50 -29
  299. package/dist/src/core/furnace-checksum-utils.d.ts +5 -5
  300. package/dist/src/core/furnace-checksum-utils.js +5 -5
  301. package/dist/src/core/furnace-config-custom.d.ts +1 -1
  302. package/dist/src/core/furnace-config-custom.js +2 -2
  303. package/dist/src/core/furnace-config-order.js +1 -1
  304. package/dist/src/core/furnace-config-tokens.d.ts +3 -3
  305. package/dist/src/core/furnace-config-tokens.js +3 -3
  306. package/dist/src/core/furnace-config-validate.js +2 -2
  307. package/dist/src/core/furnace-config.d.ts +5 -5
  308. package/dist/src/core/furnace-config.js +40 -53
  309. package/dist/src/core/furnace-constants.d.ts +6 -6
  310. package/dist/src/core/furnace-constants.js +9 -8
  311. package/dist/src/core/furnace-css-fragments.d.ts +6 -6
  312. package/dist/src/core/furnace-css-fragments.js +11 -11
  313. package/dist/src/core/furnace-dir-entry.d.ts +20 -0
  314. package/dist/src/core/furnace-dir-entry.js +21 -0
  315. package/dist/src/core/furnace-jsconfig.d.ts +7 -7
  316. package/dist/src/core/furnace-jsconfig.js +22 -20
  317. package/dist/src/core/furnace-operation.d.ts +22 -19
  318. package/dist/src/core/furnace-operation.js +38 -34
  319. package/dist/src/core/furnace-precondition.d.ts +10 -10
  320. package/dist/src/core/furnace-precondition.js +8 -8
  321. package/dist/src/core/furnace-refresh.d.ts +18 -6
  322. package/dist/src/core/furnace-refresh.js +5 -8
  323. package/dist/src/core/furnace-registration-ast.d.ts +2 -3
  324. package/dist/src/core/furnace-registration-ast.js +9 -12
  325. package/dist/src/core/furnace-registration-remove.d.ts +4 -4
  326. package/dist/src/core/furnace-registration-remove.js +6 -6
  327. package/dist/src/core/furnace-registration-validate.d.ts +2 -2
  328. package/dist/src/core/furnace-registration-validate.js +2 -2
  329. package/dist/src/core/furnace-registration.d.ts +7 -6
  330. package/dist/src/core/furnace-registration.js +29 -36
  331. package/dist/src/core/furnace-rollback.d.ts +1 -1
  332. package/dist/src/core/furnace-rollback.js +5 -5
  333. package/dist/src/core/furnace-scanner.js +3 -6
  334. package/dist/src/core/furnace-stale-export.d.ts +17 -16
  335. package/dist/src/core/furnace-stale-export.js +16 -15
  336. package/dist/src/core/furnace-staleness.d.ts +2 -2
  337. package/dist/src/core/furnace-staleness.js +2 -2
  338. package/dist/src/core/furnace-state-persist.d.ts +12 -12
  339. package/dist/src/core/furnace-state-persist.js +10 -10
  340. package/dist/src/core/furnace-step-errors.d.ts +6 -6
  341. package/dist/src/core/furnace-step-errors.js +6 -6
  342. package/dist/src/core/furnace-validate-accessibility.js +14 -14
  343. package/dist/src/core/furnace-validate-compatibility.js +9 -9
  344. package/dist/src/core/furnace-validate-registration.d.ts +2 -2
  345. package/dist/src/core/furnace-validate-registration.js +18 -20
  346. package/dist/src/core/furnace-validate-structure.d.ts +1 -1
  347. package/dist/src/core/furnace-validate-structure.js +4 -4
  348. package/dist/src/core/furnace-validate.js +9 -9
  349. package/dist/src/core/furnace-version-drift.d.ts +5 -5
  350. package/dist/src/core/furnace-version-drift.js +5 -5
  351. package/dist/src/core/git-base.d.ts +6 -4
  352. package/dist/src/core/git-base.js +29 -7
  353. package/dist/src/core/git-diff-new-file.d.ts +40 -0
  354. package/dist/src/core/git-diff-new-file.js +119 -0
  355. package/dist/src/core/git-diff.d.ts +13 -13
  356. package/dist/src/core/git-diff.js +121 -189
  357. package/dist/src/core/git-file-ops.d.ts +6 -13
  358. package/dist/src/core/git-file-ops.js +11 -35
  359. package/dist/src/core/git-readonly-index.d.ts +12 -14
  360. package/dist/src/core/git-readonly-index.js +12 -16
  361. package/dist/src/core/git-status.d.ts +9 -2
  362. package/dist/src/core/git-status.js +23 -11
  363. package/dist/src/core/git.d.ts +3 -9
  364. package/dist/src/core/git.js +28 -57
  365. package/dist/src/core/harness-orphans.d.ts +17 -17
  366. package/dist/src/core/harness-orphans.js +28 -27
  367. package/dist/src/core/history-log.d.ts +19 -0
  368. package/dist/src/core/history-log.js +29 -0
  369. package/dist/src/core/license-headers.d.ts +19 -18
  370. package/dist/src/core/license-headers.js +29 -28
  371. package/dist/src/core/mach-build-artifacts.d.ts +21 -21
  372. package/dist/src/core/mach-build-artifacts.js +23 -23
  373. package/dist/src/core/mach-error-hints.d.ts +5 -10
  374. package/dist/src/core/mach-error-hints.js +14 -14
  375. package/dist/src/core/mach-known-noise-filter.d.ts +42 -38
  376. package/dist/src/core/mach-known-noise-filter.js +57 -56
  377. package/dist/src/core/mach-mozconfig.d.ts +6 -6
  378. package/dist/src/core/mach-mozconfig.js +17 -16
  379. package/dist/src/core/mach-python.d.ts +3 -0
  380. package/dist/src/core/mach-python.js +13 -7
  381. package/dist/src/core/mach-resource-shim.d.ts +24 -12
  382. package/dist/src/core/mach-resource-shim.js +124 -21
  383. package/dist/src/core/mach.d.ts +59 -73
  384. package/dist/src/core/mach.js +47 -115
  385. package/dist/src/core/marionette-port.d.ts +15 -30
  386. package/dist/src/core/marionette-port.js +46 -89
  387. package/dist/src/core/marionette-preflight.d.ts +6 -6
  388. package/dist/src/core/marionette-preflight.js +32 -50
  389. package/dist/src/core/markdown-table.d.ts +9 -9
  390. package/dist/src/core/markdown-table.js +14 -14
  391. package/dist/src/core/mochitest-server-port.d.ts +8 -8
  392. package/dist/src/core/mochitest-server-port.js +17 -17
  393. package/dist/src/core/module-resolution-preflight.d.ts +8 -8
  394. package/dist/src/core/module-resolution-preflight.js +11 -11
  395. package/dist/src/core/moz-manifest-helpers.d.ts +7 -7
  396. package/dist/src/core/moz-manifest-helpers.js +7 -7
  397. package/dist/src/core/moz-manifest-register.d.ts +1 -1
  398. package/dist/src/core/moz-manifest-register.js +2 -2
  399. package/dist/src/core/moz-manifest-rules.js +46 -42
  400. package/dist/src/core/moz-manifest-tokenizers.js +1 -1
  401. package/dist/src/core/ownership-table.d.ts +5 -5
  402. package/dist/src/core/ownership-table.js +7 -7
  403. package/dist/src/core/parser-fallback.d.ts +3 -3
  404. package/dist/src/core/parser-fallback.js +3 -3
  405. package/dist/src/core/patch-apply-fuzz.d.ts +5 -5
  406. package/dist/src/core/patch-apply-fuzz.js +13 -13
  407. package/dist/src/core/patch-apply.d.ts +13 -14
  408. package/dist/src/core/patch-apply.js +36 -42
  409. package/dist/src/core/patch-export-coverage.d.ts +0 -9
  410. package/dist/src/core/patch-export-coverage.js +1 -30
  411. package/dist/src/core/patch-export-update.d.ts +21 -4
  412. package/dist/src/core/patch-export-update.js +7 -6
  413. package/dist/src/core/patch-export.d.ts +20 -30
  414. package/dist/src/core/patch-export.js +55 -77
  415. package/dist/src/core/patch-files.d.ts +0 -4
  416. package/dist/src/core/patch-files.js +0 -11
  417. package/dist/src/core/patch-identifier-suggest.d.ts +1 -1
  418. package/dist/src/core/patch-identifier-suggest.js +4 -4
  419. package/dist/src/core/patch-lint-binary.d.ts +12 -18
  420. package/dist/src/core/patch-lint-cache.d.ts +18 -2
  421. package/dist/src/core/patch-lint-cache.js +16 -19
  422. package/dist/src/core/patch-lint-checkjs.d.ts +55 -38
  423. package/dist/src/core/patch-lint-checkjs.js +78 -64
  424. package/dist/src/core/patch-lint-chrome-jsdoc.d.ts +8 -9
  425. package/dist/src/core/patch-lint-chrome-jsdoc.js +10 -11
  426. package/dist/src/core/patch-lint-creators.d.ts +5 -9
  427. package/dist/src/core/patch-lint-creators.js +3 -3
  428. package/dist/src/core/patch-lint-cross.d.ts +27 -19
  429. package/dist/src/core/patch-lint-cross.js +67 -110
  430. package/dist/src/core/patch-lint-css.d.ts +1 -1
  431. package/dist/src/core/patch-lint-css.js +15 -11
  432. package/dist/src/core/patch-lint-diff-tag.d.ts +5 -5
  433. package/dist/src/core/patch-lint-diff-tag.js +5 -5
  434. package/dist/src/core/patch-lint-diff.d.ts +4 -4
  435. package/dist/src/core/patch-lint-diff.js +4 -4
  436. package/dist/src/core/patch-lint-file-size.d.ts +3 -3
  437. package/dist/src/core/patch-lint-file-size.js +6 -6
  438. package/dist/src/core/patch-lint-forward-registration.d.ts +58 -0
  439. package/dist/src/core/patch-lint-forward-registration.js +210 -0
  440. package/dist/src/core/patch-lint-jsdoc.d.ts +2 -2
  441. package/dist/src/core/patch-lint-jsdoc.js +46 -46
  442. package/dist/src/core/patch-lint-module-registration.d.ts +3 -9
  443. package/dist/src/core/patch-lint-module-registration.js +1 -1
  444. package/dist/src/core/patch-lint-mozbuild.d.ts +1 -1
  445. package/dist/src/core/patch-lint-mozbuild.js +10 -10
  446. package/dist/src/core/patch-lint-observer.d.ts +3 -3
  447. package/dist/src/core/patch-lint-observer.js +7 -7
  448. package/dist/src/core/patch-lint-ownership.d.ts +6 -6
  449. package/dist/src/core/patch-lint-ownership.js +6 -6
  450. package/dist/src/core/patch-lint-prettier.d.ts +6 -6
  451. package/dist/src/core/patch-lint-prettier.js +7 -7
  452. package/dist/src/core/patch-lint-queue-types.d.ts +60 -0
  453. package/dist/src/core/patch-lint-queue-types.js +12 -0
  454. package/dist/src/core/patch-lint-staged-registration.d.ts +61 -0
  455. package/dist/src/core/patch-lint-staged-registration.js +90 -0
  456. package/dist/src/core/patch-lint-unmanaged-companion.d.ts +23 -23
  457. package/dist/src/core/patch-lint-unmanaged-companion.js +26 -26
  458. package/dist/src/core/patch-lint.d.ts +41 -35
  459. package/dist/src/core/patch-lint.js +52 -49
  460. package/dist/src/core/patch-lock.d.ts +1 -1
  461. package/dist/src/core/patch-lock.js +11 -11
  462. package/dist/src/core/patch-manifest-consistency.d.ts +7 -7
  463. package/dist/src/core/patch-manifest-consistency.js +16 -17
  464. package/dist/src/core/patch-manifest-files-affected.d.ts +1 -1
  465. package/dist/src/core/patch-manifest-files-affected.js +3 -3
  466. package/dist/src/core/patch-manifest-io.d.ts +14 -14
  467. package/dist/src/core/patch-manifest-io.js +35 -34
  468. package/dist/src/core/patch-manifest-query.d.ts +1 -1
  469. package/dist/src/core/patch-manifest-query.js +4 -4
  470. package/dist/src/core/patch-manifest-resolve.d.ts +5 -5
  471. package/dist/src/core/patch-manifest-resolve.js +7 -7
  472. package/dist/src/core/patch-manifest-validate.js +3 -3
  473. package/dist/src/core/patch-manifest.d.ts +2 -2
  474. package/dist/src/core/patch-manifest.js +2 -2
  475. package/dist/src/core/patch-parse.d.ts +32 -21
  476. package/dist/src/core/patch-parse.js +40 -15
  477. package/dist/src/core/patch-policy.js +15 -27
  478. package/dist/src/core/patch-registration-refs.d.ts +4 -4
  479. package/dist/src/core/patch-registration-refs.js +7 -7
  480. package/dist/src/core/patch-source-metadata.d.ts +1 -3
  481. package/dist/src/core/patch-source-metadata.js +0 -4
  482. package/dist/src/core/patch-transform.d.ts +8 -16
  483. package/dist/src/core/patch-transform.js +13 -23
  484. package/dist/src/core/process-cpu-time.d.ts +1 -1
  485. package/dist/src/core/process-cpu-time.js +6 -6
  486. package/dist/src/core/rebase-session.d.ts +9 -15
  487. package/dist/src/core/rebase-session.js +13 -25
  488. package/dist/src/core/register-browser-content.js +3 -2
  489. package/dist/src/core/register-browser-test.js +2 -1
  490. package/dist/src/core/register-module.js +2 -1
  491. package/dist/src/core/register-result.d.ts +1 -1
  492. package/dist/src/core/register-result.js +1 -1
  493. package/dist/src/core/register-scaffold.d.ts +2 -2
  494. package/dist/src/core/register-scaffold.js +8 -7
  495. package/dist/src/core/register-shared-css.d.ts +3 -3
  496. package/dist/src/core/register-shared-css.js +6 -5
  497. package/dist/src/core/register-xpcshell-test.d.ts +2 -2
  498. package/dist/src/core/register-xpcshell-test.js +2 -2
  499. package/dist/src/core/run-log-redact.d.ts +38 -0
  500. package/dist/src/core/run-log-redact.js +69 -0
  501. package/dist/src/core/run-log.d.ts +21 -10
  502. package/dist/src/core/run-log.js +76 -27
  503. package/dist/src/core/shared-ftl.d.ts +2 -2
  504. package/dist/src/core/shared-ftl.js +6 -6
  505. package/dist/src/core/signal-critical.d.ts +2 -2
  506. package/dist/src/core/signal-critical.js +4 -6
  507. package/dist/src/core/smoke-patterns.d.ts +5 -6
  508. package/dist/src/core/smoke-patterns.js +15 -20
  509. package/dist/src/core/state-file.d.ts +15 -4
  510. package/dist/src/core/state-file.js +14 -1
  511. package/dist/src/core/status-binary.d.ts +8 -8
  512. package/dist/src/core/status-binary.js +12 -12
  513. package/dist/src/core/status-classify.d.ts +17 -17
  514. package/dist/src/core/status-classify.js +13 -12
  515. package/dist/src/core/test-changed-prefs.d.ts +12 -12
  516. package/dist/src/core/test-changed-prefs.js +40 -25
  517. package/dist/src/core/test-harness-crash.d.ts +39 -39
  518. package/dist/src/core/test-harness-crash.js +69 -69
  519. package/dist/src/core/test-harness-output.d.ts +7 -7
  520. package/dist/src/core/test-harness-output.js +7 -7
  521. package/dist/src/core/test-harness-verdict-notes.d.ts +13 -14
  522. package/dist/src/core/test-harness-verdict-notes.js +4 -4
  523. package/dist/src/core/test-path-scope.d.ts +8 -8
  524. package/dist/src/core/test-path-scope.js +11 -11
  525. package/dist/src/core/test-stale-check.d.ts +22 -23
  526. package/dist/src/core/test-stale-check.js +31 -30
  527. package/dist/src/core/test-stale-symlink.d.ts +1 -1
  528. package/dist/src/core/test-stale-symlink.js +1 -1
  529. package/dist/src/core/test-stall-triage.d.ts +9 -9
  530. package/dist/src/core/test-stall-triage.js +22 -22
  531. package/dist/src/core/test-xpcshell-retry.d.ts +26 -7
  532. package/dist/src/core/test-xpcshell-retry.js +14 -11
  533. package/dist/src/core/token-category.d.ts +35 -2
  534. package/dist/src/core/token-category.js +67 -58
  535. package/dist/src/core/token-coverage.js +4 -5
  536. package/dist/src/core/token-dark-mode.d.ts +9 -9
  537. package/dist/src/core/token-dark-mode.js +13 -25
  538. package/dist/src/core/token-docs.d.ts +1 -1
  539. package/dist/src/core/token-inventory.d.ts +56 -0
  540. package/dist/src/core/token-inventory.js +109 -0
  541. package/dist/src/core/token-manager.d.ts +4 -4
  542. package/dist/src/core/token-manager.js +22 -22
  543. package/dist/src/core/token-scaffold.d.ts +4 -4
  544. package/dist/src/core/token-scaffold.js +4 -4
  545. package/dist/src/core/token-variant.d.ts +14 -14
  546. package/dist/src/core/token-variant.js +52 -53
  547. package/dist/src/core/toolchain-preflight.d.ts +15 -15
  548. package/dist/src/core/toolchain-preflight.js +23 -23
  549. package/dist/src/core/tree-cow.d.ts +3 -5
  550. package/dist/src/core/tree-cow.js +8 -8
  551. package/dist/src/core/tree-guard.d.ts +3 -3
  552. package/dist/src/core/tree-guard.js +23 -23
  553. package/dist/src/core/tree-store.d.ts +15 -15
  554. package/dist/src/core/tree-store.js +39 -38
  555. package/dist/src/core/typecheck-shim.d.ts +16 -15
  556. package/dist/src/core/typecheck-shim.js +26 -25
  557. package/dist/src/core/typecheck.d.ts +12 -12
  558. package/dist/src/core/typecheck.js +33 -33
  559. package/dist/src/core/wire-destroy.d.ts +2 -2
  560. package/dist/src/core/wire-destroy.js +5 -5
  561. package/dist/src/core/wire-dom-fragment.d.ts +3 -3
  562. package/dist/src/core/wire-dom-fragment.js +12 -23
  563. package/dist/src/core/wire-init.d.ts +2 -2
  564. package/dist/src/core/wire-init.js +7 -7
  565. package/dist/src/core/wire-subscript.d.ts +1 -1
  566. package/dist/src/core/wire-subscript.js +3 -3
  567. package/dist/src/core/wire-utils.d.ts +9 -9
  568. package/dist/src/core/wire-utils.js +16 -28
  569. package/dist/src/core/xpcshell-appdir.d.ts +20 -20
  570. package/dist/src/core/xpcshell-appdir.js +28 -30
  571. package/dist/src/core/xpcshell-profile-dir.d.ts +3 -3
  572. package/dist/src/core/xpcshell-profile-dir.js +7 -7
  573. package/dist/src/errors/base.d.ts +69 -16
  574. package/dist/src/errors/base.js +95 -26
  575. package/dist/src/errors/build.d.ts +6 -6
  576. package/dist/src/errors/build.js +26 -34
  577. package/dist/src/errors/codes.d.ts +10 -10
  578. package/dist/src/errors/codes.js +10 -10
  579. package/dist/src/errors/config.d.ts +0 -14
  580. package/dist/src/errors/config.js +13 -34
  581. package/dist/src/errors/download.d.ts +13 -0
  582. package/dist/src/errors/download.js +53 -24
  583. package/dist/src/errors/furnace.d.ts +2 -2
  584. package/dist/src/errors/furnace.js +8 -9
  585. package/dist/src/errors/git.d.ts +9 -9
  586. package/dist/src/errors/git.js +21 -31
  587. package/dist/src/errors/patch.d.ts +3 -3
  588. package/dist/src/errors/patch.js +11 -13
  589. package/dist/src/errors/rebase.d.ts +1 -1
  590. package/dist/src/errors/rebase.js +8 -8
  591. package/dist/src/errors/run.d.ts +1 -1
  592. package/dist/src/errors/run.js +1 -1
  593. package/dist/src/index.d.ts +4 -4
  594. package/dist/src/index.js +4 -4
  595. package/dist/src/types/commands/options.d.ts +155 -200
  596. package/dist/src/types/commands/patches.d.ts +19 -19
  597. package/dist/src/types/commands/project.d.ts +3 -3
  598. package/dist/src/types/config.d.ts +52 -19
  599. package/dist/src/types/furnace.d.ts +17 -17
  600. package/dist/src/types/index.d.ts +0 -1
  601. package/dist/src/types/json.d.ts +3 -3
  602. package/dist/src/types/json.js +2 -2
  603. package/dist/src/types/typecheck.d.ts +3 -3
  604. package/dist/src/utils/assert.d.ts +4 -16
  605. package/dist/src/utils/assert.js +7 -24
  606. package/dist/src/utils/build-info.d.ts +6 -6
  607. package/dist/src/utils/build-info.js +6 -6
  608. package/dist/src/utils/child-env.d.ts +7 -6
  609. package/dist/src/utils/child-env.js +5 -5
  610. package/dist/src/utils/concurrency.d.ts +2 -2
  611. package/dist/src/utils/concurrency.js +2 -2
  612. package/dist/src/utils/elapsed.js +10 -1
  613. package/dist/src/utils/errors.d.ts +8 -8
  614. package/dist/src/utils/errors.js +8 -8
  615. package/dist/src/utils/fs.d.ts +1 -1
  616. package/dist/src/utils/fs.js +15 -20
  617. package/dist/src/utils/hash.d.ts +12 -0
  618. package/dist/src/utils/hash.js +16 -0
  619. package/dist/src/utils/line-dispatch.d.ts +15 -0
  620. package/dist/src/utils/line-dispatch.js +48 -0
  621. package/dist/src/utils/logger.d.ts +4 -4
  622. package/dist/src/utils/logger.js +11 -11
  623. package/dist/src/utils/machine-output.js +2 -2
  624. package/dist/src/utils/options.d.ts +14 -20
  625. package/dist/src/utils/options.js +26 -27
  626. package/dist/src/utils/package-root.js +5 -14
  627. package/dist/src/utils/paths.d.ts +4 -4
  628. package/dist/src/utils/paths.js +4 -4
  629. package/dist/src/utils/platform.d.ts +0 -4
  630. package/dist/src/utils/process-group.d.ts +10 -9
  631. package/dist/src/utils/process-group.js +37 -36
  632. package/dist/src/utils/process.d.ts +70 -55
  633. package/dist/src/utils/process.js +129 -179
  634. package/dist/src/utils/ps-duration.d.ts +4 -4
  635. package/dist/src/utils/ps-duration.js +9 -9
  636. package/dist/src/utils/regex.d.ts +4 -4
  637. package/dist/src/utils/regex.js +7 -7
  638. package/dist/src/utils/sleep.d.ts +26 -0
  639. package/dist/src/utils/sleep.js +31 -0
  640. package/dist/src/utils/stdio-drain.d.ts +7 -7
  641. package/dist/src/utils/stdio-drain.js +8 -8
  642. package/dist/src/utils/validation.d.ts +12 -49
  643. package/dist/src/utils/validation.js +26 -36
  644. package/docs/README.md +2 -2
  645. package/docs/configuration.md +163 -69
  646. package/docs/exit-codes.md +66 -49
  647. package/docs/furnace.md +20 -19
  648. package/docs/lifecycle-invariants.md +414 -247
  649. package/docs/machine-output.md +58 -34
  650. package/docs/patch-workflow.md +48 -44
  651. package/docs/run-logs.md +72 -28
  652. package/docs/testing.md +105 -98
  653. package/docs/verification-trees.md +23 -22
  654. package/package.json +7 -6
  655. package/dist/src/commands/rebase.d.ts +0 -4
  656. package/dist/src/commands/rebase.js +0 -5
  657. package/dist/src/core/patch-artifact-normalize.d.ts +0 -21
  658. package/dist/src/core/patch-artifact-normalize.js +0 -24
  659. package/dist/src/core/patch-lint-reexports.d.ts +0 -7
  660. package/dist/src/core/patch-lint-reexports.js +0 -8
  661. package/dist/src/core/wire-targets.d.ts +0 -7
  662. package/dist/src/core/wire-targets.js +0 -8
@@ -89,7 +89,7 @@ export async function configCommand(projectRoot, key, value, options = {}) {
89
89
  throw new GeneralError('No fireforge.json found. Run "fireforge setup" to create a project.');
90
90
  }
91
91
  if (value === undefined) {
92
- // Get mode — read the raw document rather than the validated config so
92
+ // Get mode: read the raw document rather than the validated config so
93
93
  // keys persisted via `fireforge config <key> --force` remain readable.
94
94
  // `validateConfig` builds a typed clone containing only the known schema
95
95
  // fields, so relying on it here would hide forced-write keys and surface
@@ -110,7 +110,7 @@ export async function configCommand(projectRoot, key, value, options = {}) {
110
110
  }
111
111
  }
112
112
  else {
113
- // Set mode — validate key prefix
113
+ // Set mode: validate key prefix
114
114
  const topLevelKey = key.split('.')[0] ?? key;
115
115
  if (!SUPPORTED_CONFIG_ROOT_KEYS.includes(topLevelKey) &&
116
116
  !options.force) {
@@ -126,7 +126,7 @@ export async function configCommand(projectRoot, key, value, options = {}) {
126
126
  // Serialise the read → mutate → write round-trip behind the sidecar
127
127
  // config lock so two concurrent `fireforge config` invocations cannot
128
128
  // each read the pre-state, mutate their own copy, and clobber each
129
- // other on write — both exiting 0 with one key silently lost. Atomic
129
+ // other on write, both exiting 0 with one key silently lost. Atomic
130
130
  // file writes (temp + rename) are not enough on their own: the lost
131
131
  // update happens before the rename, inside the read-modify step.
132
132
  // Readers stay lock-free (see `withConfigFileLock`).
@@ -143,12 +143,12 @@ export async function configCommand(projectRoot, key, value, options = {}) {
143
143
  if (deepEqual(currentValue, parsedValue)) {
144
144
  return true;
145
145
  }
146
- // `--force` is an escape hatch for *unknown* keys; it must not also
147
- // let the user write a structurally invalid value for a *known* key.
146
+ // `--force` is an escape hatch for unknown keys. It must not also
147
+ // let the user write a structurally invalid value for a known key.
148
148
  // Strict validation applies whenever the key is listed in
149
149
  // SUPPORTED_CONFIG_PATHS, regardless of --force.
150
150
  //
151
- // BOTH branches seed the mutation from the raw on-disk document.
151
+ // Both branches seed the mutation from the raw on-disk document.
152
152
  // Round-tripping the known-key branch through `loadConfig` →
153
153
  // `validateConfig` builds a typed clone containing only the known
154
154
  // schema fields, so any ordinary `fireforge config <key> <value>`
@@ -160,7 +160,7 @@ export async function configCommand(projectRoot, key, value, options = {}) {
160
160
  }
161
161
  else {
162
162
  // Mutate the raw document (preserving unknown keys), then run
163
- // strict validation on the RESULT — validateConfig checks the
163
+ // strict validation on the result. validateConfig checks the
164
164
  // known schema fields and ignores unknown keys, so this keeps
165
165
  // exactly the old validation strength while writing the
166
166
  // unstripped document.
@@ -174,7 +174,7 @@ export async function configCommand(projectRoot, key, value, options = {}) {
174
174
  catch (error) {
175
175
  // Only value/validation problems are the user's "invalid value".
176
176
  // Lock-acquisition timeouts and I/O failures must keep their own
177
- // types and messages — re-labelling a lock timeout as `Invalid value
177
+ // types and messages. Re-labelling a lock timeout as `Invalid value
178
178
  // for "<key>"` points diagnosis at the value (and returns the wrong
179
179
  // exit-code class) when the real problem is a concurrent fireforge
180
180
  // process holding the config lock.
@@ -195,7 +195,7 @@ export async function configCommand(projectRoot, key, value, options = {}) {
195
195
  /**
196
196
  * Structural equality check covering the shapes `fireforge config` accepts:
197
197
  * primitives (strings, numbers, booleans), `null`, arrays of primitives, and
198
- * nested objects. Used to short-circuit no-op writes — when the parsed value
198
+ * nested objects. Used to short-circuit no-op writes: when the parsed value
199
199
  * matches the current on-disk value, the mutate + write step is skipped
200
200
  * entirely.
201
201
  */
@@ -0,0 +1,19 @@
1
+ import type { DestructiveOpResult } from '../core/destructive.js';
2
+ /**
3
+ * Closes out a {@link DestructiveOpResult} and says whether to run the
4
+ * mutation.
5
+ *
6
+ * Eleven commands had copied the same tail: `if (decision === 'dry-run') {
7
+ * outro(…); return; } if (decision === 'declined') { outro(…); return; }`.
8
+ * The dry-run wording is a user-facing contract that must not drift between
9
+ * commands, so it lives here. The declined wording is per-command and stays
10
+ * a parameter.
11
+ *
12
+ * `confirmDestructive` never mutates on its own, so a caller that forgets this
13
+ * check silently performs a "dry run" for real. That is why this returns a
14
+ * boolean the caller must act on instead of being a helper that returns void.
15
+ * @param decision - The result from `confirmDestructive`.
16
+ * @param declinedOutro - Outro to print when the operator answered "no".
17
+ * @returns True when the caller should proceed with the mutation.
18
+ */
19
+ export declare function proceedAfterDecision(decision: DestructiveOpResult, declinedOutro: string): boolean;
@@ -0,0 +1,31 @@
1
+ import { outro } from '../utils/logger.js';
2
+ /** The dry-run outro every command prints, spelled once. */
3
+ const DRY_RUN_OUTRO = 'Dry run complete — no changes made';
4
+ /**
5
+ * Closes out a {@link DestructiveOpResult} and says whether to run the
6
+ * mutation.
7
+ *
8
+ * Eleven commands had copied the same tail: `if (decision === 'dry-run') {
9
+ * outro(…); return; } if (decision === 'declined') { outro(…); return; }`.
10
+ * The dry-run wording is a user-facing contract that must not drift between
11
+ * commands, so it lives here. The declined wording is per-command and stays
12
+ * a parameter.
13
+ *
14
+ * `confirmDestructive` never mutates on its own, so a caller that forgets this
15
+ * check silently performs a "dry run" for real. That is why this returns a
16
+ * boolean the caller must act on instead of being a helper that returns void.
17
+ * @param decision - The result from `confirmDestructive`.
18
+ * @param declinedOutro - Outro to print when the operator answered "no".
19
+ * @returns True when the caller should proceed with the mutation.
20
+ */
21
+ export function proceedAfterDecision(decision, declinedOutro) {
22
+ if (decision === 'dry-run') {
23
+ outro(DRY_RUN_OUTRO);
24
+ return false;
25
+ }
26
+ if (decision === 'declined') {
27
+ outro(declinedOutro);
28
+ return false;
29
+ }
30
+ return true;
31
+ }
@@ -103,7 +103,7 @@ async function discardDirectoryEntries(projectRoot, engineDir, patchesDir, dirPa
103
103
  }
104
104
  }
105
105
  catch {
106
- // Furnace config may not exist — skip silently
106
+ // Furnace config may not exist, so skip silently.
107
107
  }
108
108
  if (failures.length > 0) {
109
109
  throw new GeneralError(`Failed to discard ${failures.length} file(s) under ${dirPath}/. See warnings above.`);
@@ -131,7 +131,7 @@ export async function discardCommand(projectRoot, file, options = {}) {
131
131
  const statusEntries = await expandUntrackedDirectoryEntries(paths.engine, await getWorkingTreeStatus(paths.engine));
132
132
  const statusEntry = statusEntries.find((entry) => entry.file === file || entry.originalPath === file);
133
133
  // Directory recursion fallback: when the explicit path does not match a
134
- // single status entry but DOES correspond to one or more entries below it,
134
+ // single status entry but does correspond to one or more entries below it,
135
135
  // treat the input as a directory and discard everything inside. Otherwise
136
136
  // `discard <dir> --yes` fails with "no changes to discard" even though
137
137
  // `status --unmanaged` lists files under that directory, forcing the
@@ -159,8 +159,8 @@ export async function discardCommand(projectRoot, file, options = {}) {
159
159
  throw new GeneralError(`File "${file}" has no changes to discard.`);
160
160
  }
161
161
  if (options.dryRun) {
162
- // Show the rename pair regardless of which side the operator passed —
163
- // passing the NEW path of a rename used to hide that discarding also
162
+ // Show the rename pair regardless of which side the operator passed.
163
+ // Passing the new path of a rename used to hide that discarding also
164
164
  // resurrects the old path, exactly when the full picture matters most.
165
165
  info(`Would discard changes to: ${dryRunLabel(plan)}`);
166
166
  outro('Dry run complete — no changes made');
@@ -182,7 +182,7 @@ export async function discardCommand(projectRoot, file, options = {}) {
182
182
  }
183
183
  }
184
184
  catch {
185
- // Furnace config may not exist — skip silently
185
+ // Furnace config may not exist, so skip silently.
186
186
  }
187
187
  outro(describeDiscardOutcome(plan, options.toUpstream === true));
188
188
  }
@@ -37,21 +37,21 @@ export interface DoctorCheckContext {
37
37
  /**
38
38
  * The parsed furnace config, set by the "Furnace configuration" check
39
39
  * when it succeeds. Later furnace checks read from this so they do not
40
- * re-parse the file; undefined when the config could not be loaded.
40
+ * re-parse the file. Undefined when the config could not be loaded.
41
41
  */
42
42
  furnaceConfig: FurnaceConfig | undefined;
43
43
  /**
44
44
  * State this run actually mutated, one human-readable line per write.
45
45
  * Repairs run inside the check loop while the exit code is computed only
46
46
  * after every check, so a repair can land and the run still exit non-zero
47
- * on an unrelated check — and a non-zero exit reads as "nothing happened".
47
+ * on an unrelated check, and a non-zero exit reads as "nothing happened".
48
48
  * The runner prints these before the summary in every branch so a write is
49
49
  * never invisible.
50
50
  */
51
51
  mutations: string[];
52
52
  }
53
53
  /**
54
- * Result a check may return. A single object is the common case; an array
54
+ * Result a check may return. A single object is the common case. An array
55
55
  * lets a single check emit multiple related rows (e.g. the engine branch
56
56
  * check which may report on branch + detached state together).
57
57
  */
@@ -85,7 +85,7 @@ export interface DoctorCheckDefinition {
85
85
  dependsOn?: readonly string[];
86
86
  /**
87
87
  * Runs the inspection. Throwing is shorthand for "this check failed with
88
- * severity 'error'" — the runner converts the exception message into a
88
+ * severity 'error'": the runner converts the exception message into a
89
89
  * DoctorCheck. Returning a DoctorCheck (or array) lets the check control
90
90
  * severity, warnings, and fix hints directly.
91
91
  */
@@ -96,12 +96,6 @@ export interface DoctorCheckDefinition {
96
96
  */
97
97
  fix?: string;
98
98
  }
99
- /**
100
- * Resolves a {@link DoctorCheck} to its effective severity. `severity` is the
101
- * single source of truth; this exists so every consumer of a
102
- * `DoctorCheck[]` reads it the same way.
103
- */
104
- export declare function resolveDoctorSeverity(check: DoctorCheck): 'ok' | 'warning' | 'error';
105
99
  /**
106
100
  * Builds a DoctorCheck object representing a successful "OK" check.
107
101
  */
@@ -4,14 +4,6 @@
4
4
  * `doctor.ts` and sibling check modules. Kept separate so registries can import
5
5
  * these symbols without creating cycles through `doctor.ts`.
6
6
  */
7
- /**
8
- * Resolves a {@link DoctorCheck} to its effective severity. `severity` is the
9
- * single source of truth; this exists so every consumer of a
10
- * `DoctorCheck[]` reads it the same way.
11
- */
12
- export function resolveDoctorSeverity(check) {
13
- return check.severity;
14
- }
15
7
  /**
16
8
  * Builds a DoctorCheck object representing a successful "OK" check.
17
9
  */
@@ -15,8 +15,8 @@ async function resolveDeclaredTool(projectRoot, tool) {
15
15
  return found.exitCode === 0 ? line?.trim() : undefined;
16
16
  }
17
17
  catch {
18
- // `xcrun -find` is absent or the tool is unknown — either way the tool has
19
- // no resolvable path, which is what `undefined` means to the caller.
18
+ // `xcrun -find` is absent or the tool is unknown. Either way the tool
19
+ // has no resolvable path, which is what `undefined` means to the caller.
20
20
  return undefined;
21
21
  }
22
22
  }
@@ -2,11 +2,11 @@
2
2
  * "Furnace config sync" doctor check.
3
3
  *
4
4
  * Surfaces orphaned component directories on disk whose names are missing
5
- * from `furnace.json` — typically the concurrent-override race, where two
5
+ * from `furnace.json`, typically the concurrent-override race, where two
6
6
  * parallel `furnace override` commands both leave their directory on disk
7
7
  * but only the second reaches `writeFurnaceConfig`. Under
8
8
  * `--repair-furnace`, override orphans are re-registered from the
9
- * `override.json` sidecar the command wrote during the copy phase; custom
9
+ * `override.json` sidecar the command wrote during the copy phase. Custom
10
10
  * orphans are listed for the operator to either re-run `furnace create`
11
11
  * against or delete manually, because custom components have no similar
12
12
  * persisted metadata.
@@ -3,11 +3,11 @@
3
3
  * "Furnace config sync" doctor check.
4
4
  *
5
5
  * Surfaces orphaned component directories on disk whose names are missing
6
- * from `furnace.json` — typically the concurrent-override race, where two
6
+ * from `furnace.json`, typically the concurrent-override race, where two
7
7
  * parallel `furnace override` commands both leave their directory on disk
8
8
  * but only the second reaches `writeFurnaceConfig`. Under
9
9
  * `--repair-furnace`, override orphans are re-registered from the
10
- * `override.json` sidecar the command wrote during the copy phase; custom
10
+ * `override.json` sidecar the command wrote during the copy phase. Custom
11
11
  * orphans are listed for the operator to either re-run `furnace create`
12
12
  * against or delete manually, because custom components have no similar
13
13
  * persisted metadata.
@@ -32,10 +32,10 @@ import { failure, ok, warning } from './doctor-check-core.js';
32
32
  * to catch. The caller surfaces the failure instead.
33
33
  */
34
34
  async function listComponentDirs(dir) {
35
- // `pathExistsStrict`, not `pathExists`: the latter answers `false` for EVERY
35
+ // `pathExistsStrict`, not `pathExists`: the latter answers `false` for every
36
36
  // access error, so an unreadable components directory reported "no orphans",
37
- // i.e. a clean check — the same fail-open the comment above rejects for
38
- // `readdir`. Only ENOENT means genuinely absent.
37
+ // i.e. a clean check. That is the same fail-open the comment above rejects
38
+ // for `readdir`. Only ENOENT means genuinely absent.
39
39
  if (!(await pathExistsStrict(dir)))
40
40
  return [];
41
41
  const entries = await readdir(dir, { withFileTypes: true });
@@ -48,7 +48,7 @@ async function recoverOverrideConfig(overrideDir, name) {
48
48
  // outer-snapshot config and drops the sibling write's addition.
49
49
  //
50
50
  // No `pathExists` precheck: it collapses "absent" and "unreadable" into
51
- // the same `false`, and both outcomes lead here anyway — a missing file
51
+ // the same `false`, and both outcomes lead here anyway. A missing file
52
52
  // lands in the catch below with the same `undefined` result.
53
53
  const sidecarPath = join(overrideDir, name, 'override.json');
54
54
  try {
@@ -79,7 +79,7 @@ async function recoverOverrideConfig(overrideDir, name) {
79
79
  catch {
80
80
  // Unreadable or malformed sidecar. Returning `undefined` here is the same
81
81
  // value as "no sidecar present", so the caller reports the override as
82
- // unrecoverable — which is the safe direction (it never invents config),
82
+ // unrecoverable. That is the safe direction (it never invents config),
83
83
  // but the operator sees "no valid override.json" rather than "the
84
84
  // override.json is corrupt". The remediation is identical either way.
85
85
  return undefined;
@@ -125,7 +125,7 @@ function emptyOutcome() {
125
125
  }
126
126
  /**
127
127
  * Re-registers override orphans and deletes empty custom orphan directories,
128
- * under ONE furnace lock held across both.
128
+ * under one furnace lock held across both.
129
129
  *
130
130
  * Two things this must not do, both of which reproduce the lost-write race the
131
131
  * check exists to clean up after:
@@ -133,9 +133,9 @@ function emptyOutcome() {
133
133
  * 1. Write back a decision made before the lock. The orphan list is computed
134
134
  * from a config snapshot loaded well before we hold anything, so by the
135
135
  * time we can write, a concurrent `furnace override` may have registered
136
- * the same name — writing our sidecar-reconstructed entry over it discards
136
+ * the same name. Writing our sidecar-reconstructed entry over it discards
137
137
  * a live write, and a concurrent `furnace create` registering the name
138
- * under `custom` would leave it in BOTH maps, a state nothing validates.
138
+ * under `custom` would leave it in both maps, a state nothing validates.
139
139
  * Every orphan is therefore re-checked against `freshConfig` inside the
140
140
  * lock and skipped when it is no longer orphaned.
141
141
  * 2. Delete custom directories outside the lock. `repairCustomOrphans` used to
@@ -148,12 +148,12 @@ async function repairOrphans(projectRoot, orphans) {
148
148
  if (orphans.overrides.length === 0 && orphans.customNames.length === 0)
149
149
  return outcome;
150
150
  const lockPath = getFurnaceLockPath(projectRoot);
151
- // One catch covers four distinct phases; naming the one that failed keeps
152
- // the report honest — a lock timeout otherwise renders as "failed while
151
+ // One catch covers four distinct phases. Naming the one that failed keeps
152
+ // the report honest. A lock timeout otherwise renders as "failed while
153
153
  // writing furnace.json", the phase least likely to have been reached.
154
154
  // Held in an object rather than two `let`s: the lock callback mutates them
155
155
  // from inside a closure, and TS's control-flow analysis does not propagate
156
- // that through the call — it would narrow both to their initial literals
156
+ // that through the call, so it would narrow both to their initial literals
157
157
  // in the catch below.
158
158
  const progress = { phase: 'waiting for the furnace lock', persisted: false };
159
159
  try {
@@ -165,7 +165,7 @@ async function repairOrphans(projectRoot, orphans) {
165
165
  progress.phase = 'writing furnace.json';
166
166
  await writeFurnaceConfig(projectRoot, freshConfig);
167
167
  }
168
- // From here the restore (if any) is on disk; a later failure must not
168
+ // From here the restore (if any) is on disk. A later failure must not
169
169
  // report the whole repair as if it never happened.
170
170
  progress.persisted = true;
171
171
  progress.phase = 'cleaning custom orphan directories';
@@ -188,11 +188,11 @@ async function repairOrphans(projectRoot, orphans) {
188
188
  }
189
189
  return outcome;
190
190
  }
191
- /** Override half of {@link repairOrphans}; mutates `freshConfig` in place. */
191
+ /** Override half of {@link repairOrphans}. Mutates `freshConfig` in place. */
192
192
  function repairOverridesLocked(freshConfig, orphans, outcome) {
193
193
  for (const orphan of orphans) {
194
194
  if (orphan.name in freshConfig.overrides || orphan.name in freshConfig.custom) {
195
- // Registered while we waited for the lock — no longer an orphan, and
195
+ // Registered while we waited for the lock, so no longer an orphan, and
196
196
  // writing over it would either discard that write or duplicate the name
197
197
  // across `overrides` and `custom`.
198
198
  outcome.reconciled.push(orphan.name);
@@ -207,15 +207,15 @@ function repairOverridesLocked(freshConfig, orphans, outcome) {
207
207
  }
208
208
  }
209
209
  }
210
- /** Custom half of {@link repairOrphans}; must run under the same lock. */
210
+ /** Custom half of {@link repairOrphans}. Must run under the same lock. */
211
211
  async function deleteEmptyCustomOrphans(projectRoot, freshConfig, customNames, outcome) {
212
212
  if (customNames.length === 0)
213
213
  return;
214
214
  const furnacePaths = getFurnacePaths(projectRoot);
215
215
  for (const name of customNames) {
216
216
  if (name in freshConfig.custom || name in freshConfig.overrides) {
217
- // A name that was orphaned in BOTH trees is reconciled once, not once
218
- // per tree — the report reads "Skipped 2 names (x, x)" otherwise.
217
+ // A name orphaned in both trees is reconciled once rather than once
218
+ // per tree. The report reads "Skipped 2 names (x, x)" otherwise.
219
219
  if (!outcome.reconciled.includes(name))
220
220
  outcome.reconciled.push(name);
221
221
  continue;
@@ -237,7 +237,7 @@ async function deleteEmptyCustomOrphans(projectRoot, freshConfig, customNames, o
237
237
  // `rmdir`, not `rm`: `rm` without `{ recursive: true }` throws EISDIR on
238
238
  // a directory, so on a real filesystem this branch always failed and the
239
239
  // "deleted N empty directories" report was unreachable. `rmdir` is also
240
- // the exact semantics wanted here — it refuses a non-empty directory,
240
+ // the exact semantics wanted here: it refuses a non-empty directory,
241
241
  // which keeps the emptiness check above from being the only safeguard.
242
242
  await rmdir(dir);
243
243
  outcome.deleted.push(name);
@@ -8,7 +8,7 @@ import type { DoctorCheckDefinition } from './doctor-check-core.js';
8
8
  /**
9
9
  * "Furnace jar.mn registrations" check: detect widget registration lines
10
10
  * pointing at component files that no longer exist in the workspace,
11
- * typically left by a rename. These break `mach build` at packaging;
11
+ * typically left by a rename. These break `mach build` at packaging.
12
12
  * `--repair-furnace` prunes them.
13
13
  */
14
14
  export declare const furnaceStaleJarRegistrationCheck: DoctorCheckDefinition;
@@ -12,7 +12,7 @@ import { failure, ok, warning } from './doctor-check-core.js';
12
12
  /**
13
13
  * "Furnace jar.mn registrations" check: detect widget registration lines
14
14
  * pointing at component files that no longer exist in the workspace,
15
- * typically left by a rename. These break `mach build` at packaging;
15
+ * typically left by a rename. These break `mach build` at packaging.
16
16
  * `--repair-furnace` prunes them.
17
17
  */
18
18
  export const furnaceStaleJarRegistrationCheck = {
@@ -50,7 +50,7 @@ async function clearPendingRepairMarker(projectRoot) {
50
50
  * `stock` and name is the tag name.
51
51
  *
52
52
  * Stock components are never checksummed by apply, so they never appear
53
- * in the state file — any stock-prefixed entry is automatically stale.
53
+ * in the state file, so any stock-prefixed entry is automatically stale.
54
54
  */
55
55
  function collectStaleChecksumKeys(appliedChecksums, config) {
56
56
  const stale = [];
@@ -103,7 +103,7 @@ async function collectFurnaceDrift(projectRoot, engineDir, config, ftlDir) {
103
103
  }
104
104
  }
105
105
  catch {
106
- // Drift check throws on unreadable paths; treat as drift so the
106
+ // Drift check throws on unreadable paths. Treat as drift so the
107
107
  // operator is told to run apply rather than swallowing the error.
108
108
  drifted.push(name);
109
109
  }
@@ -120,9 +120,9 @@ async function collectFurnaceDrift(projectRoot, engineDir, config, ftlDir) {
120
120
  }
121
121
  }
122
122
  catch {
123
- // A drift probe that cannot complete is reported AS drift: the doctor check
124
- // must not claim a component is clean when it failed to look. Mirrors the
125
- // documented twin above.
123
+ // A drift probe that cannot complete is reported as drift: the doctor
124
+ // check must not claim a component is clean when it failed to look.
125
+ // Mirrors the documented twin above.
126
126
  drifted.push(name);
127
127
  }
128
128
  }
@@ -182,7 +182,7 @@ const furnaceStateConsistencyCheck = {
182
182
  }
183
183
  const ghostSet = new Set();
184
184
  for (const key of staleKeys) {
185
- // Keys look like "override/<name>/<file>" — the ghost component is
185
+ // Keys look like "override/<name>/<file>", so the ghost component is
186
186
  // the first two segments joined for display purposes.
187
187
  const segments = key.split('/');
188
188
  if (segments.length >= 2) {
@@ -214,14 +214,14 @@ const furnaceStateConsistencyCheck = {
214
214
  };
215
215
  /**
216
216
  * "Furnace engine state" check: detect the `pendingRepair` marker set by
217
- * a failed preview teardown AND any on-disk drift between the workspace
217
+ * a failed preview teardown and any on-disk drift between the workspace
218
218
  * and the engine. Repair runs `applyAllComponents` to reconcile and
219
219
  * clears the marker on success.
220
220
  */
221
221
  const furnaceEngineStateCheck = {
222
222
  name: 'Furnace engine state',
223
223
  dependsOn: ['Furnace configuration'],
224
- // Requires both a furnace project AND an engine checkout — the drift
224
+ // Requires both a furnace project and an engine checkout: the drift
225
225
  // oracles resolve engine paths, so a missing engine dir would throw.
226
226
  skipIf: (ctx) => !ctx.furnaceConfigExists || !ctx.furnaceConfig || !ctx.engineExists,
227
227
  run: async (ctx) => {
@@ -286,16 +286,16 @@ const furnaceEngineStateCheck = {
286
286
  }
287
287
  // Repair path: run apply to reconcile the engine with the workspace
288
288
  // state, then clear the pendingRepair marker on success. We re-run
289
- // apply even when only the marker is set — the marker exists
290
- // specifically because the last mutation could not clean up, so the
291
- // cheapest honest thing we can do is re-reconcile end-to-end.
289
+ // apply even when only the marker is set. The marker exists
290
+ // specifically because the last mutation could not clean up, so
291
+ // re-reconciling end-to-end is the cheapest honest thing to do.
292
292
  try {
293
293
  const applyResult = await runRepairApply(ctx.projectRoot);
294
294
  const totalFailures = countApplyFailures(applyResult);
295
295
  if (totalFailures > 0) {
296
296
  return failure('Furnace engine state', `Repair attempted but apply reported ${totalFailures} failure${totalFailures === 1 ? '' : 's'} (first: ${firstApplyFailure(applyResult)}).`, 'Fix the underlying component issue and retry the doctor command.');
297
297
  }
298
- // Apply succeeded — clear the pendingRepair marker so subsequent
298
+ // Apply succeeded, so clear the pendingRepair marker so subsequent
299
299
  // doctor runs stop reporting the issue. updateFurnaceState merges
300
300
  // its return value via `validateFurnaceState` which simply writes
301
301
  // whatever object we return, so dropping the key from the spread
@@ -356,9 +356,9 @@ const furnaceEnginePathsCheck = {
356
356
  /**
357
357
  * Furnace Storybook backend check: verifies that the engine contains the
358
358
  * Storybook workspace required by `furnace preview`. Missing Storybook
359
- * support is a warning, not a failure, since furnace works fine without
360
- * preview — but operators should know upfront rather than discovering it
361
- * mid-command.
359
+ * support is a warning rather than a failure, since furnace works fine
360
+ * without preview. Operators should still know upfront rather than
361
+ * discovering it mid-command.
362
362
  */
363
363
  const furnaceStorybookCheck = {
364
364
  name: 'Furnace Storybook backend',
@@ -422,7 +422,7 @@ const furnaceComponentValidationCheck = {
422
422
  /**
423
423
  * Reads the owner PID from a furnace lock directory. Returns `null` when
424
424
  * the PID file is missing, unreadable, or does not parse as a finite
425
- * integer — the caller then falls back to an age-only heuristic.
425
+ * integer. The caller then falls back to an age-only heuristic.
426
426
  */
427
427
  async function readFurnaceLockPid(lockPath) {
428
428
  try {
@@ -443,10 +443,10 @@ async function readFurnaceLockPid(lockPath) {
443
443
  *
444
444
  * This is the recovery path when the signal-handler sweep
445
445
  * (`forceReleaseFurnaceLocksForActiveOperations` in `bin/fireforge.ts`)
446
- * misses — a SIGKILL'd process that never ran the handler, or a lock created
446
+ * misses: a SIGKILL'd process that never ran the handler, or a lock created
447
447
  * by an older FireForge release without a PID file. SIGINT'ing `furnace
448
448
  * preview` leaves the lock behind, and the next `fireforge test --build`
449
- * then times out waiting for it; `doctor --repair-furnace` clears it so the
449
+ * then times out waiting for it. `doctor --repair-furnace` clears it so the
450
450
  * next command runs immediately.
451
451
  */
452
452
  const furnaceStaleLockCheck = {
@@ -464,12 +464,12 @@ const furnaceStaleLockCheck = {
464
464
  const ageSuffix = ageMs !== undefined ? ` (age: ${Math.round(ageMs / 1000)}s)` : '';
465
465
  // Two signals mark a lock as stale:
466
466
  // 1. PID file says owner is dead → unambiguous, remove immediately.
467
- // 2. PID file absent AND lock is older than 60s → older FireForge
467
+ // 2. PID file absent and lock is older than 60s → older FireForge
468
468
  // releases (or an externally-created lock directory) fall into this
469
- // bucket; the age gate avoids false positives on a lock just
469
+ // bucket. The age gate avoids false positives on a lock just
470
470
  // acquired by a concurrent process that has not written its PID yet.
471
471
  //
472
- // `isProcessAlive` treats EPERM as ALIVE. Returning false for EPERM
472
+ // `isProcessAlive` treats EPERM as alive. Returning false for EPERM
473
473
  // reports a furnace lock held by a live process owned by another uid as
474
474
  // "owner is no longer running", and --repair-furnace then deletes it,
475
475
  // dropping mutual exclusion under a concurrent furnace operation.
@@ -477,7 +477,7 @@ const furnaceStaleLockCheck = {
477
477
  const pidMissingAndOld = pid === null && (ageMs ?? 0) > 60_000;
478
478
  const isStale = ownerDead || pidMissingAndOld;
479
479
  if (!isStale) {
480
- // Lock is held by a running FireForge process — nothing to report.
480
+ // Lock is held by a running FireForge process, so nothing to report.
481
481
  return ok('Furnace lock');
482
482
  }
483
483
  const description = ownerDead
@@ -1,20 +1,19 @@
1
1
  /**
2
- * Doctor check for PRE-EXISTING orphaned test-harness workers.
2
+ * Doctor check for pre-existing orphaned test-harness workers.
3
3
  *
4
4
  * A mach invocation that dies at harness startup can strand a Python
5
- * `multiprocessing` spawn worker plus its resource tracker; the worker
5
+ * `multiprocessing` spawn worker plus its resource tracker. The worker
6
6
  * reparents to launchd (PPID 1) and busy-spins at 100% CPU indefinitely.
7
- * The dispatch-side fix is the process-group reaping in `utils/process.ts`;
8
- * this check covers orphans that predate it (or leaked from non-FireForge
7
+ * The dispatch-side fix is the process-group reaping in `utils/process.ts`.
8
+ * This check covers orphans that predate it (or leaked from non-FireForge
9
9
  * invocations), detecting them by PPID 1 + large accumulated CPU TIME + a
10
10
  * `multiprocessing.spawn`/`resource_tracker` command line.
11
11
  *
12
- * Report-only by design: FireForge never kills pre-existing processes it did
13
- * not spawn — the check names each candidate and suggests the kill.
12
+ * Report-only: FireForge never kills pre-existing processes it did not
13
+ * spawn, so the check names each candidate and suggests the kill.
14
14
  *
15
- * Deliberately not wired into `test --canary`: a system-wide process scan on
16
- * the canary hot path buys no coverage the doctor check does not already
17
- * give.
15
+ * Not wired into `test --canary`: a system-wide process scan on the canary
16
+ * hot path buys no coverage the doctor check does not already give.
18
17
  */
19
18
  import type { DoctorCheckDefinition } from './doctor-check-core.js';
20
19
  /** One process matching the orphaned-harness-worker shape. */
@@ -27,21 +26,15 @@ export interface OrphanedHarnessWorker {
27
26
  cpuSeconds: number;
28
27
  command: string;
29
28
  }
30
- /**
31
- * Parses a `ps` TIME (accumulated CPU) value. Implemented in terms of
32
- * {@link parsePsDuration} — `time=` and `etime=` share one grammar, and a
33
- * second copy is how the two would drift.
34
- */
35
- export declare function parseCpuTime(time: string): number;
36
29
  /**
37
30
  * Scans `ps -axo pid=,ppid=,time=,command=` output for orphaned harness
38
31
  * workers: PPID 1 (reparented to init/launchd), a multiprocessing
39
32
  * worker/tracker command line, and at least `minCpuSeconds` of accumulated
40
- * CPU time. Pure — fixture-testable without spawning anything.
33
+ * CPU time. Pure, so it is fixture-testable without spawning anything.
41
34
  */
42
35
  export declare function findOrphanedHarnessWorkers(psOutput: string, minCpuSeconds?: number): OrphanedHarnessWorker[];
43
36
  /**
44
- * Doctor check reporting orphaned harness workers. Windows has no `ps`;
37
+ * Doctor check reporting orphaned harness workers. Windows has no `ps`, so
45
38
  * the check is skipped there (best-effort platform gap, matching the
46
39
  * process-group reaper's POSIX-only sweep).
47
40
  */