audit-tools 0.28.0

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 (1476) hide show
  1. package/README.audit.md +223 -0
  2. package/README.md +42 -0
  3. package/README.remediate.md +113 -0
  4. package/audit-code-wrapper-build.mjs +185 -0
  5. package/audit-code-wrapper-install-hosts.mjs +1079 -0
  6. package/audit-code-wrapper-install-renderers.mjs +58 -0
  7. package/audit-code-wrapper-io.mjs +155 -0
  8. package/audit-code-wrapper-legacy.mjs +125 -0
  9. package/audit-code-wrapper-lib.mjs +314 -0
  10. package/audit-code-wrapper-opencode.mjs +241 -0
  11. package/audit-code.mjs +12 -0
  12. package/dispatch/lens-definitions.json +46 -0
  13. package/dispatch/merge-results.mjs +110 -0
  14. package/dispatch/validate-result.mjs +59 -0
  15. package/dispatch/validate.mjs +16 -0
  16. package/dist/audit/adapters/coverageSummary.d.ts +9 -0
  17. package/dist/audit/adapters/coverageSummary.d.ts.map +1 -0
  18. package/dist/audit/adapters/coverageSummary.js +18 -0
  19. package/dist/audit/adapters/coverageSummary.js.map +1 -0
  20. package/dist/audit/adapters/eslint.d.ts +14 -0
  21. package/dist/audit/adapters/eslint.d.ts.map +1 -0
  22. package/dist/audit/adapters/eslint.js +28 -0
  23. package/dist/audit/adapters/eslint.js.map +1 -0
  24. package/dist/audit/adapters/normalizeExternal.d.ts +13 -0
  25. package/dist/audit/adapters/normalizeExternal.d.ts.map +1 -0
  26. package/dist/audit/adapters/normalizeExternal.js +44 -0
  27. package/dist/audit/adapters/normalizeExternal.js.map +1 -0
  28. package/dist/audit/adapters/npmAudit.d.ts +16 -0
  29. package/dist/audit/adapters/npmAudit.d.ts.map +1 -0
  30. package/dist/audit/adapters/npmAudit.js +24 -0
  31. package/dist/audit/adapters/npmAudit.js.map +1 -0
  32. package/dist/audit/adapters/semgrep.d.ts +23 -0
  33. package/dist/audit/adapters/semgrep.d.ts.map +1 -0
  34. package/dist/audit/adapters/semgrep.js +40 -0
  35. package/dist/audit/adapters/semgrep.js.map +1 -0
  36. package/dist/audit/cli/advanceAuditCommand.d.ts +2 -0
  37. package/dist/audit/cli/advanceAuditCommand.d.ts.map +1 -0
  38. package/dist/audit/cli/advanceAuditCommand.js +95 -0
  39. package/dist/audit/cli/advanceAuditCommand.js.map +1 -0
  40. package/dist/audit/cli/args.d.ts +95 -0
  41. package/dist/audit/cli/args.d.ts.map +1 -0
  42. package/dist/audit/cli/args.js +274 -0
  43. package/dist/audit/cli/args.js.map +1 -0
  44. package/dist/audit/cli/auditStep.d.ts +34 -0
  45. package/dist/audit/cli/auditStep.d.ts.map +1 -0
  46. package/dist/audit/cli/auditStep.js +162 -0
  47. package/dist/audit/cli/auditStep.js.map +1 -0
  48. package/dist/audit/cli/cleanup.d.ts +12 -0
  49. package/dist/audit/cli/cleanup.d.ts.map +1 -0
  50. package/dist/audit/cli/cleanup.js +44 -0
  51. package/dist/audit/cli/cleanup.js.map +1 -0
  52. package/dist/audit/cli/cleanupCommand.d.ts +2 -0
  53. package/dist/audit/cli/cleanupCommand.d.ts.map +1 -0
  54. package/dist/audit/cli/cleanupCommand.js +25 -0
  55. package/dist/audit/cli/cleanupCommand.js.map +1 -0
  56. package/dist/audit/cli/conceptualDispatch.d.ts +74 -0
  57. package/dist/audit/cli/conceptualDispatch.d.ts.map +1 -0
  58. package/dist/audit/cli/conceptualDispatch.js +118 -0
  59. package/dist/audit/cli/conceptualDispatch.js.map +1 -0
  60. package/dist/audit/cli/confirmIntentStep.d.ts +25 -0
  61. package/dist/audit/cli/confirmIntentStep.d.ts.map +1 -0
  62. package/dist/audit/cli/confirmIntentStep.js +210 -0
  63. package/dist/audit/cli/confirmIntentStep.js.map +1 -0
  64. package/dist/audit/cli/dispatch/packetFilter.d.ts +102 -0
  65. package/dist/audit/cli/dispatch/packetFilter.d.ts.map +1 -0
  66. package/dist/audit/cli/dispatch/packetFilter.js +148 -0
  67. package/dist/audit/cli/dispatch/packetFilter.js.map +1 -0
  68. package/dist/audit/cli/dispatch/packetPrompt.d.ts +48 -0
  69. package/dist/audit/cli/dispatch/packetPrompt.d.ts.map +1 -0
  70. package/dist/audit/cli/dispatch/packetPrompt.js +258 -0
  71. package/dist/audit/cli/dispatch/packetPrompt.js.map +1 -0
  72. package/dist/audit/cli/dispatch/paths.d.ts +7 -0
  73. package/dist/audit/cli/dispatch/paths.d.ts.map +1 -0
  74. package/dist/audit/cli/dispatch/paths.js +38 -0
  75. package/dist/audit/cli/dispatch/paths.js.map +1 -0
  76. package/dist/audit/cli/dispatch/quotaPool.d.ts +75 -0
  77. package/dist/audit/cli/dispatch/quotaPool.d.ts.map +1 -0
  78. package/dist/audit/cli/dispatch/quotaPool.js +163 -0
  79. package/dist/audit/cli/dispatch/quotaPool.js.map +1 -0
  80. package/dist/audit/cli/dispatch/tierRouting.d.ts +36 -0
  81. package/dist/audit/cli/dispatch/tierRouting.d.ts.map +1 -0
  82. package/dist/audit/cli/dispatch/tierRouting.js +121 -0
  83. package/dist/audit/cli/dispatch/tierRouting.js.map +1 -0
  84. package/dist/audit/cli/dispatch/types.d.ts +90 -0
  85. package/dist/audit/cli/dispatch/types.d.ts.map +1 -0
  86. package/dist/audit/cli/dispatch/types.js +15 -0
  87. package/dist/audit/cli/dispatch/types.js.map +1 -0
  88. package/dist/audit/cli/dispatch.d.ts +29 -0
  89. package/dist/audit/cli/dispatch.d.ts.map +1 -0
  90. package/dist/audit/cli/dispatch.js +303 -0
  91. package/dist/audit/cli/dispatch.js.map +1 -0
  92. package/dist/audit/cli/dispatchStatusCommand.d.ts +2 -0
  93. package/dist/audit/cli/dispatchStatusCommand.d.ts.map +1 -0
  94. package/dist/audit/cli/dispatchStatusCommand.js +81 -0
  95. package/dist/audit/cli/dispatchStatusCommand.js.map +1 -0
  96. package/dist/audit/cli/envelope.d.ts +50 -0
  97. package/dist/audit/cli/envelope.d.ts.map +1 -0
  98. package/dist/audit/cli/envelope.js +69 -0
  99. package/dist/audit/cli/envelope.js.map +1 -0
  100. package/dist/audit/cli/explainTaskCommand.d.ts +2 -0
  101. package/dist/audit/cli/explainTaskCommand.d.ts.map +1 -0
  102. package/dist/audit/cli/explainTaskCommand.js +34 -0
  103. package/dist/audit/cli/explainTaskCommand.js.map +1 -0
  104. package/dist/audit/cli/importExternalAnalyzerCommand.d.ts +2 -0
  105. package/dist/audit/cli/importExternalAnalyzerCommand.d.ts.map +1 -0
  106. package/dist/audit/cli/importExternalAnalyzerCommand.js +25 -0
  107. package/dist/audit/cli/importExternalAnalyzerCommand.js.map +1 -0
  108. package/dist/audit/cli/ingestResultsCommand.d.ts +2 -0
  109. package/dist/audit/cli/ingestResultsCommand.d.ts.map +1 -0
  110. package/dist/audit/cli/ingestResultsCommand.js +42 -0
  111. package/dist/audit/cli/ingestResultsCommand.js.map +1 -0
  112. package/dist/audit/cli/intakeCommand.d.ts +2 -0
  113. package/dist/audit/cli/intakeCommand.d.ts.map +1 -0
  114. package/dist/audit/cli/intakeCommand.js +18 -0
  115. package/dist/audit/cli/intakeCommand.js.map +1 -0
  116. package/dist/audit/cli/lineIndex.d.ts +5 -0
  117. package/dist/audit/cli/lineIndex.d.ts.map +1 -0
  118. package/dist/audit/cli/lineIndex.js +70 -0
  119. package/dist/audit/cli/lineIndex.js.map +1 -0
  120. package/dist/audit/cli/mergeAndIngestCommand.d.ts +46 -0
  121. package/dist/audit/cli/mergeAndIngestCommand.d.ts.map +1 -0
  122. package/dist/audit/cli/mergeAndIngestCommand.js +541 -0
  123. package/dist/audit/cli/mergeAndIngestCommand.js.map +1 -0
  124. package/dist/audit/cli/nextStepCommand.d.ts +22 -0
  125. package/dist/audit/cli/nextStepCommand.d.ts.map +1 -0
  126. package/dist/audit/cli/nextStepCommand.js +531 -0
  127. package/dist/audit/cli/nextStepCommand.js.map +1 -0
  128. package/dist/audit/cli/nextStepHelpers.d.ts +303 -0
  129. package/dist/audit/cli/nextStepHelpers.d.ts.map +1 -0
  130. package/dist/audit/cli/nextStepHelpers.js +861 -0
  131. package/dist/audit/cli/nextStepHelpers.js.map +1 -0
  132. package/dist/audit/cli/paths.d.ts +2 -0
  133. package/dist/audit/cli/paths.d.ts.map +1 -0
  134. package/dist/audit/cli/paths.js +10 -0
  135. package/dist/audit/cli/paths.js.map +1 -0
  136. package/dist/audit/cli/planCommand.d.ts +2 -0
  137. package/dist/audit/cli/planCommand.d.ts.map +1 -0
  138. package/dist/audit/cli/planCommand.js +17 -0
  139. package/dist/audit/cli/planCommand.js.map +1 -0
  140. package/dist/audit/cli/prepareDispatchCommand.d.ts +2 -0
  141. package/dist/audit/cli/prepareDispatchCommand.d.ts.map +1 -0
  142. package/dist/audit/cli/prepareDispatchCommand.js +37 -0
  143. package/dist/audit/cli/prepareDispatchCommand.js.map +1 -0
  144. package/dist/audit/cli/prompts.d.ts +54 -0
  145. package/dist/audit/cli/prompts.d.ts.map +1 -0
  146. package/dist/audit/cli/prompts.js +324 -0
  147. package/dist/audit/cli/prompts.js.map +1 -0
  148. package/dist/audit/cli/quotaCommand.d.ts +2 -0
  149. package/dist/audit/cli/quotaCommand.d.ts.map +1 -0
  150. package/dist/audit/cli/quotaCommand.js +64 -0
  151. package/dist/audit/cli/quotaCommand.js.map +1 -0
  152. package/dist/audit/cli/requeueCommand.d.ts +2 -0
  153. package/dist/audit/cli/requeueCommand.d.ts.map +1 -0
  154. package/dist/audit/cli/requeueCommand.js +11 -0
  155. package/dist/audit/cli/requeueCommand.js.map +1 -0
  156. package/dist/audit/cli/resynthesizeCommand.d.ts +2 -0
  157. package/dist/audit/cli/resynthesizeCommand.d.ts.map +1 -0
  158. package/dist/audit/cli/resynthesizeCommand.js +57 -0
  159. package/dist/audit/cli/resynthesizeCommand.js.map +1 -0
  160. package/dist/audit/cli/reviewRun.d.ts +57 -0
  161. package/dist/audit/cli/reviewRun.d.ts.map +1 -0
  162. package/dist/audit/cli/reviewRun.js +180 -0
  163. package/dist/audit/cli/reviewRun.js.map +1 -0
  164. package/dist/audit/cli/rollingAuditDispatch.d.ts +119 -0
  165. package/dist/audit/cli/rollingAuditDispatch.d.ts.map +1 -0
  166. package/dist/audit/cli/rollingAuditDispatch.js +264 -0
  167. package/dist/audit/cli/rollingAuditDispatch.js.map +1 -0
  168. package/dist/audit/cli/sampleRunCommand.d.ts +2 -0
  169. package/dist/audit/cli/sampleRunCommand.d.ts.map +1 -0
  170. package/dist/audit/cli/sampleRunCommand.js +106 -0
  171. package/dist/audit/cli/sampleRunCommand.js.map +1 -0
  172. package/dist/audit/cli/semanticReviewStep.d.ts +23 -0
  173. package/dist/audit/cli/semanticReviewStep.d.ts.map +1 -0
  174. package/dist/audit/cli/semanticReviewStep.js +123 -0
  175. package/dist/audit/cli/semanticReviewStep.js.map +1 -0
  176. package/dist/audit/cli/statusCommand.d.ts +2 -0
  177. package/dist/audit/cli/statusCommand.d.ts.map +1 -0
  178. package/dist/audit/cli/statusCommand.js +133 -0
  179. package/dist/audit/cli/statusCommand.js.map +1 -0
  180. package/dist/audit/cli/steps.d.ts +204 -0
  181. package/dist/audit/cli/steps.d.ts.map +1 -0
  182. package/dist/audit/cli/steps.js +105 -0
  183. package/dist/audit/cli/steps.js.map +1 -0
  184. package/dist/audit/cli/submitPacketCommand.d.ts +2 -0
  185. package/dist/audit/cli/submitPacketCommand.d.ts.map +1 -0
  186. package/dist/audit/cli/submitPacketCommand.js +126 -0
  187. package/dist/audit/cli/submitPacketCommand.js.map +1 -0
  188. package/dist/audit/cli/synthesizeCommand.d.ts +2 -0
  189. package/dist/audit/cli/synthesizeCommand.d.ts.map +1 -0
  190. package/dist/audit/cli/synthesizeCommand.js +16 -0
  191. package/dist/audit/cli/synthesizeCommand.js.map +1 -0
  192. package/dist/audit/cli/updateRuntimeValidationCommand.d.ts +2 -0
  193. package/dist/audit/cli/updateRuntimeValidationCommand.d.ts.map +1 -0
  194. package/dist/audit/cli/updateRuntimeValidationCommand.js +17 -0
  195. package/dist/audit/cli/updateRuntimeValidationCommand.js.map +1 -0
  196. package/dist/audit/cli/validateCommand.d.ts +2 -0
  197. package/dist/audit/cli/validateCommand.d.ts.map +1 -0
  198. package/dist/audit/cli/validateCommand.js +42 -0
  199. package/dist/audit/cli/validateCommand.js.map +1 -0
  200. package/dist/audit/cli/validateResultCommand.d.ts +2 -0
  201. package/dist/audit/cli/validateResultCommand.d.ts.map +1 -0
  202. package/dist/audit/cli/validateResultCommand.js +92 -0
  203. package/dist/audit/cli/validateResultCommand.js.map +1 -0
  204. package/dist/audit/cli/validateResultsCommand.d.ts +2 -0
  205. package/dist/audit/cli/validateResultsCommand.d.ts.map +1 -0
  206. package/dist/audit/cli/validateResultsCommand.js +32 -0
  207. package/dist/audit/cli/validateResultsCommand.js.map +1 -0
  208. package/dist/audit/cli/waveManifest.d.ts +41 -0
  209. package/dist/audit/cli/waveManifest.d.ts.map +1 -0
  210. package/dist/audit/cli/waveManifest.js +42 -0
  211. package/dist/audit/cli/waveManifest.js.map +1 -0
  212. package/dist/audit/cli/workerResult.d.ts +19 -0
  213. package/dist/audit/cli/workerResult.d.ts.map +1 -0
  214. package/dist/audit/cli/workerResult.js +43 -0
  215. package/dist/audit/cli/workerResult.js.map +1 -0
  216. package/dist/audit/cli/workerRunCommand.d.ts +16 -0
  217. package/dist/audit/cli/workerRunCommand.d.ts.map +1 -0
  218. package/dist/audit/cli/workerRunCommand.js +132 -0
  219. package/dist/audit/cli/workerRunCommand.js.map +1 -0
  220. package/dist/audit/cli.d.ts +21 -0
  221. package/dist/audit/cli.d.ts.map +1 -0
  222. package/dist/audit/cli.js +137 -0
  223. package/dist/audit/cli.js.map +1 -0
  224. package/dist/audit/contracts/workerSchemas.d.ts +1448 -0
  225. package/dist/audit/contracts/workerSchemas.d.ts.map +1 -0
  226. package/dist/audit/contracts/workerSchemas.js +117 -0
  227. package/dist/audit/contracts/workerSchemas.js.map +1 -0
  228. package/dist/audit/contracts/wrapperResponse.d.ts +316 -0
  229. package/dist/audit/contracts/wrapperResponse.d.ts.map +1 -0
  230. package/dist/audit/contracts/wrapperResponse.js +96 -0
  231. package/dist/audit/contracts/wrapperResponse.js.map +1 -0
  232. package/dist/audit/coverage.d.ts +11 -0
  233. package/dist/audit/coverage.d.ts.map +1 -0
  234. package/dist/audit/coverage.js +78 -0
  235. package/dist/audit/coverage.js.map +1 -0
  236. package/dist/audit/extractors/analyzers/css.d.ts +3 -0
  237. package/dist/audit/extractors/analyzers/css.d.ts.map +1 -0
  238. package/dist/audit/extractors/analyzers/css.js +102 -0
  239. package/dist/audit/extractors/analyzers/css.js.map +1 -0
  240. package/dist/audit/extractors/analyzers/html.d.ts +3 -0
  241. package/dist/audit/extractors/analyzers/html.d.ts.map +1 -0
  242. package/dist/audit/extractors/analyzers/html.js +93 -0
  243. package/dist/audit/extractors/analyzers/html.js.map +1 -0
  244. package/dist/audit/extractors/analyzers/merge.d.ts +15 -0
  245. package/dist/audit/extractors/analyzers/merge.d.ts.map +1 -0
  246. package/dist/audit/extractors/analyzers/merge.js +86 -0
  247. package/dist/audit/extractors/analyzers/merge.js.map +1 -0
  248. package/dist/audit/extractors/analyzers/python.d.ts +3 -0
  249. package/dist/audit/extractors/analyzers/python.d.ts.map +1 -0
  250. package/dist/audit/extractors/analyzers/python.js +105 -0
  251. package/dist/audit/extractors/analyzers/python.js.map +1 -0
  252. package/dist/audit/extractors/analyzers/registry.d.ts +34 -0
  253. package/dist/audit/extractors/analyzers/registry.d.ts.map +1 -0
  254. package/dist/audit/extractors/analyzers/registry.js +82 -0
  255. package/dist/audit/extractors/analyzers/registry.js.map +1 -0
  256. package/dist/audit/extractors/analyzers/resourceUrl.d.ts +8 -0
  257. package/dist/audit/extractors/analyzers/resourceUrl.d.ts.map +1 -0
  258. package/dist/audit/extractors/analyzers/resourceUrl.js +26 -0
  259. package/dist/audit/extractors/analyzers/resourceUrl.js.map +1 -0
  260. package/dist/audit/extractors/analyzers/sql.d.ts +3 -0
  261. package/dist/audit/extractors/analyzers/sql.d.ts.map +1 -0
  262. package/dist/audit/extractors/analyzers/sql.js +23 -0
  263. package/dist/audit/extractors/analyzers/sql.js.map +1 -0
  264. package/dist/audit/extractors/analyzers/treeSitter.d.ts +44 -0
  265. package/dist/audit/extractors/analyzers/treeSitter.d.ts.map +1 -0
  266. package/dist/audit/extractors/analyzers/treeSitter.js +148 -0
  267. package/dist/audit/extractors/analyzers/treeSitter.js.map +1 -0
  268. package/dist/audit/extractors/analyzers/types.d.ts +54 -0
  269. package/dist/audit/extractors/analyzers/types.d.ts.map +1 -0
  270. package/dist/audit/extractors/analyzers/types.js +2 -0
  271. package/dist/audit/extractors/analyzers/types.js.map +1 -0
  272. package/dist/audit/extractors/analyzers/typescript.d.ts +3 -0
  273. package/dist/audit/extractors/analyzers/typescript.d.ts.map +1 -0
  274. package/dist/audit/extractors/analyzers/typescript.js +279 -0
  275. package/dist/audit/extractors/analyzers/typescript.js.map +1 -0
  276. package/dist/audit/extractors/browserExtension.d.ts +12 -0
  277. package/dist/audit/extractors/browserExtension.d.ts.map +1 -0
  278. package/dist/audit/extractors/browserExtension.js +388 -0
  279. package/dist/audit/extractors/browserExtension.js.map +1 -0
  280. package/dist/audit/extractors/bucketing.d.ts +12 -0
  281. package/dist/audit/extractors/bucketing.d.ts.map +1 -0
  282. package/dist/audit/extractors/bucketing.js +56 -0
  283. package/dist/audit/extractors/bucketing.js.map +1 -0
  284. package/dist/audit/extractors/designAssessment.d.ts +10 -0
  285. package/dist/audit/extractors/designAssessment.d.ts.map +1 -0
  286. package/dist/audit/extractors/designAssessment.js +280 -0
  287. package/dist/audit/extractors/designAssessment.js.map +1 -0
  288. package/dist/audit/extractors/disposition.d.ts +76 -0
  289. package/dist/audit/extractors/disposition.d.ts.map +1 -0
  290. package/dist/audit/extractors/disposition.js +265 -0
  291. package/dist/audit/extractors/disposition.js.map +1 -0
  292. package/dist/audit/extractors/fileInventory.d.ts +8 -0
  293. package/dist/audit/extractors/fileInventory.d.ts.map +1 -0
  294. package/dist/audit/extractors/fileInventory.js +36 -0
  295. package/dist/audit/extractors/fileInventory.js.map +1 -0
  296. package/dist/audit/extractors/flows.d.ts +9 -0
  297. package/dist/audit/extractors/flows.d.ts.map +1 -0
  298. package/dist/audit/extractors/flows.js +111 -0
  299. package/dist/audit/extractors/flows.js.map +1 -0
  300. package/dist/audit/extractors/fsIntake.d.ts +9 -0
  301. package/dist/audit/extractors/fsIntake.d.ts.map +1 -0
  302. package/dist/audit/extractors/fsIntake.js +95 -0
  303. package/dist/audit/extractors/fsIntake.js.map +1 -0
  304. package/dist/audit/extractors/graph.d.ts +11 -0
  305. package/dist/audit/extractors/graph.d.ts.map +1 -0
  306. package/dist/audit/extractors/graph.js +472 -0
  307. package/dist/audit/extractors/graph.js.map +1 -0
  308. package/dist/audit/extractors/graphManifestEdges/cargo.d.ts +15 -0
  309. package/dist/audit/extractors/graphManifestEdges/cargo.d.ts.map +1 -0
  310. package/dist/audit/extractors/graphManifestEdges/cargo.js +74 -0
  311. package/dist/audit/extractors/graphManifestEdges/cargo.js.map +1 -0
  312. package/dist/audit/extractors/graphManifestEdges/go.d.ts +6 -0
  313. package/dist/audit/extractors/graphManifestEdges/go.d.ts.map +1 -0
  314. package/dist/audit/extractors/graphManifestEdges/go.js +152 -0
  315. package/dist/audit/extractors/graphManifestEdges/go.js.map +1 -0
  316. package/dist/audit/extractors/graphManifestEdges/index.d.ts +9 -0
  317. package/dist/audit/extractors/graphManifestEdges/index.d.ts.map +1 -0
  318. package/dist/audit/extractors/graphManifestEdges/index.js +12 -0
  319. package/dist/audit/extractors/graphManifestEdges/index.js.map +1 -0
  320. package/dist/audit/extractors/graphManifestEdges/jsonc.d.ts +4 -0
  321. package/dist/audit/extractors/graphManifestEdges/jsonc.d.ts.map +1 -0
  322. package/dist/audit/extractors/graphManifestEdges/jsonc.js +98 -0
  323. package/dist/audit/extractors/graphManifestEdges/jsonc.js.map +1 -0
  324. package/dist/audit/extractors/graphManifestEdges/maven.d.ts +4 -0
  325. package/dist/audit/extractors/graphManifestEdges/maven.d.ts.map +1 -0
  326. package/dist/audit/extractors/graphManifestEdges/maven.js +74 -0
  327. package/dist/audit/extractors/graphManifestEdges/maven.js.map +1 -0
  328. package/dist/audit/extractors/graphManifestEdges/packageJson.d.ts +20 -0
  329. package/dist/audit/extractors/graphManifestEdges/packageJson.d.ts.map +1 -0
  330. package/dist/audit/extractors/graphManifestEdges/packageJson.js +205 -0
  331. package/dist/audit/extractors/graphManifestEdges/packageJson.js.map +1 -0
  332. package/dist/audit/extractors/graphManifestEdges/pnpm.d.ts +10 -0
  333. package/dist/audit/extractors/graphManifestEdges/pnpm.d.ts.map +1 -0
  334. package/dist/audit/extractors/graphManifestEdges/pnpm.js +18 -0
  335. package/dist/audit/extractors/graphManifestEdges/pnpm.js.map +1 -0
  336. package/dist/audit/extractors/graphManifestEdges/pyproject.d.ts +4 -0
  337. package/dist/audit/extractors/graphManifestEdges/pyproject.d.ts.map +1 -0
  338. package/dist/audit/extractors/graphManifestEdges/pyproject.js +45 -0
  339. package/dist/audit/extractors/graphManifestEdges/pyproject.js.map +1 -0
  340. package/dist/audit/extractors/graphManifestEdges/toml.d.ts +25 -0
  341. package/dist/audit/extractors/graphManifestEdges/toml.d.ts.map +1 -0
  342. package/dist/audit/extractors/graphManifestEdges/toml.js +49 -0
  343. package/dist/audit/extractors/graphManifestEdges/toml.js.map +1 -0
  344. package/dist/audit/extractors/graphManifestEdges/typescript.d.ts +4 -0
  345. package/dist/audit/extractors/graphManifestEdges/typescript.d.ts.map +1 -0
  346. package/dist/audit/extractors/graphManifestEdges/typescript.js +57 -0
  347. package/dist/audit/extractors/graphManifestEdges/typescript.js.map +1 -0
  348. package/dist/audit/extractors/graphManifestEdges/workspace.d.ts +11 -0
  349. package/dist/audit/extractors/graphManifestEdges/workspace.d.ts.map +1 -0
  350. package/dist/audit/extractors/graphManifestEdges/workspace.js +73 -0
  351. package/dist/audit/extractors/graphManifestEdges/workspace.js.map +1 -0
  352. package/dist/audit/extractors/graphManifestEdges/yaml.d.ts +24 -0
  353. package/dist/audit/extractors/graphManifestEdges/yaml.d.ts.map +1 -0
  354. package/dist/audit/extractors/graphManifestEdges/yaml.js +57 -0
  355. package/dist/audit/extractors/graphManifestEdges/yaml.js.map +1 -0
  356. package/dist/audit/extractors/graphManifestEdges/yamlPaths.d.ts +5 -0
  357. package/dist/audit/extractors/graphManifestEdges/yamlPaths.d.ts.map +1 -0
  358. package/dist/audit/extractors/graphManifestEdges/yamlPaths.js +75 -0
  359. package/dist/audit/extractors/graphManifestEdges/yamlPaths.js.map +1 -0
  360. package/dist/audit/extractors/graphPathUtils.d.ts +34 -0
  361. package/dist/audit/extractors/graphPathUtils.d.ts.map +1 -0
  362. package/dist/audit/extractors/graphPathUtils.js +174 -0
  363. package/dist/audit/extractors/graphPathUtils.js.map +1 -0
  364. package/dist/audit/extractors/graphPythonImports.d.ts +19 -0
  365. package/dist/audit/extractors/graphPythonImports.d.ts.map +1 -0
  366. package/dist/audit/extractors/graphPythonImports.js +318 -0
  367. package/dist/audit/extractors/graphPythonImports.js.map +1 -0
  368. package/dist/audit/extractors/graphRoutes.d.ts +13 -0
  369. package/dist/audit/extractors/graphRoutes.d.ts.map +1 -0
  370. package/dist/audit/extractors/graphRoutes.js +447 -0
  371. package/dist/audit/extractors/graphRoutes.js.map +1 -0
  372. package/dist/audit/extractors/graphSuites.d.ts +5 -0
  373. package/dist/audit/extractors/graphSuites.d.ts.map +1 -0
  374. package/dist/audit/extractors/graphSuites.js +248 -0
  375. package/dist/audit/extractors/graphSuites.js.map +1 -0
  376. package/dist/audit/extractors/graphTestSources.d.ts +3 -0
  377. package/dist/audit/extractors/graphTestSources.d.ts.map +1 -0
  378. package/dist/audit/extractors/graphTestSources.js +103 -0
  379. package/dist/audit/extractors/graphTestSources.js.map +1 -0
  380. package/dist/audit/extractors/ignore.d.ts +2 -0
  381. package/dist/audit/extractors/ignore.d.ts.map +1 -0
  382. package/dist/audit/extractors/ignore.js +18 -0
  383. package/dist/audit/extractors/ignore.js.map +1 -0
  384. package/dist/audit/extractors/languageMap.generated.d.ts +2 -0
  385. package/dist/audit/extractors/languageMap.generated.d.ts.map +1 -0
  386. package/dist/audit/extractors/languageMap.generated.js +1456 -0
  387. package/dist/audit/extractors/languageMap.generated.js.map +1 -0
  388. package/dist/audit/extractors/pathPatterns.d.ts +55 -0
  389. package/dist/audit/extractors/pathPatterns.d.ts.map +1 -0
  390. package/dist/audit/extractors/pathPatterns.js +303 -0
  391. package/dist/audit/extractors/pathPatterns.js.map +1 -0
  392. package/dist/audit/extractors/risk.d.ts +5 -0
  393. package/dist/audit/extractors/risk.d.ts.map +1 -0
  394. package/dist/audit/extractors/risk.js +54 -0
  395. package/dist/audit/extractors/risk.js.map +1 -0
  396. package/dist/audit/extractors/surfaces.d.ts +10 -0
  397. package/dist/audit/extractors/surfaces.d.ts.map +1 -0
  398. package/dist/audit/extractors/surfaces.js +49 -0
  399. package/dist/audit/extractors/surfaces.js.map +1 -0
  400. package/dist/audit/index.d.ts +2 -0
  401. package/dist/audit/index.d.ts.map +1 -0
  402. package/dist/audit/index.js +3 -0
  403. package/dist/audit/index.js.map +1 -0
  404. package/dist/audit/io/artifacts.d.ts +152 -0
  405. package/dist/audit/io/artifacts.d.ts.map +1 -0
  406. package/dist/audit/io/artifacts.js +239 -0
  407. package/dist/audit/io/artifacts.js.map +1 -0
  408. package/dist/audit/io/runArtifactTypes.d.ts +19 -0
  409. package/dist/audit/io/runArtifactTypes.d.ts.map +1 -0
  410. package/dist/audit/io/runArtifactTypes.js +2 -0
  411. package/dist/audit/io/runArtifactTypes.js.map +1 -0
  412. package/dist/audit/io/runArtifacts.d.ts +33 -0
  413. package/dist/audit/io/runArtifacts.d.ts.map +1 -0
  414. package/dist/audit/io/runArtifacts.js +254 -0
  415. package/dist/audit/io/runArtifacts.js.map +1 -0
  416. package/dist/audit/io/toolingManifest.d.ts +4 -0
  417. package/dist/audit/io/toolingManifest.d.ts.map +1 -0
  418. package/dist/audit/io/toolingManifest.js +79 -0
  419. package/dist/audit/io/toolingManifest.js.map +1 -0
  420. package/dist/audit/orchestrator/advance.d.ts +5 -0
  421. package/dist/audit/orchestrator/advance.d.ts.map +1 -0
  422. package/dist/audit/orchestrator/advance.js +172 -0
  423. package/dist/audit/orchestrator/advance.js.map +1 -0
  424. package/dist/audit/orchestrator/advanceTypes.d.ts +50 -0
  425. package/dist/audit/orchestrator/advanceTypes.d.ts.map +1 -0
  426. package/dist/audit/orchestrator/advanceTypes.js +2 -0
  427. package/dist/audit/orchestrator/advanceTypes.js.map +1 -0
  428. package/dist/audit/orchestrator/artifactFreshness.d.ts +4 -0
  429. package/dist/audit/orchestrator/artifactFreshness.d.ts.map +1 -0
  430. package/dist/audit/orchestrator/artifactFreshness.js +99 -0
  431. package/dist/audit/orchestrator/artifactFreshness.js.map +1 -0
  432. package/dist/audit/orchestrator/artifactMetadata.d.ts +6 -0
  433. package/dist/audit/orchestrator/artifactMetadata.d.ts.map +1 -0
  434. package/dist/audit/orchestrator/artifactMetadata.js +98 -0
  435. package/dist/audit/orchestrator/artifactMetadata.js.map +1 -0
  436. package/dist/audit/orchestrator/auditTaskUtils.d.ts +10 -0
  437. package/dist/audit/orchestrator/auditTaskUtils.d.ts.map +1 -0
  438. package/dist/audit/orchestrator/auditTaskUtils.js +53 -0
  439. package/dist/audit/orchestrator/auditTaskUtils.js.map +1 -0
  440. package/dist/audit/orchestrator/autoFixExecutor.d.ts +4 -0
  441. package/dist/audit/orchestrator/autoFixExecutor.d.ts.map +1 -0
  442. package/dist/audit/orchestrator/autoFixExecutor.js +152 -0
  443. package/dist/audit/orchestrator/autoFixExecutor.js.map +1 -0
  444. package/dist/audit/orchestrator/chunking.d.ts +6 -0
  445. package/dist/audit/orchestrator/chunking.d.ts.map +1 -0
  446. package/dist/audit/orchestrator/chunking.js +14 -0
  447. package/dist/audit/orchestrator/chunking.js.map +1 -0
  448. package/dist/audit/orchestrator/dependencyMap.d.ts +74 -0
  449. package/dist/audit/orchestrator/dependencyMap.d.ts.map +1 -0
  450. package/dist/audit/orchestrator/dependencyMap.js +193 -0
  451. package/dist/audit/orchestrator/dependencyMap.js.map +1 -0
  452. package/dist/audit/orchestrator/designReviewProjection.d.ts +66 -0
  453. package/dist/audit/orchestrator/designReviewProjection.d.ts.map +1 -0
  454. package/dist/audit/orchestrator/designReviewProjection.js +215 -0
  455. package/dist/audit/orchestrator/designReviewProjection.js.map +1 -0
  456. package/dist/audit/orchestrator/designReviewPrompt.d.ts +82 -0
  457. package/dist/audit/orchestrator/designReviewPrompt.d.ts.map +1 -0
  458. package/dist/audit/orchestrator/designReviewPrompt.js +474 -0
  459. package/dist/audit/orchestrator/designReviewPrompt.js.map +1 -0
  460. package/dist/audit/orchestrator/designReviewSnapshot.d.ts +69 -0
  461. package/dist/audit/orchestrator/designReviewSnapshot.d.ts.map +1 -0
  462. package/dist/audit/orchestrator/designReviewSnapshot.js +135 -0
  463. package/dist/audit/orchestrator/designReviewSnapshot.js.map +1 -0
  464. package/dist/audit/orchestrator/edgeReasoning.d.ts +40 -0
  465. package/dist/audit/orchestrator/edgeReasoning.d.ts.map +1 -0
  466. package/dist/audit/orchestrator/edgeReasoning.js +126 -0
  467. package/dist/audit/orchestrator/edgeReasoning.js.map +1 -0
  468. package/dist/audit/orchestrator/executorResult.d.ts +71 -0
  469. package/dist/audit/orchestrator/executorResult.d.ts.map +1 -0
  470. package/dist/audit/orchestrator/executorResult.js +2 -0
  471. package/dist/audit/orchestrator/executorResult.js.map +1 -0
  472. package/dist/audit/orchestrator/executorRunners.d.ts +34 -0
  473. package/dist/audit/orchestrator/executorRunners.d.ts.map +1 -0
  474. package/dist/audit/orchestrator/executorRunners.js +85 -0
  475. package/dist/audit/orchestrator/executorRunners.js.map +1 -0
  476. package/dist/audit/orchestrator/executors.d.ts +13 -0
  477. package/dist/audit/orchestrator/executors.d.ts.map +1 -0
  478. package/dist/audit/orchestrator/executors.js +114 -0
  479. package/dist/audit/orchestrator/executors.js.map +1 -0
  480. package/dist/audit/orchestrator/fileAnchors.d.ts +33 -0
  481. package/dist/audit/orchestrator/fileAnchors.d.ts.map +1 -0
  482. package/dist/audit/orchestrator/fileAnchors.js +242 -0
  483. package/dist/audit/orchestrator/fileAnchors.js.map +1 -0
  484. package/dist/audit/orchestrator/fileIntegrity.d.ts +9 -0
  485. package/dist/audit/orchestrator/fileIntegrity.d.ts.map +1 -0
  486. package/dist/audit/orchestrator/fileIntegrity.js +58 -0
  487. package/dist/audit/orchestrator/fileIntegrity.js.map +1 -0
  488. package/dist/audit/orchestrator/flowCoverage.d.ts +5 -0
  489. package/dist/audit/orchestrator/flowCoverage.d.ts.map +1 -0
  490. package/dist/audit/orchestrator/flowCoverage.js +46 -0
  491. package/dist/audit/orchestrator/flowCoverage.js.map +1 -0
  492. package/dist/audit/orchestrator/flowPlanning.d.ts +8 -0
  493. package/dist/audit/orchestrator/flowPlanning.d.ts.map +1 -0
  494. package/dist/audit/orchestrator/flowPlanning.js +65 -0
  495. package/dist/audit/orchestrator/flowPlanning.js.map +1 -0
  496. package/dist/audit/orchestrator/flowRequeue.d.ts +6 -0
  497. package/dist/audit/orchestrator/flowRequeue.d.ts.map +1 -0
  498. package/dist/audit/orchestrator/flowRequeue.js +73 -0
  499. package/dist/audit/orchestrator/flowRequeue.js.map +1 -0
  500. package/dist/audit/orchestrator/graphEnrichmentExecutor.d.ts +30 -0
  501. package/dist/audit/orchestrator/graphEnrichmentExecutor.d.ts.map +1 -0
  502. package/dist/audit/orchestrator/graphEnrichmentExecutor.js +227 -0
  503. package/dist/audit/orchestrator/graphEnrichmentExecutor.js.map +1 -0
  504. package/dist/audit/orchestrator/ingestionExecutors.d.ts +10 -0
  505. package/dist/audit/orchestrator/ingestionExecutors.d.ts.map +1 -0
  506. package/dist/audit/orchestrator/ingestionExecutors.js +262 -0
  507. package/dist/audit/orchestrator/ingestionExecutors.js.map +1 -0
  508. package/dist/audit/orchestrator/intakeExecutors.d.ts +26 -0
  509. package/dist/audit/orchestrator/intakeExecutors.d.ts.map +1 -0
  510. package/dist/audit/orchestrator/intakeExecutors.js +138 -0
  511. package/dist/audit/orchestrator/intakeExecutors.js.map +1 -0
  512. package/dist/audit/orchestrator/intentCheckpointExecutor.d.ts +89 -0
  513. package/dist/audit/orchestrator/intentCheckpointExecutor.d.ts.map +1 -0
  514. package/dist/audit/orchestrator/intentCheckpointExecutor.js +264 -0
  515. package/dist/audit/orchestrator/intentCheckpointExecutor.js.map +1 -0
  516. package/dist/audit/orchestrator/intentInterpreter.d.ts +49 -0
  517. package/dist/audit/orchestrator/intentInterpreter.d.ts.map +1 -0
  518. package/dist/audit/orchestrator/intentInterpreter.js +110 -0
  519. package/dist/audit/orchestrator/intentInterpreter.js.map +1 -0
  520. package/dist/audit/orchestrator/lensSelection.d.ts +35 -0
  521. package/dist/audit/orchestrator/lensSelection.d.ts.map +1 -0
  522. package/dist/audit/orchestrator/lensSelection.js +81 -0
  523. package/dist/audit/orchestrator/lensSelection.js.map +1 -0
  524. package/dist/audit/orchestrator/localCommands.d.ts +16 -0
  525. package/dist/audit/orchestrator/localCommands.d.ts.map +1 -0
  526. package/dist/audit/orchestrator/localCommands.js +113 -0
  527. package/dist/audit/orchestrator/localCommands.js.map +1 -0
  528. package/dist/audit/orchestrator/nextStep.d.ts +12 -0
  529. package/dist/audit/orchestrator/nextStep.d.ts.map +1 -0
  530. package/dist/audit/orchestrator/nextStep.js +63 -0
  531. package/dist/audit/orchestrator/nextStep.js.map +1 -0
  532. package/dist/audit/orchestrator/partitionTaskGraph.d.ts +32 -0
  533. package/dist/audit/orchestrator/partitionTaskGraph.d.ts.map +1 -0
  534. package/dist/audit/orchestrator/partitionTaskGraph.js +98 -0
  535. package/dist/audit/orchestrator/partitionTaskGraph.js.map +1 -0
  536. package/dist/audit/orchestrator/planning.d.ts +5 -0
  537. package/dist/audit/orchestrator/planning.d.ts.map +1 -0
  538. package/dist/audit/orchestrator/planning.js +81 -0
  539. package/dist/audit/orchestrator/planning.js.map +1 -0
  540. package/dist/audit/orchestrator/planningExecutors.d.ts +21 -0
  541. package/dist/audit/orchestrator/planningExecutors.d.ts.map +1 -0
  542. package/dist/audit/orchestrator/planningExecutors.js +228 -0
  543. package/dist/audit/orchestrator/planningExecutors.js.map +1 -0
  544. package/dist/audit/orchestrator/providerConfirmation.d.ts +21 -0
  545. package/dist/audit/orchestrator/providerConfirmation.d.ts.map +1 -0
  546. package/dist/audit/orchestrator/providerConfirmation.js +54 -0
  547. package/dist/audit/orchestrator/providerConfirmation.js.map +1 -0
  548. package/dist/audit/orchestrator/requeue.d.ts +4 -0
  549. package/dist/audit/orchestrator/requeue.d.ts.map +1 -0
  550. package/dist/audit/orchestrator/requeue.js +33 -0
  551. package/dist/audit/orchestrator/requeue.js.map +1 -0
  552. package/dist/audit/orchestrator/requeueCommand.d.ts +32 -0
  553. package/dist/audit/orchestrator/requeueCommand.d.ts.map +1 -0
  554. package/dist/audit/orchestrator/requeueCommand.js +45 -0
  555. package/dist/audit/orchestrator/requeueCommand.js.map +1 -0
  556. package/dist/audit/orchestrator/requeueUtils.d.ts +14 -0
  557. package/dist/audit/orchestrator/requeueUtils.d.ts.map +1 -0
  558. package/dist/audit/orchestrator/requeueUtils.js +22 -0
  559. package/dist/audit/orchestrator/requeueUtils.js.map +1 -0
  560. package/dist/audit/orchestrator/resultIngestion.d.ts +18 -0
  561. package/dist/audit/orchestrator/resultIngestion.d.ts.map +1 -0
  562. package/dist/audit/orchestrator/resultIngestion.js +63 -0
  563. package/dist/audit/orchestrator/resultIngestion.js.map +1 -0
  564. package/dist/audit/orchestrator/reviewPacketGraph.d.ts +5 -0
  565. package/dist/audit/orchestrator/reviewPacketGraph.d.ts.map +1 -0
  566. package/dist/audit/orchestrator/reviewPacketGraph.js +11 -0
  567. package/dist/audit/orchestrator/reviewPacketGraph.js.map +1 -0
  568. package/dist/audit/orchestrator/reviewPacketGraphClustering.d.ts +4 -0
  569. package/dist/audit/orchestrator/reviewPacketGraphClustering.d.ts.map +1 -0
  570. package/dist/audit/orchestrator/reviewPacketGraphClustering.js +481 -0
  571. package/dist/audit/orchestrator/reviewPacketGraphClustering.js.map +1 -0
  572. package/dist/audit/orchestrator/reviewPacketGraphContext.d.ts +10 -0
  573. package/dist/audit/orchestrator/reviewPacketGraphContext.d.ts.map +1 -0
  574. package/dist/audit/orchestrator/reviewPacketGraphContext.js +95 -0
  575. package/dist/audit/orchestrator/reviewPacketGraphContext.js.map +1 -0
  576. package/dist/audit/orchestrator/reviewPacketGraphEdges.d.ts +23 -0
  577. package/dist/audit/orchestrator/reviewPacketGraphEdges.d.ts.map +1 -0
  578. package/dist/audit/orchestrator/reviewPacketGraphEdges.js +169 -0
  579. package/dist/audit/orchestrator/reviewPacketGraphEdges.js.map +1 -0
  580. package/dist/audit/orchestrator/reviewPacketMetrics.d.ts +17 -0
  581. package/dist/audit/orchestrator/reviewPacketMetrics.d.ts.map +1 -0
  582. package/dist/audit/orchestrator/reviewPacketMetrics.js +322 -0
  583. package/dist/audit/orchestrator/reviewPacketMetrics.js.map +1 -0
  584. package/dist/audit/orchestrator/reviewPacketSizing.d.ts +27 -0
  585. package/dist/audit/orchestrator/reviewPacketSizing.d.ts.map +1 -0
  586. package/dist/audit/orchestrator/reviewPacketSizing.js +64 -0
  587. package/dist/audit/orchestrator/reviewPacketSizing.js.map +1 -0
  588. package/dist/audit/orchestrator/reviewPackets.d.ts +54 -0
  589. package/dist/audit/orchestrator/reviewPackets.d.ts.map +1 -0
  590. package/dist/audit/orchestrator/reviewPackets.js +318 -0
  591. package/dist/audit/orchestrator/reviewPackets.js.map +1 -0
  592. package/dist/audit/orchestrator/rollingDispatch.d.ts +45 -0
  593. package/dist/audit/orchestrator/rollingDispatch.d.ts.map +1 -0
  594. package/dist/audit/orchestrator/rollingDispatch.js +103 -0
  595. package/dist/audit/orchestrator/rollingDispatch.js.map +1 -0
  596. package/dist/audit/orchestrator/runtimeCommand.d.ts +10 -0
  597. package/dist/audit/orchestrator/runtimeCommand.d.ts.map +1 -0
  598. package/dist/audit/orchestrator/runtimeCommand.js +129 -0
  599. package/dist/audit/orchestrator/runtimeCommand.js.map +1 -0
  600. package/dist/audit/orchestrator/runtimeValidation.d.ts +13 -0
  601. package/dist/audit/orchestrator/runtimeValidation.d.ts.map +1 -0
  602. package/dist/audit/orchestrator/runtimeValidation.js +94 -0
  603. package/dist/audit/orchestrator/runtimeValidation.js.map +1 -0
  604. package/dist/audit/orchestrator/runtimeValidationUpdate.d.ts +3 -0
  605. package/dist/audit/orchestrator/runtimeValidationUpdate.d.ts.map +1 -0
  606. package/dist/audit/orchestrator/runtimeValidationUpdate.js +57 -0
  607. package/dist/audit/orchestrator/runtimeValidationUpdate.js.map +1 -0
  608. package/dist/audit/orchestrator/scope.d.ts +75 -0
  609. package/dist/audit/orchestrator/scope.d.ts.map +1 -0
  610. package/dist/audit/orchestrator/scope.js +268 -0
  611. package/dist/audit/orchestrator/scope.js.map +1 -0
  612. package/dist/audit/orchestrator/selectiveDeepening/conflict.d.ts +9 -0
  613. package/dist/audit/orchestrator/selectiveDeepening/conflict.d.ts.map +1 -0
  614. package/dist/audit/orchestrator/selectiveDeepening/conflict.js +72 -0
  615. package/dist/audit/orchestrator/selectiveDeepening/conflict.js.map +1 -0
  616. package/dist/audit/orchestrator/selectiveDeepening/findingFollowup.d.ts +11 -0
  617. package/dist/audit/orchestrator/selectiveDeepening/findingFollowup.d.ts.map +1 -0
  618. package/dist/audit/orchestrator/selectiveDeepening/findingFollowup.js +53 -0
  619. package/dist/audit/orchestrator/selectiveDeepening/findingFollowup.js.map +1 -0
  620. package/dist/audit/orchestrator/selectiveDeepening/highRiskClean.d.ts +8 -0
  621. package/dist/audit/orchestrator/selectiveDeepening/highRiskClean.d.ts.map +1 -0
  622. package/dist/audit/orchestrator/selectiveDeepening/highRiskClean.js +46 -0
  623. package/dist/audit/orchestrator/selectiveDeepening/highRiskClean.js.map +1 -0
  624. package/dist/audit/orchestrator/selectiveDeepening/index.d.ts +25 -0
  625. package/dist/audit/orchestrator/selectiveDeepening/index.d.ts.map +1 -0
  626. package/dist/audit/orchestrator/selectiveDeepening/index.js +157 -0
  627. package/dist/audit/orchestrator/selectiveDeepening/index.js.map +1 -0
  628. package/dist/audit/orchestrator/selectiveDeepening/lensVerification.d.ts +13 -0
  629. package/dist/audit/orchestrator/selectiveDeepening/lensVerification.d.ts.map +1 -0
  630. package/dist/audit/orchestrator/selectiveDeepening/lensVerification.js +269 -0
  631. package/dist/audit/orchestrator/selectiveDeepening/lensVerification.js.map +1 -0
  632. package/dist/audit/orchestrator/selectiveDeepening/runtimeValidation.d.ts +14 -0
  633. package/dist/audit/orchestrator/selectiveDeepening/runtimeValidation.d.ts.map +1 -0
  634. package/dist/audit/orchestrator/selectiveDeepening/runtimeValidation.js +58 -0
  635. package/dist/audit/orchestrator/selectiveDeepening/runtimeValidation.js.map +1 -0
  636. package/dist/audit/orchestrator/selectiveDeepening/shared.d.ts +42 -0
  637. package/dist/audit/orchestrator/selectiveDeepening/shared.d.ts.map +1 -0
  638. package/dist/audit/orchestrator/selectiveDeepening/shared.js +121 -0
  639. package/dist/audit/orchestrator/selectiveDeepening/shared.js.map +1 -0
  640. package/dist/audit/orchestrator/selectiveDeepening/stewardFollowup.d.ts +7 -0
  641. package/dist/audit/orchestrator/selectiveDeepening/stewardFollowup.d.ts.map +1 -0
  642. package/dist/audit/orchestrator/selectiveDeepening/stewardFollowup.js +73 -0
  643. package/dist/audit/orchestrator/selectiveDeepening/stewardFollowup.js.map +1 -0
  644. package/dist/audit/orchestrator/selectiveDeepening.d.ts +3 -0
  645. package/dist/audit/orchestrator/selectiveDeepening.d.ts.map +1 -0
  646. package/dist/audit/orchestrator/selectiveDeepening.js +7 -0
  647. package/dist/audit/orchestrator/selectiveDeepening.js.map +1 -0
  648. package/dist/audit/orchestrator/staleness.d.ts +3 -0
  649. package/dist/audit/orchestrator/staleness.d.ts.map +1 -0
  650. package/dist/audit/orchestrator/staleness.js +102 -0
  651. package/dist/audit/orchestrator/staleness.js.map +1 -0
  652. package/dist/audit/orchestrator/state.d.ts +4 -0
  653. package/dist/audit/orchestrator/state.d.ts.map +1 -0
  654. package/dist/audit/orchestrator/state.js +158 -0
  655. package/dist/audit/orchestrator/state.js.map +1 -0
  656. package/dist/audit/orchestrator/structureExecutors.d.ts +6 -0
  657. package/dist/audit/orchestrator/structureExecutors.d.ts.map +1 -0
  658. package/dist/audit/orchestrator/structureExecutors.js +116 -0
  659. package/dist/audit/orchestrator/structureExecutors.js.map +1 -0
  660. package/dist/audit/orchestrator/syntaxResolutionExecutor.d.ts +4 -0
  661. package/dist/audit/orchestrator/syntaxResolutionExecutor.d.ts.map +1 -0
  662. package/dist/audit/orchestrator/syntaxResolutionExecutor.js +260 -0
  663. package/dist/audit/orchestrator/syntaxResolutionExecutor.js.map +1 -0
  664. package/dist/audit/orchestrator/synthesisExecutors.d.ts +13 -0
  665. package/dist/audit/orchestrator/synthesisExecutors.d.ts.map +1 -0
  666. package/dist/audit/orchestrator/synthesisExecutors.js +107 -0
  667. package/dist/audit/orchestrator/synthesisExecutors.js.map +1 -0
  668. package/dist/audit/orchestrator/taskAffinityGraph.d.ts +154 -0
  669. package/dist/audit/orchestrator/taskAffinityGraph.d.ts.map +1 -0
  670. package/dist/audit/orchestrator/taskAffinityGraph.js +216 -0
  671. package/dist/audit/orchestrator/taskAffinityGraph.js.map +1 -0
  672. package/dist/audit/orchestrator/taskBuilder.d.ts +43 -0
  673. package/dist/audit/orchestrator/taskBuilder.d.ts.map +1 -0
  674. package/dist/audit/orchestrator/taskBuilder.js +355 -0
  675. package/dist/audit/orchestrator/taskBuilder.js.map +1 -0
  676. package/dist/audit/orchestrator/trivialAudit.d.ts +5 -0
  677. package/dist/audit/orchestrator/trivialAudit.d.ts.map +1 -0
  678. package/dist/audit/orchestrator/trivialAudit.js +50 -0
  679. package/dist/audit/orchestrator/trivialAudit.js.map +1 -0
  680. package/dist/audit/orchestrator/unionFind.d.ts +8 -0
  681. package/dist/audit/orchestrator/unionFind.d.ts.map +1 -0
  682. package/dist/audit/orchestrator/unionFind.js +43 -0
  683. package/dist/audit/orchestrator/unionFind.js.map +1 -0
  684. package/dist/audit/orchestrator/unitBuilder.d.ts +8 -0
  685. package/dist/audit/orchestrator/unitBuilder.d.ts.map +1 -0
  686. package/dist/audit/orchestrator/unitBuilder.js +171 -0
  687. package/dist/audit/orchestrator/unitBuilder.js.map +1 -0
  688. package/dist/audit/orchestrator.d.ts +7 -0
  689. package/dist/audit/orchestrator.d.ts.map +1 -0
  690. package/dist/audit/orchestrator.js +68 -0
  691. package/dist/audit/orchestrator.js.map +1 -0
  692. package/dist/audit/prompts/renderWorkerPrompt.d.ts +3 -0
  693. package/dist/audit/prompts/renderWorkerPrompt.d.ts.map +1 -0
  694. package/dist/audit/prompts/renderWorkerPrompt.js +87 -0
  695. package/dist/audit/prompts/renderWorkerPrompt.js.map +1 -0
  696. package/dist/audit/providers/claudeCodeProvider.d.ts +11 -0
  697. package/dist/audit/providers/claudeCodeProvider.d.ts.map +1 -0
  698. package/dist/audit/providers/claudeCodeProvider.js +23 -0
  699. package/dist/audit/providers/claudeCodeProvider.js.map +1 -0
  700. package/dist/audit/providers/constants.d.ts +2 -0
  701. package/dist/audit/providers/constants.d.ts.map +1 -0
  702. package/dist/audit/providers/constants.js +2 -0
  703. package/dist/audit/providers/constants.js.map +1 -0
  704. package/dist/audit/providers/index.d.ts +14 -0
  705. package/dist/audit/providers/index.d.ts.map +1 -0
  706. package/dist/audit/providers/index.js +21 -0
  707. package/dist/audit/providers/index.js.map +1 -0
  708. package/dist/audit/providers/opencodeProvider.d.ts +5 -0
  709. package/dist/audit/providers/opencodeProvider.d.ts.map +1 -0
  710. package/dist/audit/providers/opencodeProvider.js +10 -0
  711. package/dist/audit/providers/opencodeProvider.js.map +1 -0
  712. package/dist/audit/quota/discoveredLimits.d.ts +27 -0
  713. package/dist/audit/quota/discoveredLimits.d.ts.map +1 -0
  714. package/dist/audit/quota/discoveredLimits.js +91 -0
  715. package/dist/audit/quota/discoveredLimits.js.map +1 -0
  716. package/dist/audit/quota/headerExtraction.d.ts +9 -0
  717. package/dist/audit/quota/headerExtraction.d.ts.map +1 -0
  718. package/dist/audit/quota/headerExtraction.js +148 -0
  719. package/dist/audit/quota/headerExtraction.js.map +1 -0
  720. package/dist/audit/quota/headerExtractors/claudeCodeHeaderExtractor.d.ts +7 -0
  721. package/dist/audit/quota/headerExtractors/claudeCodeHeaderExtractor.d.ts.map +1 -0
  722. package/dist/audit/quota/headerExtractors/claudeCodeHeaderExtractor.js +27 -0
  723. package/dist/audit/quota/headerExtractors/claudeCodeHeaderExtractor.js.map +1 -0
  724. package/dist/audit/quota/headerExtractors/genericHeaderExtractor.d.ts +10 -0
  725. package/dist/audit/quota/headerExtractors/genericHeaderExtractor.d.ts.map +1 -0
  726. package/dist/audit/quota/headerExtractors/genericHeaderExtractor.js +8 -0
  727. package/dist/audit/quota/headerExtractors/genericHeaderExtractor.js.map +1 -0
  728. package/dist/audit/quota/headerExtractors/index.d.ts +6 -0
  729. package/dist/audit/quota/headerExtractors/index.d.ts.map +1 -0
  730. package/dist/audit/quota/headerExtractors/index.js +11 -0
  731. package/dist/audit/quota/headerExtractors/index.js.map +1 -0
  732. package/dist/audit/quota/hostLimits.d.ts +8 -0
  733. package/dist/audit/quota/hostLimits.d.ts.map +1 -0
  734. package/dist/audit/quota/hostLimits.js +9 -0
  735. package/dist/audit/quota/hostLimits.js.map +1 -0
  736. package/dist/audit/quota/index.d.ts +383 -0
  737. package/dist/audit/quota/index.d.ts.map +1 -0
  738. package/dist/audit/quota/index.js +45 -0
  739. package/dist/audit/quota/index.js.map +1 -0
  740. package/dist/audit/reporting/findingIdentity.d.ts +34 -0
  741. package/dist/audit/reporting/findingIdentity.d.ts.map +1 -0
  742. package/dist/audit/reporting/findingIdentity.js +64 -0
  743. package/dist/audit/reporting/findingIdentity.js.map +1 -0
  744. package/dist/audit/reporting/findingRanks.d.ts +2 -0
  745. package/dist/audit/reporting/findingRanks.d.ts.map +1 -0
  746. package/dist/audit/reporting/findingRanks.js +7 -0
  747. package/dist/audit/reporting/findingRanks.js.map +1 -0
  748. package/dist/audit/reporting/mergeFindings.d.ts +6 -0
  749. package/dist/audit/reporting/mergeFindings.d.ts.map +1 -0
  750. package/dist/audit/reporting/mergeFindings.js +326 -0
  751. package/dist/audit/reporting/mergeFindings.js.map +1 -0
  752. package/dist/audit/reporting/synthesis.d.ts +124 -0
  753. package/dist/audit/reporting/synthesis.d.ts.map +1 -0
  754. package/dist/audit/reporting/synthesis.js +369 -0
  755. package/dist/audit/reporting/synthesis.js.map +1 -0
  756. package/dist/audit/reporting/synthesisNarrativePrompt.d.ts +8 -0
  757. package/dist/audit/reporting/synthesisNarrativePrompt.d.ts.map +1 -0
  758. package/dist/audit/reporting/synthesisNarrativePrompt.js +66 -0
  759. package/dist/audit/reporting/synthesisNarrativePrompt.js.map +1 -0
  760. package/dist/audit/reporting/workBlocks.d.ts +10 -0
  761. package/dist/audit/reporting/workBlocks.d.ts.map +1 -0
  762. package/dist/audit/reporting/workBlocks.js +154 -0
  763. package/dist/audit/reporting/workBlocks.js.map +1 -0
  764. package/dist/audit/supervisor/operatorHandoff.d.ts +65 -0
  765. package/dist/audit/supervisor/operatorHandoff.d.ts.map +1 -0
  766. package/dist/audit/supervisor/operatorHandoff.js +277 -0
  767. package/dist/audit/supervisor/operatorHandoff.js.map +1 -0
  768. package/dist/audit/supervisor/runLedger.d.ts +4 -0
  769. package/dist/audit/supervisor/runLedger.d.ts.map +1 -0
  770. package/dist/audit/supervisor/runLedger.js +118 -0
  771. package/dist/audit/supervisor/runLedger.js.map +1 -0
  772. package/dist/audit/supervisor/sessionConfig.d.ts +12 -0
  773. package/dist/audit/supervisor/sessionConfig.d.ts.map +1 -0
  774. package/dist/audit/supervisor/sessionConfig.js +49 -0
  775. package/dist/audit/supervisor/sessionConfig.js.map +1 -0
  776. package/dist/audit/types/activeDispatch.d.ts +36 -0
  777. package/dist/audit/types/activeDispatch.d.ts.map +1 -0
  778. package/dist/audit/types/activeDispatch.js +3 -0
  779. package/dist/audit/types/activeDispatch.js.map +1 -0
  780. package/dist/audit/types/analyzerCapability.d.ts +17 -0
  781. package/dist/audit/types/analyzerCapability.d.ts.map +1 -0
  782. package/dist/audit/types/analyzerCapability.js +2 -0
  783. package/dist/audit/types/analyzerCapability.js.map +1 -0
  784. package/dist/audit/types/artifactMetadata.d.ts +9 -0
  785. package/dist/audit/types/artifactMetadata.d.ts.map +1 -0
  786. package/dist/audit/types/artifactMetadata.js +2 -0
  787. package/dist/audit/types/artifactMetadata.js.map +1 -0
  788. package/dist/audit/types/auditScope.d.ts +58 -0
  789. package/dist/audit/types/auditScope.d.ts.map +1 -0
  790. package/dist/audit/types/auditScope.js +15 -0
  791. package/dist/audit/types/auditScope.js.map +1 -0
  792. package/dist/audit/types/auditState.d.ts +18 -0
  793. package/dist/audit/types/auditState.d.ts.map +1 -0
  794. package/dist/audit/types/auditState.js +2 -0
  795. package/dist/audit/types/auditState.js.map +1 -0
  796. package/dist/audit/types/designAssessment.d.ts +22 -0
  797. package/dist/audit/types/designAssessment.d.ts.map +1 -0
  798. package/dist/audit/types/designAssessment.js +8 -0
  799. package/dist/audit/types/designAssessment.js.map +1 -0
  800. package/dist/audit/types/externalAnalyzer.d.ts +225 -0
  801. package/dist/audit/types/externalAnalyzer.d.ts.map +1 -0
  802. package/dist/audit/types/externalAnalyzer.js +56 -0
  803. package/dist/audit/types/externalAnalyzer.js.map +1 -0
  804. package/dist/audit/types/flowCoverage.d.ts +16 -0
  805. package/dist/audit/types/flowCoverage.d.ts.map +1 -0
  806. package/dist/audit/types/flowCoverage.js +6 -0
  807. package/dist/audit/types/flowCoverage.js.map +1 -0
  808. package/dist/audit/types/reviewPlanning.d.ts +513 -0
  809. package/dist/audit/types/reviewPlanning.d.ts.map +1 -0
  810. package/dist/audit/types/reviewPlanning.js +109 -0
  811. package/dist/audit/types/reviewPlanning.js.map +1 -0
  812. package/dist/audit/types/runtimeValidation.d.ts +155 -0
  813. package/dist/audit/types/runtimeValidation.d.ts.map +1 -0
  814. package/dist/audit/types/runtimeValidation.js +52 -0
  815. package/dist/audit/types/runtimeValidation.js.map +1 -0
  816. package/dist/audit/types/synthesisNarrative.d.ts +8 -0
  817. package/dist/audit/types/synthesisNarrative.d.ts.map +1 -0
  818. package/dist/audit/types/synthesisNarrative.js +6 -0
  819. package/dist/audit/types/synthesisNarrative.js.map +1 -0
  820. package/dist/audit/types/toolingManifest.d.ts +8 -0
  821. package/dist/audit/types/toolingManifest.d.ts.map +1 -0
  822. package/dist/audit/types/toolingManifest.js +2 -0
  823. package/dist/audit/types/toolingManifest.js.map +1 -0
  824. package/dist/audit/types/workerResult.d.ts +14 -0
  825. package/dist/audit/types/workerResult.d.ts.map +1 -0
  826. package/dist/audit/types/workerResult.js +2 -0
  827. package/dist/audit/types/workerResult.js.map +1 -0
  828. package/dist/audit/types/workerSession.d.ts +28 -0
  829. package/dist/audit/types/workerSession.d.ts.map +1 -0
  830. package/dist/audit/types/workerSession.js +5 -0
  831. package/dist/audit/types/workerSession.js.map +1 -0
  832. package/dist/audit/types.d.ts +1077 -0
  833. package/dist/audit/types.d.ts.map +1 -0
  834. package/dist/audit/types.js +160 -0
  835. package/dist/audit/types.js.map +1 -0
  836. package/dist/audit/validation/anchorGrounding.d.ts +49 -0
  837. package/dist/audit/validation/anchorGrounding.d.ts.map +1 -0
  838. package/dist/audit/validation/anchorGrounding.js +183 -0
  839. package/dist/audit/validation/anchorGrounding.js.map +1 -0
  840. package/dist/audit/validation/artifacts.d.ts +4 -0
  841. package/dist/audit/validation/artifacts.d.ts.map +1 -0
  842. package/dist/audit/validation/artifacts.js +313 -0
  843. package/dist/audit/validation/artifacts.js.map +1 -0
  844. package/dist/audit/validation/auditResults.d.ts +16 -0
  845. package/dist/audit/validation/auditResults.d.ts.map +1 -0
  846. package/dist/audit/validation/auditResults.js +619 -0
  847. package/dist/audit/validation/auditResults.js.map +1 -0
  848. package/dist/audit/validation/designFindingGrounding.d.ts +33 -0
  849. package/dist/audit/validation/designFindingGrounding.d.ts.map +1 -0
  850. package/dist/audit/validation/designFindingGrounding.js +43 -0
  851. package/dist/audit/validation/designFindingGrounding.js.map +1 -0
  852. package/dist/audit/validation/quoteGrounding.d.ts +18 -0
  853. package/dist/audit/validation/quoteGrounding.d.ts.map +1 -0
  854. package/dist/audit/validation/quoteGrounding.js +18 -0
  855. package/dist/audit/validation/quoteGrounding.js.map +1 -0
  856. package/dist/audit/validation/sessionConfig.d.ts +8 -0
  857. package/dist/audit/validation/sessionConfig.d.ts.map +1 -0
  858. package/dist/audit/validation/sessionConfig.js +334 -0
  859. package/dist/audit/validation/sessionConfig.js.map +1 -0
  860. package/dist/remediate/contractPipeline/artifactStore.d.ts +58 -0
  861. package/dist/remediate/contractPipeline/artifactStore.d.ts.map +1 -0
  862. package/dist/remediate/contractPipeline/artifactStore.js +201 -0
  863. package/dist/remediate/contractPipeline/artifactStore.js.map +1 -0
  864. package/dist/remediate/contractPipeline/cyclicSeamResolution.d.ts +68 -0
  865. package/dist/remediate/contractPipeline/cyclicSeamResolution.d.ts.map +1 -0
  866. package/dist/remediate/contractPipeline/cyclicSeamResolution.js +151 -0
  867. package/dist/remediate/contractPipeline/cyclicSeamResolution.js.map +1 -0
  868. package/dist/remediate/contractPipeline/derive.d.ts +88 -0
  869. package/dist/remediate/contractPipeline/derive.d.ts.map +1 -0
  870. package/dist/remediate/contractPipeline/derive.js +216 -0
  871. package/dist/remediate/contractPipeline/derive.js.map +1 -0
  872. package/dist/remediate/contractPipeline/idRegistry.d.ts +49 -0
  873. package/dist/remediate/contractPipeline/idRegistry.d.ts.map +1 -0
  874. package/dist/remediate/contractPipeline/idRegistry.js +57 -0
  875. package/dist/remediate/contractPipeline/idRegistry.js.map +1 -0
  876. package/dist/remediate/contractPipeline/reviewSnapshot.d.ts +52 -0
  877. package/dist/remediate/contractPipeline/reviewSnapshot.d.ts.map +1 -0
  878. package/dist/remediate/contractPipeline/reviewSnapshot.js +116 -0
  879. package/dist/remediate/contractPipeline/reviewSnapshot.js.map +1 -0
  880. package/dist/remediate/contractPipeline/semanticProjection.d.ts +46 -0
  881. package/dist/remediate/contractPipeline/semanticProjection.d.ts.map +1 -0
  882. package/dist/remediate/contractPipeline/semanticProjection.js +102 -0
  883. package/dist/remediate/contractPipeline/semanticProjection.js.map +1 -0
  884. package/dist/remediate/coverage/findingLedger.d.ts +99 -0
  885. package/dist/remediate/coverage/findingLedger.d.ts.map +1 -0
  886. package/dist/remediate/coverage/findingLedger.js +110 -0
  887. package/dist/remediate/coverage/findingLedger.js.map +1 -0
  888. package/dist/remediate/dedup/crossLensDedup.d.ts +9 -0
  889. package/dist/remediate/dedup/crossLensDedup.d.ts.map +1 -0
  890. package/dist/remediate/dedup/crossLensDedup.js +191 -0
  891. package/dist/remediate/dedup/crossLensDedup.js.map +1 -0
  892. package/dist/remediate/dispatch/amendmentClaim.d.ts +41 -0
  893. package/dist/remediate/dispatch/amendmentClaim.d.ts.map +1 -0
  894. package/dist/remediate/dispatch/amendmentClaim.js +60 -0
  895. package/dist/remediate/dispatch/amendmentClaim.js.map +1 -0
  896. package/dist/remediate/dispatch/ownershipRegistry.d.ts +97 -0
  897. package/dist/remediate/dispatch/ownershipRegistry.d.ts.map +1 -0
  898. package/dist/remediate/dispatch/ownershipRegistry.js +217 -0
  899. package/dist/remediate/dispatch/ownershipRegistry.js.map +1 -0
  900. package/dist/remediate/findingFilter.d.ts +42 -0
  901. package/dist/remediate/findingFilter.d.ts.map +1 -0
  902. package/dist/remediate/findingFilter.js +62 -0
  903. package/dist/remediate/findingFilter.js.map +1 -0
  904. package/dist/remediate/index.d.ts +45 -0
  905. package/dist/remediate/index.d.ts.map +1 -0
  906. package/dist/remediate/index.js +434 -0
  907. package/dist/remediate/index.js.map +1 -0
  908. package/dist/remediate/intake.d.ts +168 -0
  909. package/dist/remediate/intake.d.ts.map +1 -0
  910. package/dist/remediate/intake.js +340 -0
  911. package/dist/remediate/intake.js.map +1 -0
  912. package/dist/remediate/intent/checkpointFilter.d.ts +14 -0
  913. package/dist/remediate/intent/checkpointFilter.d.ts.map +1 -0
  914. package/dist/remediate/intent/checkpointFilter.js +111 -0
  915. package/dist/remediate/intent/checkpointFilter.js.map +1 -0
  916. package/dist/remediate/phases/close.d.ts +32 -0
  917. package/dist/remediate/phases/close.d.ts.map +1 -0
  918. package/dist/remediate/phases/close.js +992 -0
  919. package/dist/remediate/phases/close.js.map +1 -0
  920. package/dist/remediate/phases/constants.d.ts +3 -0
  921. package/dist/remediate/phases/constants.d.ts.map +1 -0
  922. package/dist/remediate/phases/constants.js +3 -0
  923. package/dist/remediate/phases/constants.js.map +1 -0
  924. package/dist/remediate/phases/grounding.d.ts +77 -0
  925. package/dist/remediate/phases/grounding.d.ts.map +1 -0
  926. package/dist/remediate/phases/grounding.js +153 -0
  927. package/dist/remediate/phases/grounding.js.map +1 -0
  928. package/dist/remediate/phases/plan.d.ts +113 -0
  929. package/dist/remediate/phases/plan.d.ts.map +1 -0
  930. package/dist/remediate/phases/plan.js +988 -0
  931. package/dist/remediate/phases/plan.js.map +1 -0
  932. package/dist/remediate/phases/triage.d.ts +4 -0
  933. package/dist/remediate/phases/triage.d.ts.map +1 -0
  934. package/dist/remediate/phases/triage.js +175 -0
  935. package/dist/remediate/phases/triage.js.map +1 -0
  936. package/dist/remediate/phases/workerTasks.d.ts +21 -0
  937. package/dist/remediate/phases/workerTasks.d.ts.map +1 -0
  938. package/dist/remediate/phases/workerTasks.js +31 -0
  939. package/dist/remediate/phases/workerTasks.js.map +1 -0
  940. package/dist/remediate/providers/claudeCodeProvider.d.ts +12 -0
  941. package/dist/remediate/providers/claudeCodeProvider.d.ts.map +1 -0
  942. package/dist/remediate/providers/claudeCodeProvider.js +24 -0
  943. package/dist/remediate/providers/claudeCodeProvider.js.map +1 -0
  944. package/dist/remediate/providers/constants.d.ts +2 -0
  945. package/dist/remediate/providers/constants.d.ts.map +1 -0
  946. package/dist/remediate/providers/constants.js +2 -0
  947. package/dist/remediate/providers/constants.js.map +1 -0
  948. package/dist/remediate/providers/index.d.ts +15 -0
  949. package/dist/remediate/providers/index.d.ts.map +1 -0
  950. package/dist/remediate/providers/index.js +22 -0
  951. package/dist/remediate/providers/index.js.map +1 -0
  952. package/dist/remediate/providers/opencodeProvider.d.ts +5 -0
  953. package/dist/remediate/providers/opencodeProvider.d.ts.map +1 -0
  954. package/dist/remediate/providers/opencodeProvider.js +10 -0
  955. package/dist/remediate/providers/opencodeProvider.js.map +1 -0
  956. package/dist/remediate/quota/hostLimits.d.ts +8 -0
  957. package/dist/remediate/quota/hostLimits.d.ts.map +1 -0
  958. package/dist/remediate/quota/hostLimits.js +9 -0
  959. package/dist/remediate/quota/hostLimits.js.map +1 -0
  960. package/dist/remediate/quota/index.d.ts +8 -0
  961. package/dist/remediate/quota/index.d.ts.map +1 -0
  962. package/dist/remediate/quota/index.js +12 -0
  963. package/dist/remediate/quota/index.js.map +1 -0
  964. package/dist/remediate/review/reviewGate.d.ts +72 -0
  965. package/dist/remediate/review/reviewGate.d.ts.map +1 -0
  966. package/dist/remediate/review/reviewGate.js +112 -0
  967. package/dist/remediate/review/reviewGate.js.map +1 -0
  968. package/dist/remediate/review/reviewNecessity.d.ts +53 -0
  969. package/dist/remediate/review/reviewNecessity.d.ts.map +1 -0
  970. package/dist/remediate/review/reviewNecessity.js +129 -0
  971. package/dist/remediate/review/reviewNecessity.js.map +1 -0
  972. package/dist/remediate/state/closingActions.d.ts +3 -0
  973. package/dist/remediate/state/closingActions.d.ts.map +1 -0
  974. package/dist/remediate/state/closingActions.js +10 -0
  975. package/dist/remediate/state/closingActions.js.map +1 -0
  976. package/dist/remediate/state/itemStatus.d.ts +40 -0
  977. package/dist/remediate/state/itemStatus.d.ts.map +1 -0
  978. package/dist/remediate/state/itemStatus.js +138 -0
  979. package/dist/remediate/state/itemStatus.js.map +1 -0
  980. package/dist/remediate/state/store.d.ts +65 -0
  981. package/dist/remediate/state/store.d.ts.map +1 -0
  982. package/dist/remediate/state/store.js +141 -0
  983. package/dist/remediate/state/store.js.map +1 -0
  984. package/dist/remediate/state/types.d.ts +766 -0
  985. package/dist/remediate/state/types.d.ts.map +1 -0
  986. package/dist/remediate/state/types.js +122 -0
  987. package/dist/remediate/state/types.js.map +1 -0
  988. package/dist/remediate/steps/contractPipeline.d.ts +173 -0
  989. package/dist/remediate/steps/contractPipeline.d.ts.map +1 -0
  990. package/dist/remediate/steps/contractPipeline.js +1229 -0
  991. package/dist/remediate/steps/contractPipeline.js.map +1 -0
  992. package/dist/remediate/steps/contractPipelinePrompts.d.ts +72 -0
  993. package/dist/remediate/steps/contractPipelinePrompts.d.ts.map +1 -0
  994. package/dist/remediate/steps/contractPipelinePrompts.js +438 -0
  995. package/dist/remediate/steps/contractPipelinePrompts.js.map +1 -0
  996. package/dist/remediate/steps/dispatch.d.ts +434 -0
  997. package/dist/remediate/steps/dispatch.d.ts.map +1 -0
  998. package/dist/remediate/steps/dispatch.js +2180 -0
  999. package/dist/remediate/steps/dispatch.js.map +1 -0
  1000. package/dist/remediate/steps/intakeResolver.d.ts +32 -0
  1001. package/dist/remediate/steps/intakeResolver.d.ts.map +1 -0
  1002. package/dist/remediate/steps/intakeResolver.js +310 -0
  1003. package/dist/remediate/steps/intakeResolver.js.map +1 -0
  1004. package/dist/remediate/steps/leanFastPath.d.ts +49 -0
  1005. package/dist/remediate/steps/leanFastPath.d.ts.map +1 -0
  1006. package/dist/remediate/steps/leanFastPath.js +151 -0
  1007. package/dist/remediate/steps/leanFastPath.js.map +1 -0
  1008. package/dist/remediate/steps/nextStep.d.ts +323 -0
  1009. package/dist/remediate/steps/nextStep.d.ts.map +1 -0
  1010. package/dist/remediate/steps/nextStep.js +2721 -0
  1011. package/dist/remediate/steps/nextStep.js.map +1 -0
  1012. package/dist/remediate/steps/prompts.d.ts +26 -0
  1013. package/dist/remediate/steps/prompts.d.ts.map +1 -0
  1014. package/dist/remediate/steps/prompts.js +370 -0
  1015. package/dist/remediate/steps/prompts.js.map +1 -0
  1016. package/dist/remediate/steps/providerNodeDispatch.d.ts +42 -0
  1017. package/dist/remediate/steps/providerNodeDispatch.d.ts.map +1 -0
  1018. package/dist/remediate/steps/providerNodeDispatch.js +100 -0
  1019. package/dist/remediate/steps/providerNodeDispatch.js.map +1 -0
  1020. package/dist/remediate/steps/rollingSession.d.ts +84 -0
  1021. package/dist/remediate/steps/rollingSession.d.ts.map +1 -0
  1022. package/dist/remediate/steps/rollingSession.js +147 -0
  1023. package/dist/remediate/steps/rollingSession.js.map +1 -0
  1024. package/dist/remediate/steps/stepUtils.d.ts +63 -0
  1025. package/dist/remediate/steps/stepUtils.d.ts.map +1 -0
  1026. package/dist/remediate/steps/stepUtils.js +117 -0
  1027. package/dist/remediate/steps/stepUtils.js.map +1 -0
  1028. package/dist/remediate/steps/stepWriter.d.ts +27 -0
  1029. package/dist/remediate/steps/stepWriter.d.ts.map +1 -0
  1030. package/dist/remediate/steps/stepWriter.js +37 -0
  1031. package/dist/remediate/steps/stepWriter.js.map +1 -0
  1032. package/dist/remediate/steps/types.d.ts +83 -0
  1033. package/dist/remediate/steps/types.d.ts.map +1 -0
  1034. package/dist/remediate/steps/types.js +6 -0
  1035. package/dist/remediate/steps/types.js.map +1 -0
  1036. package/dist/remediate/types/options.d.ts +6 -0
  1037. package/dist/remediate/types/options.d.ts.map +1 -0
  1038. package/dist/remediate/types/options.js +2 -0
  1039. package/dist/remediate/types/options.js.map +1 -0
  1040. package/dist/remediate/types/workerSession.d.ts +36 -0
  1041. package/dist/remediate/types/workerSession.d.ts.map +1 -0
  1042. package/dist/remediate/types/workerSession.js +13 -0
  1043. package/dist/remediate/types/workerSession.js.map +1 -0
  1044. package/dist/remediate/utils/commands.d.ts +17 -0
  1045. package/dist/remediate/utils/commands.d.ts.map +1 -0
  1046. package/dist/remediate/utils/commands.js +26 -0
  1047. package/dist/remediate/utils/commands.js.map +1 -0
  1048. package/dist/remediate/utils/fileIntegrity.d.ts +27 -0
  1049. package/dist/remediate/utils/fileIntegrity.d.ts.map +1 -0
  1050. package/dist/remediate/utils/fileIntegrity.js +201 -0
  1051. package/dist/remediate/utils/fileIntegrity.js.map +1 -0
  1052. package/dist/remediate/utils/hostAssets.d.ts +18 -0
  1053. package/dist/remediate/utils/hostAssets.d.ts.map +1 -0
  1054. package/dist/remediate/utils/hostAssets.js +31 -0
  1055. package/dist/remediate/utils/hostAssets.js.map +1 -0
  1056. package/dist/remediate/validation/artifacts.d.ts +9 -0
  1057. package/dist/remediate/validation/artifacts.d.ts.map +1 -0
  1058. package/dist/remediate/validation/artifacts.js +316 -0
  1059. package/dist/remediate/validation/artifacts.js.map +1 -0
  1060. package/dist/remediate/validation/contractPipeline.d.ts +36 -0
  1061. package/dist/remediate/validation/contractPipeline.d.ts.map +1 -0
  1062. package/dist/remediate/validation/contractPipeline.js +569 -0
  1063. package/dist/remediate/validation/contractPipeline.js.map +1 -0
  1064. package/dist/remediate/validation/contractPipelineGates.d.ts +161 -0
  1065. package/dist/remediate/validation/contractPipelineGates.d.ts.map +1 -0
  1066. package/dist/remediate/validation/contractPipelineGates.js +739 -0
  1067. package/dist/remediate/validation/contractPipelineGates.js.map +1 -0
  1068. package/dist/remediate/validation/remediationState.d.ts +8 -0
  1069. package/dist/remediate/validation/remediationState.d.ts.map +1 -0
  1070. package/dist/remediate/validation/remediationState.js +187 -0
  1071. package/dist/remediate/validation/remediationState.js.map +1 -0
  1072. package/dist/shared/agentReflections.d.ts +61 -0
  1073. package/dist/shared/agentReflections.d.ts.map +1 -0
  1074. package/dist/shared/agentReflections.js +180 -0
  1075. package/dist/shared/agentReflections.js.map +1 -0
  1076. package/dist/shared/concurrency.d.ts +16 -0
  1077. package/dist/shared/concurrency.d.ts.map +1 -0
  1078. package/dist/shared/concurrency.js +34 -0
  1079. package/dist/shared/concurrency.js.map +1 -0
  1080. package/dist/shared/contracts.d.ts +2 -0
  1081. package/dist/shared/contracts.d.ts.map +1 -0
  1082. package/dist/shared/contracts.js +2 -0
  1083. package/dist/shared/contracts.js.map +1 -0
  1084. package/dist/shared/dispatch/rollingDispatch.d.ts +192 -0
  1085. package/dist/shared/dispatch/rollingDispatch.d.ts.map +1 -0
  1086. package/dist/shared/dispatch/rollingDispatch.js +389 -0
  1087. package/dist/shared/dispatch/rollingDispatch.js.map +1 -0
  1088. package/dist/shared/dispatch/tierRank.d.ts +53 -0
  1089. package/dist/shared/dispatch/tierRank.d.ts.map +1 -0
  1090. package/dist/shared/dispatch/tierRank.js +69 -0
  1091. package/dist/shared/dispatch/tierRank.js.map +1 -0
  1092. package/dist/shared/engine/obligationEngine.d.ts +159 -0
  1093. package/dist/shared/engine/obligationEngine.d.ts.map +1 -0
  1094. package/dist/shared/engine/obligationEngine.js +124 -0
  1095. package/dist/shared/engine/obligationEngine.js.map +1 -0
  1096. package/dist/shared/findingIdentitySignature.d.ts +82 -0
  1097. package/dist/shared/findingIdentitySignature.d.ts.map +1 -0
  1098. package/dist/shared/findingIdentitySignature.js +114 -0
  1099. package/dist/shared/findingIdentitySignature.js.map +1 -0
  1100. package/dist/shared/git.d.ts +18 -0
  1101. package/dist/shared/git.d.ts.map +1 -0
  1102. package/dist/shared/git.js +63 -0
  1103. package/dist/shared/git.js.map +1 -0
  1104. package/dist/shared/hash.d.ts +16 -0
  1105. package/dist/shared/hash.d.ts.map +1 -0
  1106. package/dist/shared/hash.js +36 -0
  1107. package/dist/shared/hash.js.map +1 -0
  1108. package/dist/shared/hostAssets.d.ts +40 -0
  1109. package/dist/shared/hostAssets.d.ts.map +1 -0
  1110. package/dist/shared/hostAssets.js +110 -0
  1111. package/dist/shared/hostAssets.js.map +1 -0
  1112. package/dist/shared/ids.d.ts +18 -0
  1113. package/dist/shared/ids.d.ts.map +1 -0
  1114. package/dist/shared/ids.js +27 -0
  1115. package/dist/shared/ids.js.map +1 -0
  1116. package/dist/shared/index.d.ts +150 -0
  1117. package/dist/shared/index.d.ts.map +1 -0
  1118. package/dist/shared/index.js +112 -0
  1119. package/dist/shared/index.js.map +1 -0
  1120. package/dist/shared/intent/clauseInterpreter.d.ts +84 -0
  1121. package/dist/shared/intent/clauseInterpreter.d.ts.map +1 -0
  1122. package/dist/shared/intent/clauseInterpreter.js +183 -0
  1123. package/dist/shared/intent/clauseInterpreter.js.map +1 -0
  1124. package/dist/shared/intent/freeFormIntentInterpreter.d.ts +46 -0
  1125. package/dist/shared/intent/freeFormIntentInterpreter.d.ts.map +1 -0
  1126. package/dist/shared/intent/freeFormIntentInterpreter.js +126 -0
  1127. package/dist/shared/intent/freeFormIntentInterpreter.js.map +1 -0
  1128. package/dist/shared/intent/sharedIntentData.d.ts +16 -0
  1129. package/dist/shared/intent/sharedIntentData.d.ts.map +1 -0
  1130. package/dist/shared/intent/sharedIntentData.js +38 -0
  1131. package/dist/shared/intent/sharedIntentData.js.map +1 -0
  1132. package/dist/shared/io/auditToolsPaths.d.ts +36 -0
  1133. package/dist/shared/io/auditToolsPaths.d.ts.map +1 -0
  1134. package/dist/shared/io/auditToolsPaths.js +47 -0
  1135. package/dist/shared/io/auditToolsPaths.js.map +1 -0
  1136. package/dist/shared/io/json.d.ts +30 -0
  1137. package/dist/shared/io/json.d.ts.map +1 -0
  1138. package/dist/shared/io/json.js +183 -0
  1139. package/dist/shared/io/json.js.map +1 -0
  1140. package/dist/shared/io/stepContractWriter.d.ts +103 -0
  1141. package/dist/shared/io/stepContractWriter.d.ts.map +1 -0
  1142. package/dist/shared/io/stepContractWriter.js +85 -0
  1143. package/dist/shared/io/stepContractWriter.js.map +1 -0
  1144. package/dist/shared/observability/runLog.d.ts +37 -0
  1145. package/dist/shared/observability/runLog.d.ts.map +1 -0
  1146. package/dist/shared/observability/runLog.js +40 -0
  1147. package/dist/shared/observability/runLog.js.map +1 -0
  1148. package/dist/shared/opencodePermissions.d.ts +49 -0
  1149. package/dist/shared/opencodePermissions.d.ts.map +1 -0
  1150. package/dist/shared/opencodePermissions.js +118 -0
  1151. package/dist/shared/opencodePermissions.js.map +1 -0
  1152. package/dist/shared/parsing/stringAwareScanner.d.ts +32 -0
  1153. package/dist/shared/parsing/stringAwareScanner.d.ts.map +1 -0
  1154. package/dist/shared/parsing/stringAwareScanner.js +51 -0
  1155. package/dist/shared/parsing/stringAwareScanner.js.map +1 -0
  1156. package/dist/shared/prompts.d.ts +47 -0
  1157. package/dist/shared/prompts.d.ts.map +1 -0
  1158. package/dist/shared/prompts.js +41 -0
  1159. package/dist/shared/prompts.js.map +1 -0
  1160. package/dist/shared/providers/claudeCodeProvider.d.ts +56 -0
  1161. package/dist/shared/providers/claudeCodeProvider.d.ts.map +1 -0
  1162. package/dist/shared/providers/claudeCodeProvider.js +67 -0
  1163. package/dist/shared/providers/claudeCodeProvider.js.map +1 -0
  1164. package/dist/shared/providers/codexProvider.d.ts +37 -0
  1165. package/dist/shared/providers/codexProvider.d.ts.map +1 -0
  1166. package/dist/shared/providers/codexProvider.js +79 -0
  1167. package/dist/shared/providers/codexProvider.js.map +1 -0
  1168. package/dist/shared/providers/constants.d.ts +4 -0
  1169. package/dist/shared/providers/constants.d.ts.map +1 -0
  1170. package/dist/shared/providers/constants.js +4 -0
  1171. package/dist/shared/providers/constants.js.map +1 -0
  1172. package/dist/shared/providers/localSubprocessProvider.d.ts +10 -0
  1173. package/dist/shared/providers/localSubprocessProvider.d.ts.map +1 -0
  1174. package/dist/shared/providers/localSubprocessProvider.js +20 -0
  1175. package/dist/shared/providers/localSubprocessProvider.js.map +1 -0
  1176. package/dist/shared/providers/openAiCompatibleProvider.d.ts +62 -0
  1177. package/dist/shared/providers/openAiCompatibleProvider.d.ts.map +1 -0
  1178. package/dist/shared/providers/openAiCompatibleProvider.js +333 -0
  1179. package/dist/shared/providers/openAiCompatibleProvider.js.map +1 -0
  1180. package/dist/shared/providers/opencodeLaunch.d.ts +28 -0
  1181. package/dist/shared/providers/opencodeLaunch.d.ts.map +1 -0
  1182. package/dist/shared/providers/opencodeLaunch.js +39 -0
  1183. package/dist/shared/providers/opencodeLaunch.js.map +1 -0
  1184. package/dist/shared/providers/opencodeProvider.d.ts +19 -0
  1185. package/dist/shared/providers/opencodeProvider.d.ts.map +1 -0
  1186. package/dist/shared/providers/opencodeProvider.js +41 -0
  1187. package/dist/shared/providers/opencodeProvider.js.map +1 -0
  1188. package/dist/shared/providers/providerConfirmation.d.ts +56 -0
  1189. package/dist/shared/providers/providerConfirmation.d.ts.map +1 -0
  1190. package/dist/shared/providers/providerConfirmation.js +195 -0
  1191. package/dist/shared/providers/providerConfirmation.js.map +1 -0
  1192. package/dist/shared/providers/providerDiagnostics.d.ts +11 -0
  1193. package/dist/shared/providers/providerDiagnostics.d.ts.map +1 -0
  1194. package/dist/shared/providers/providerDiagnostics.js +28 -0
  1195. package/dist/shared/providers/providerDiagnostics.js.map +1 -0
  1196. package/dist/shared/providers/providerFactory.d.ts +72 -0
  1197. package/dist/shared/providers/providerFactory.d.ts.map +1 -0
  1198. package/dist/shared/providers/providerFactory.js +246 -0
  1199. package/dist/shared/providers/providerFactory.js.map +1 -0
  1200. package/dist/shared/providers/providerKeyedFactory.d.ts +14 -0
  1201. package/dist/shared/providers/providerKeyedFactory.d.ts.map +1 -0
  1202. package/dist/shared/providers/providerKeyedFactory.js +16 -0
  1203. package/dist/shared/providers/providerKeyedFactory.js.map +1 -0
  1204. package/dist/shared/providers/spawnLoggedCommand.d.ts +10 -0
  1205. package/dist/shared/providers/spawnLoggedCommand.d.ts.map +1 -0
  1206. package/dist/shared/providers/spawnLoggedCommand.js +304 -0
  1207. package/dist/shared/providers/spawnLoggedCommand.js.map +1 -0
  1208. package/dist/shared/providers/subprocessTemplateProvider.d.ts +19 -0
  1209. package/dist/shared/providers/subprocessTemplateProvider.d.ts.map +1 -0
  1210. package/dist/shared/providers/subprocessTemplateProvider.js +91 -0
  1211. package/dist/shared/providers/subprocessTemplateProvider.js.map +1 -0
  1212. package/dist/shared/providers/types.d.ts +43 -0
  1213. package/dist/shared/providers/types.d.ts.map +1 -0
  1214. package/dist/shared/providers/types.js +2 -0
  1215. package/dist/shared/providers/types.js.map +1 -0
  1216. package/dist/shared/providers/workerTaskLaunch.d.ts +32 -0
  1217. package/dist/shared/providers/workerTaskLaunch.d.ts.map +1 -0
  1218. package/dist/shared/providers/workerTaskLaunch.js +27 -0
  1219. package/dist/shared/providers/workerTaskLaunch.js.map +1 -0
  1220. package/dist/shared/quota/antigravityQuotaSource.d.ts +44 -0
  1221. package/dist/shared/quota/antigravityQuotaSource.d.ts.map +1 -0
  1222. package/dist/shared/quota/antigravityQuotaSource.js +101 -0
  1223. package/dist/shared/quota/antigravityQuotaSource.js.map +1 -0
  1224. package/dist/shared/quota/capacity.d.ts +283 -0
  1225. package/dist/shared/quota/capacity.d.ts.map +1 -0
  1226. package/dist/shared/quota/capacity.js +290 -0
  1227. package/dist/shared/quota/capacity.js.map +1 -0
  1228. package/dist/shared/quota/claudeCodeJsonLines.d.ts +15 -0
  1229. package/dist/shared/quota/claudeCodeJsonLines.d.ts.map +1 -0
  1230. package/dist/shared/quota/claudeCodeJsonLines.js +34 -0
  1231. package/dist/shared/quota/claudeCodeJsonLines.js.map +1 -0
  1232. package/dist/shared/quota/claudeOAuthQuotaSource.d.ts +56 -0
  1233. package/dist/shared/quota/claudeOAuthQuotaSource.d.ts.map +1 -0
  1234. package/dist/shared/quota/claudeOAuthQuotaSource.js +136 -0
  1235. package/dist/shared/quota/claudeOAuthQuotaSource.js.map +1 -0
  1236. package/dist/shared/quota/codexQuotaSource.d.ts +49 -0
  1237. package/dist/shared/quota/codexQuotaSource.d.ts.map +1 -0
  1238. package/dist/shared/quota/codexQuotaSource.js +96 -0
  1239. package/dist/shared/quota/codexQuotaSource.js.map +1 -0
  1240. package/dist/shared/quota/compositeQuotaSource.d.ts +29 -0
  1241. package/dist/shared/quota/compositeQuotaSource.d.ts.map +1 -0
  1242. package/dist/shared/quota/compositeQuotaSource.js +58 -0
  1243. package/dist/shared/quota/compositeQuotaSource.js.map +1 -0
  1244. package/dist/shared/quota/copilotQuotaSource.d.ts +57 -0
  1245. package/dist/shared/quota/copilotQuotaSource.d.ts.map +1 -0
  1246. package/dist/shared/quota/copilotQuotaSource.js +141 -0
  1247. package/dist/shared/quota/copilotQuotaSource.js.map +1 -0
  1248. package/dist/shared/quota/errorParsers/claudeCodeErrorParser.d.ts +7 -0
  1249. package/dist/shared/quota/errorParsers/claudeCodeErrorParser.d.ts.map +1 -0
  1250. package/dist/shared/quota/errorParsers/claudeCodeErrorParser.js +33 -0
  1251. package/dist/shared/quota/errorParsers/claudeCodeErrorParser.js.map +1 -0
  1252. package/dist/shared/quota/errorParsers/genericErrorParser.d.ts +10 -0
  1253. package/dist/shared/quota/errorParsers/genericErrorParser.d.ts.map +1 -0
  1254. package/dist/shared/quota/errorParsers/genericErrorParser.js +8 -0
  1255. package/dist/shared/quota/errorParsers/genericErrorParser.js.map +1 -0
  1256. package/dist/shared/quota/errorParsers/index.d.ts +6 -0
  1257. package/dist/shared/quota/errorParsers/index.d.ts.map +1 -0
  1258. package/dist/shared/quota/errorParsers/index.js +16 -0
  1259. package/dist/shared/quota/errorParsers/index.js.map +1 -0
  1260. package/dist/shared/quota/errorParsing.d.ts +8 -0
  1261. package/dist/shared/quota/errorParsing.d.ts.map +1 -0
  1262. package/dist/shared/quota/errorParsing.js +129 -0
  1263. package/dist/shared/quota/errorParsing.js.map +1 -0
  1264. package/dist/shared/quota/fileLock.d.ts +9 -0
  1265. package/dist/shared/quota/fileLock.d.ts.map +1 -0
  1266. package/dist/shared/quota/fileLock.js +202 -0
  1267. package/dist/shared/quota/fileLock.js.map +1 -0
  1268. package/dist/shared/quota/hostLimits.d.ts +16 -0
  1269. package/dist/shared/quota/hostLimits.d.ts.map +1 -0
  1270. package/dist/shared/quota/hostLimits.js +57 -0
  1271. package/dist/shared/quota/hostLimits.js.map +1 -0
  1272. package/dist/shared/quota/httpQuotaSource.d.ts +87 -0
  1273. package/dist/shared/quota/httpQuotaSource.d.ts.map +1 -0
  1274. package/dist/shared/quota/httpQuotaSource.js +90 -0
  1275. package/dist/shared/quota/httpQuotaSource.js.map +1 -0
  1276. package/dist/shared/quota/learnedQuotaSource.d.ts +8 -0
  1277. package/dist/shared/quota/learnedQuotaSource.d.ts.map +1 -0
  1278. package/dist/shared/quota/learnedQuotaSource.js +26 -0
  1279. package/dist/shared/quota/learnedQuotaSource.js.map +1 -0
  1280. package/dist/shared/quota/limits.d.ts +35 -0
  1281. package/dist/shared/quota/limits.d.ts.map +1 -0
  1282. package/dist/shared/quota/limits.js +110 -0
  1283. package/dist/shared/quota/limits.js.map +1 -0
  1284. package/dist/shared/quota/openCodeQuotaSource.d.ts +18 -0
  1285. package/dist/shared/quota/openCodeQuotaSource.d.ts.map +1 -0
  1286. package/dist/shared/quota/openCodeQuotaSource.js +84 -0
  1287. package/dist/shared/quota/openCodeQuotaSource.js.map +1 -0
  1288. package/dist/shared/quota/quotaSource.d.ts +29 -0
  1289. package/dist/shared/quota/quotaSource.d.ts.map +1 -0
  1290. package/dist/shared/quota/quotaSource.js +12 -0
  1291. package/dist/shared/quota/quotaSource.js.map +1 -0
  1292. package/dist/shared/quota/rollingEngine.d.ts +130 -0
  1293. package/dist/shared/quota/rollingEngine.d.ts.map +1 -0
  1294. package/dist/shared/quota/rollingEngine.js +153 -0
  1295. package/dist/shared/quota/rollingEngine.js.map +1 -0
  1296. package/dist/shared/quota/scheduler.d.ts +94 -0
  1297. package/dist/shared/quota/scheduler.d.ts.map +1 -0
  1298. package/dist/shared/quota/scheduler.js +313 -0
  1299. package/dist/shared/quota/scheduler.js.map +1 -0
  1300. package/dist/shared/quota/slidingWindow.d.ts +5 -0
  1301. package/dist/shared/quota/slidingWindow.d.ts.map +1 -0
  1302. package/dist/shared/quota/slidingWindow.js +29 -0
  1303. package/dist/shared/quota/slidingWindow.js.map +1 -0
  1304. package/dist/shared/quota/state.d.ts +27 -0
  1305. package/dist/shared/quota/state.d.ts.map +1 -0
  1306. package/dist/shared/quota/state.js +204 -0
  1307. package/dist/shared/quota/state.js.map +1 -0
  1308. package/dist/shared/quota/types.d.ts +109 -0
  1309. package/dist/shared/quota/types.d.ts.map +1 -0
  1310. package/dist/shared/quota/types.js +56 -0
  1311. package/dist/shared/quota/types.js.map +1 -0
  1312. package/dist/shared/reReview/projectionDiff.d.ts +65 -0
  1313. package/dist/shared/reReview/projectionDiff.d.ts.map +1 -0
  1314. package/dist/shared/reReview/projectionDiff.js +144 -0
  1315. package/dist/shared/reReview/projectionDiff.js.map +1 -0
  1316. package/dist/shared/rolling/pausedState.d.ts +109 -0
  1317. package/dist/shared/rolling/pausedState.d.ts.map +1 -0
  1318. package/dist/shared/rolling/pausedState.js +100 -0
  1319. package/dist/shared/rolling/pausedState.js.map +1 -0
  1320. package/dist/shared/tokens.d.ts +24 -0
  1321. package/dist/shared/tokens.d.ts.map +1 -0
  1322. package/dist/shared/tokens.js +54 -0
  1323. package/dist/shared/tokens.js.map +1 -0
  1324. package/dist/shared/tooling/allowlistedExec.d.ts +45 -0
  1325. package/dist/shared/tooling/allowlistedExec.d.ts.map +1 -0
  1326. package/dist/shared/tooling/allowlistedExec.js +340 -0
  1327. package/dist/shared/tooling/allowlistedExec.js.map +1 -0
  1328. package/dist/shared/tooling/analyzerDeps.d.ts +65 -0
  1329. package/dist/shared/tooling/analyzerDeps.d.ts.map +1 -0
  1330. package/dist/shared/tooling/analyzerDeps.js +130 -0
  1331. package/dist/shared/tooling/analyzerDeps.js.map +1 -0
  1332. package/dist/shared/tooling/exec.d.ts +99 -0
  1333. package/dist/shared/tooling/exec.d.ts.map +1 -0
  1334. package/dist/shared/tooling/exec.js +217 -0
  1335. package/dist/shared/tooling/exec.js.map +1 -0
  1336. package/dist/shared/tooling/repoConventions.d.ts +23 -0
  1337. package/dist/shared/tooling/repoConventions.d.ts.map +1 -0
  1338. package/dist/shared/tooling/repoConventions.js +177 -0
  1339. package/dist/shared/tooling/repoConventions.js.map +1 -0
  1340. package/dist/shared/tooling/testCommand.d.ts +17 -0
  1341. package/dist/shared/tooling/testCommand.d.ts.map +1 -0
  1342. package/dist/shared/tooling/testCommand.js +106 -0
  1343. package/dist/shared/tooling/testCommand.js.map +1 -0
  1344. package/dist/shared/types/accessDeclaration.d.ts +16 -0
  1345. package/dist/shared/types/accessDeclaration.d.ts.map +1 -0
  1346. package/dist/shared/types/accessDeclaration.js +9 -0
  1347. package/dist/shared/types/accessDeclaration.js.map +1 -0
  1348. package/dist/shared/types/contractPipeline/design.d.ts +74 -0
  1349. package/dist/shared/types/contractPipeline/design.d.ts.map +1 -0
  1350. package/dist/shared/types/contractPipeline/design.js +10 -0
  1351. package/dist/shared/types/contractPipeline/design.js.map +1 -0
  1352. package/dist/shared/types/contractPipeline/goal.d.ts +41 -0
  1353. package/dist/shared/types/contractPipeline/goal.d.ts.map +1 -0
  1354. package/dist/shared/types/contractPipeline/goal.js +10 -0
  1355. package/dist/shared/types/contractPipeline/goal.js.map +1 -0
  1356. package/dist/shared/types/contractPipeline/implementation.d.ts +64 -0
  1357. package/dist/shared/types/contractPipeline/implementation.d.ts.map +1 -0
  1358. package/dist/shared/types/contractPipeline/implementation.js +8 -0
  1359. package/dist/shared/types/contractPipeline/implementation.js.map +1 -0
  1360. package/dist/shared/types/contractPipeline/obligations.d.ts +141 -0
  1361. package/dist/shared/types/contractPipeline/obligations.d.ts.map +1 -0
  1362. package/dist/shared/types/contractPipeline/obligations.js +16 -0
  1363. package/dist/shared/types/contractPipeline/obligations.js.map +1 -0
  1364. package/dist/shared/types/contractPipeline/verification.d.ts +64 -0
  1365. package/dist/shared/types/contractPipeline/verification.d.ts.map +1 -0
  1366. package/dist/shared/types/contractPipeline/verification.js +10 -0
  1367. package/dist/shared/types/contractPipeline/verification.js.map +1 -0
  1368. package/dist/shared/types/contractPipeline.d.ts +36 -0
  1369. package/dist/shared/types/contractPipeline.d.ts.map +1 -0
  1370. package/dist/shared/types/contractPipeline.js +31 -0
  1371. package/dist/shared/types/contractPipeline.js.map +1 -0
  1372. package/dist/shared/types/disposition.d.ts +46 -0
  1373. package/dist/shared/types/disposition.d.ts.map +1 -0
  1374. package/dist/shared/types/disposition.js +22 -0
  1375. package/dist/shared/types/disposition.js.map +1 -0
  1376. package/dist/shared/types/finding.d.ts +1463 -0
  1377. package/dist/shared/types/finding.d.ts.map +1 -0
  1378. package/dist/shared/types/finding.js +234 -0
  1379. package/dist/shared/types/finding.js.map +1 -0
  1380. package/dist/shared/types/flows.d.ts +84 -0
  1381. package/dist/shared/types/flows.d.ts.map +1 -0
  1382. package/dist/shared/types/flows.js +23 -0
  1383. package/dist/shared/types/flows.js.map +1 -0
  1384. package/dist/shared/types/graph.d.ts +359 -0
  1385. package/dist/shared/types/graph.d.ts.map +1 -0
  1386. package/dist/shared/types/graph.js +38 -0
  1387. package/dist/shared/types/graph.js.map +1 -0
  1388. package/dist/shared/types/intentCheckpoint.d.ts +95 -0
  1389. package/dist/shared/types/intentCheckpoint.d.ts.map +1 -0
  1390. package/dist/shared/types/intentCheckpoint.js +2 -0
  1391. package/dist/shared/types/intentCheckpoint.js.map +1 -0
  1392. package/dist/shared/types/intentInterpretation.d.ts +57 -0
  1393. package/dist/shared/types/intentInterpretation.d.ts.map +1 -0
  1394. package/dist/shared/types/intentInterpretation.js +20 -0
  1395. package/dist/shared/types/intentInterpretation.js.map +1 -0
  1396. package/dist/shared/types/lens.d.ts +38 -0
  1397. package/dist/shared/types/lens.d.ts.map +1 -0
  1398. package/dist/shared/types/lens.js +80 -0
  1399. package/dist/shared/types/lens.js.map +1 -0
  1400. package/dist/shared/types/obligationLedger.d.ts +35 -0
  1401. package/dist/shared/types/obligationLedger.d.ts.map +1 -0
  1402. package/dist/shared/types/obligationLedger.js +77 -0
  1403. package/dist/shared/types/obligationLedger.js.map +1 -0
  1404. package/dist/shared/types/providerConfirmation.d.ts +51 -0
  1405. package/dist/shared/types/providerConfirmation.d.ts.map +1 -0
  1406. package/dist/shared/types/providerConfirmation.js +19 -0
  1407. package/dist/shared/types/providerConfirmation.js.map +1 -0
  1408. package/dist/shared/types/remediationOutcome.d.ts +41 -0
  1409. package/dist/shared/types/remediationOutcome.d.ts.map +1 -0
  1410. package/dist/shared/types/remediationOutcome.js +7 -0
  1411. package/dist/shared/types/remediationOutcome.js.map +1 -0
  1412. package/dist/shared/types/risk.d.ts +52 -0
  1413. package/dist/shared/types/risk.d.ts.map +1 -0
  1414. package/dist/shared/types/risk.js +17 -0
  1415. package/dist/shared/types/risk.js.map +1 -0
  1416. package/dist/shared/types/rollingDispatch.d.ts +61 -0
  1417. package/dist/shared/types/rollingDispatch.d.ts.map +1 -0
  1418. package/dist/shared/types/rollingDispatch.js +19 -0
  1419. package/dist/shared/types/rollingDispatch.js.map +1 -0
  1420. package/dist/shared/types/runLedger.d.ts +18 -0
  1421. package/dist/shared/types/runLedger.d.ts.map +1 -0
  1422. package/dist/shared/types/runLedger.js +7 -0
  1423. package/dist/shared/types/runLedger.js.map +1 -0
  1424. package/dist/shared/types/sessionConfig.d.ts +294 -0
  1425. package/dist/shared/types/sessionConfig.d.ts.map +1 -0
  1426. package/dist/shared/types/sessionConfig.js +44 -0
  1427. package/dist/shared/types/sessionConfig.js.map +1 -0
  1428. package/dist/shared/types/stepContract.d.ts +10 -0
  1429. package/dist/shared/types/stepContract.d.ts.map +1 -0
  1430. package/dist/shared/types/stepContract.js +4 -0
  1431. package/dist/shared/types/stepContract.js.map +1 -0
  1432. package/dist/shared/types/surfaces.d.ts +73 -0
  1433. package/dist/shared/types/surfaces.d.ts.map +1 -0
  1434. package/dist/shared/types/surfaces.js +21 -0
  1435. package/dist/shared/types/surfaces.js.map +1 -0
  1436. package/dist/shared/validation/basic.d.ts +24 -0
  1437. package/dist/shared/validation/basic.d.ts.map +1 -0
  1438. package/dist/shared/validation/basic.js +57 -0
  1439. package/dist/shared/validation/basic.js.map +1 -0
  1440. package/dist/shared/validation/findingGrounding.d.ts +45 -0
  1441. package/dist/shared/validation/findingGrounding.d.ts.map +1 -0
  1442. package/dist/shared/validation/findingGrounding.js +103 -0
  1443. package/dist/shared/validation/findingGrounding.js.map +1 -0
  1444. package/dist/shared/validation/findingsReport.d.ts +42 -0
  1445. package/dist/shared/validation/findingsReport.d.ts.map +1 -0
  1446. package/dist/shared/validation/findingsReport.js +76 -0
  1447. package/dist/shared/validation/findingsReport.js.map +1 -0
  1448. package/dist/shared/validation/sessionConfig.d.ts +22 -0
  1449. package/dist/shared/validation/sessionConfig.d.ts.map +1 -0
  1450. package/dist/shared/validation/sessionConfig.js +38 -0
  1451. package/dist/shared/validation/sessionConfig.js.map +1 -0
  1452. package/docs/audit-pkg/contracts.md +227 -0
  1453. package/docs/audit-pkg/development.md +112 -0
  1454. package/docs/audit-pkg/history.md +66 -0
  1455. package/docs/audit-pkg/operator-guide.md +204 -0
  1456. package/docs/audit-pkg/product.md +119 -0
  1457. package/docs/audit-pkg/release.md +131 -0
  1458. package/opencode.json +159 -0
  1459. package/package.json +104 -0
  1460. package/remediate-code.mjs +116 -0
  1461. package/schemas/audit_result.schema.json +510 -0
  1462. package/schemas/audit_results.schema.json +514 -0
  1463. package/schemas/audit_task.schema.json +127 -0
  1464. package/schemas/finding.schema.json +261 -0
  1465. package/schemas/lens.schema.json +19 -0
  1466. package/scripts/audit/postinstall.mjs +385 -0
  1467. package/scripts/postinstall.mjs +24 -0
  1468. package/scripts/remediate/postinstall.mjs +387 -0
  1469. package/skills/audit-code/SKILL.md +166 -0
  1470. package/skills/audit-code/agents/openai.yaml +4 -0
  1471. package/skills/audit-code/audit-code.prompt.md +112 -0
  1472. package/skills/audit-code/opencode-command-template.txt +13 -0
  1473. package/skills/remediate-code/SKILL.md +90 -0
  1474. package/skills/remediate-code/agents/openai.yaml +4 -0
  1475. package/skills/remediate-code/remediate-code.prompt.md +94 -0
  1476. package/templates/AGENTS.remediate-code.md +6 -0
@@ -0,0 +1,2721 @@
1
+ import { existsSync } from "node:fs";
2
+ import { mkdir, readFile, rename } from "node:fs/promises";
3
+ import { dirname, join, resolve } from "node:path";
4
+ import { StateStore } from "../state/store.js";
5
+ import { readOptionalJsonFile, writeJsonFile, formatValidationIssues, isRecord, withFsRetry, RunLogger, DO_NOT_TOKEN_WRAP_NOTE, DISPATCH_PROMPT_HANDOFF_NOTE, coerceJsonObjectArg, createRollingDispatcher, setQuotaStateDir, interpretFreeFormIntent, advance } from "audit-tools/shared";
6
+ import { applyPlanPipeline, buildCoverageLedger } from "../phases/plan.js";
7
+ import { groundExtractedFindings } from "../phases/grounding.js";
8
+ import { runTriagePhase } from "../phases/triage.js";
9
+ import { runClosePhase } from "../phases/close.js";
10
+ import { validateRemediationPlan } from "../validation/remediationState.js";
11
+ import { mergeImplementResults, prepareImplementDispatch, readExtractedPlanIfPresent, buildConfirmedPools, createWorktree, removeWorktree, resetNodeWorktreeAndBranch, acceptNodeWorktree, recordNodeAcceptOutcome, ensureWorktreeNodeModules, worktreePath, worktreeBranchForBlock, } from "./dispatch.js";
12
+ import { makeProviderNodeDispatcher } from "./providerNodeDispatch.js";
13
+ import { prepareHostRollingDispatch } from "./rollingSession.js";
14
+ import { writeCurrentStep } from "./stepWriter.js";
15
+ import { dependencyVerifiedComplete } from "./stepUtils.js";
16
+ import { isTerminalStatus, isVerifiedCompleteStatus, isSkipStatus, } from "../state/itemStatus.js";
17
+ import { deduplicateCrossLensFindings, fixupBlocksAfterDedup, } from "../dedup/crossLensDedup.js";
18
+ import { checkAffectedFileIntegrity } from "../utils/fileIntegrity.js";
19
+ import { resolveIntakeStep } from "./intakeResolver.js";
20
+ import { runCommand } from "../utils/commands.js";
21
+ import { buildNextContractPipelineStep, shouldEnterContractPipeline, writePathASeedFromFindings, } from "./contractPipeline.js";
22
+ import { evaluateFastPath, buildLeanExtractedPlan, } from "./leanFastPath.js";
23
+ import { contractArtifactExists, contractPipelineDir, } from "../contractPipeline/artifactStore.js";
24
+ import { buildReviewRequest, applyReviewResolution, } from "../review/reviewGate.js";
25
+ import { runFindingFilterPass } from "../findingFilter.js";
26
+ import { intakePaths, isIntakeReady, readIntakeArtifacts, resolveManifestSources, } from "../intake.js";
27
+ import { clarificationPrompt, collectIntakeClarificationsPrompt, collectStartingPointPrompt, loaderCommand, reviewApprovalPrompt, synthesizeIntakePrompt, triagePrompt, } from "./prompts.js";
28
+ export function resolveHostDispatchCapability(options) {
29
+ if (options.hostCanDispatchSubagents !== undefined) {
30
+ return options.hostCanDispatchSubagents;
31
+ }
32
+ if (options.sessionConfig?.host_can_dispatch_subagents !== undefined) {
33
+ return options.sessionConfig.host_can_dispatch_subagents;
34
+ }
35
+ const envValue = (options.env ?? process.env).REMEDIATE_HOST_CAN_DISPATCH;
36
+ if (envValue === "true")
37
+ return true;
38
+ if (envValue === "false")
39
+ return false;
40
+ // Conversation-first default: an interactive agent host (e.g. Claude Code) can
41
+ // dispatch callable subagents, so default to parallel wave dispatch. A host that
42
+ // genuinely cannot dispatch opts out via host_can_dispatch_subagents:false,
43
+ // REMEDIATE_HOST_CAN_DISPATCH=false, or --host-can-dispatch-subagents=false.
44
+ return true;
45
+ }
46
+ /**
47
+ * Whether the rolling dispatch engine drives the implement phase. Defaults to TRUE:
48
+ * both rolling drivers on the shared `acceptNodeWorktree` core (per-node worktree →
49
+ * tool-owned commit → verify → cherry-pick merge; verify-fail → triage) are now
50
+ * validated end-to-end — the host-subagent driver via a real-subagent smoke
51
+ * (f18138fe) and the in-process provider driver via a live-NIM run THROUGH
52
+ * decideNextStep (2026-06-17, tests/nim-rolling-e2e.test.ts). The legacy host-fanned
53
+ * wave (`dispatch_implement`) is retained as an explicit opt-OUT (rolling_engine:false
54
+ * / REMEDIATE_ROLLING_ENGINE=false), not deleted. Resolution order: explicit option →
55
+ * sessionConfig.dispatch.rolling_engine → REMEDIATE_ROLLING_ENGINE env → true.
56
+ */
57
+ export function resolveRollingEngineEnabled(options) {
58
+ if (options.rollingEngine !== undefined)
59
+ return options.rollingEngine;
60
+ const cfg = options.sessionConfig?.dispatch?.rolling_engine;
61
+ if (cfg !== undefined)
62
+ return cfg;
63
+ const envValue = (options.env ?? process.env).REMEDIATE_ROLLING_ENGINE;
64
+ if (envValue === "true")
65
+ return true;
66
+ if (envValue === "false")
67
+ return false;
68
+ return true;
69
+ }
70
+ function randomRunId(prefix = "RUN") {
71
+ return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
72
+ }
73
+ /**
74
+ * Host-facing note interposing a shared rebuild between rolling dependency
75
+ * levels. The tool admits a downstream node only once its upstream node is
76
+ * verified-complete; once that upstream edit lands, the host must rebuild the
77
+ * shared surface before the next next-step pass so the downstream node
78
+ * typechecks/runs against the realized output rather than stale `dist/`. The
79
+ * rebuild is build-FREE single-flight at the package level — one central build,
80
+ * never a per-node `npm run build` racing it (CE-001).
81
+ */
82
+ const SHARED_REBUILD_BETWEEN_LEVELS_NOTE = `## Shared rebuild between dependency levels
83
+
84
+ These nodes were selected because their dependencies are verified-complete. When a
85
+ node you just merged edited a shared/upstream surface a later node depends on,
86
+ rebuild that surface ONCE — \`npm run build\`
87
+ — before the next \`next-step\` dispatches the now-eligible downstream nodes, so they
88
+ build against the realized upstream output. Do not run a per-node \`npm run build\`;
89
+ the central rebuild is single-flight (one build, never one-per-node racing \`dist/\`).`;
90
+ function resolveRoot(root) {
91
+ return resolve(root ?? ".");
92
+ }
93
+ function resolveArtifactsDir(root, artifactsDir) {
94
+ return resolve(artifactsDir ?? join(root, ".audit-tools", "remediation"));
95
+ }
96
+ function stateRunId(state) {
97
+ return state?.plan?.plan_id ?? randomRunId("REMEDIATE");
98
+ }
99
+ function defaultInputCandidates(root) {
100
+ // Prefer the canonical machine contract (audit-findings.json) over its
101
+ // human-facing render (audit-report.md). The JSON is the source of truth on
102
+ // both sides of the audit -> remediate pipeline, and feeding it triggers the
103
+ // lossless structured hand-off in the plan phase instead of a lossy LLM
104
+ // re-extraction from the markdown render that sits beside it.
105
+ return [
106
+ join(root, ".audit-tools", "audit-findings.json"),
107
+ join(root, ".audit-tools", "audit", "audit-findings.json"),
108
+ join(root, "audit-findings.json"),
109
+ join(root, ".audit-tools", "audit-report.md"),
110
+ join(root, ".audit-tools", "audit", "audit-report.md"),
111
+ join(root, "audit-report.md"),
112
+ ];
113
+ }
114
+ function inputValues(input) {
115
+ if (input === undefined)
116
+ return [];
117
+ return Array.isArray(input) ? input : [input];
118
+ }
119
+ function resolveInputPaths(root, input) {
120
+ const values = inputValues(input).filter((value) => value.trim().length > 0);
121
+ if (values.length > 0) {
122
+ const checked = values.map((value) => resolve(root, value));
123
+ return {
124
+ supplied: true,
125
+ existing: checked.filter((candidate) => existsSync(candidate)),
126
+ missing: checked.filter((candidate) => !existsSync(candidate)),
127
+ checked,
128
+ };
129
+ }
130
+ const checked = defaultInputCandidates(root);
131
+ // Default discovery probes the same logical artifact (the audit output) in
132
+ // several canonical locations and two formats. Select the single
133
+ // highest-priority match — never feed both the structured contract and its
134
+ // markdown render — so a lone .json input takes the lossless structured
135
+ // fast-path instead of being demoted to multi-source LLM extraction.
136
+ const best = checked.find((candidate) => existsSync(candidate));
137
+ return {
138
+ supplied: false,
139
+ existing: best ? [best] : [],
140
+ missing: [],
141
+ checked,
142
+ };
143
+ }
144
+ export { NO_CHANGE_RE, dependenciesSatisfied, dependencyVerifiedComplete, specIndicatesNoChange, classifyFindingRisk, } from "./stepUtils.js";
145
+ export { isTerminalStatus, isVerifiedCompleteStatus };
146
+ function documentableFindings(state) {
147
+ if (!state.plan || !state.items)
148
+ return [];
149
+ return state.plan.findings.filter((finding) => state.items?.[finding.id]?.status === "pending");
150
+ }
151
+ /**
152
+ * Blocks/nodes eligible for the next rolling dispatch pass: those with pending
153
+ * work AND every dependency VERIFIED-COMPLETE (INV-RS-01 — a SKIP or blocked
154
+ * dependency never makes a dependent eligible). This is the rolling-scheduler
155
+ * eligibility gate; it replaced the old `dependenciesSatisfied` (any-terminal)
156
+ * wave gate so a node whose prerequisite was skipped/blocked is held back rather
157
+ * than dispatched against a surface that never landed.
158
+ */
159
+ function implementableBlocks(state) {
160
+ if (!state.plan || !state.items)
161
+ return [];
162
+ return state.plan.blocks.filter((block) => dependencyVerifiedComplete(block, state) &&
163
+ block.items.some((findingId) => {
164
+ const item = state.items?.[findingId];
165
+ return item?.status === "pending";
166
+ }));
167
+ }
168
+ /**
169
+ * Pending nodes that are NOT eligible because at least one dependency did not
170
+ * reach a verified-complete disposition (a prerequisite was skipped, blocked, or
171
+ * is still pending). Once no eligible block remains, these are dead-ended: the
172
+ * rolling scheduler marks them `blocked` (their upstream surface never landed)
173
+ * rather than looping forever. Used by `handlePlanning` to make that transition
174
+ * deterministic.
175
+ */
176
+ function blockedByUnsatisfiedDependency(state) {
177
+ if (!state.plan || !state.items)
178
+ return [];
179
+ return state.plan.blocks.filter((block) => !dependencyVerifiedComplete(block, state) &&
180
+ block.items.some((findingId) => state.items?.[findingId]?.status === "pending"));
181
+ }
182
+ // ---------------------------------------------------------------------------
183
+ // Rolling per-node scheduler (CP-BLOCK-N-rolling-scheduler)
184
+ // ---------------------------------------------------------------------------
185
+ //
186
+ // The rolling scheduler replaced the wave-batch shim: instead of dispatching one
187
+ // fixed-size wave per next-step and folding back through `implementing`, a node
188
+ // becomes eligible the instant every dependency reaches a verified-complete
189
+ // disposition (INV-RS-01). Concurrency is owned entirely by the quota scheduler
190
+ // (the `dispatch-quota.json` max_concurrent_agents from `scheduleWave` /
191
+ // `computeDispatchCapacity` — INV-S05 / INV-QD-11), never a separate wave cap.
192
+ // A shared rebuild is interposed between dependency levels so a downstream node
193
+ // typechecks/runs against the freshly-built upstream `audit-tools/shared`
194
+ // surface; the rebuild is single-flight (CE-001) so the same package is never
195
+ // built twice or concurrently within one dispatch run.
196
+ /**
197
+ * Partition pending nodes into rolling dependency LEVELS. Level 0 is every
198
+ * pending node already eligible (deps verified-complete now); each subsequent
199
+ * level is the pending nodes that become eligible once all earlier levels are
200
+ * assumed verified-complete. The boundary between two levels is exactly where a
201
+ * shared rebuild is interposed (so a later level builds against the realized
202
+ * upstream surface). A node with a permanently-unsatisfiable edge (its
203
+ * prerequisite is skipped/blocked, not merely pending) is NOT placed in any
204
+ * level — it is dead-ended by `handlePlanning`.
205
+ *
206
+ * Pure and deterministic: levels and the nodes within a level are ordered by
207
+ * block_id so the interposed-rebuild boundaries are stable across runs.
208
+ */
209
+ export function rollingDependencyLevels(state) {
210
+ const plan = state.plan;
211
+ const items = state.items;
212
+ if (!plan || !items)
213
+ return [];
214
+ const blockById = new Map(plan.blocks.map((b) => [b.block_id, b]));
215
+ const pendingBlocks = plan.blocks
216
+ .filter((b) => b.items.some((id) => items[id]?.status === "pending"))
217
+ .sort((a, b) => a.block_id.localeCompare(b.block_id));
218
+ // A dependency edge is "completable" only when the dep node is itself pending
219
+ // (will be satisfied by some level) or already verified-complete. A skipped /
220
+ // blocked dependency makes the dependent permanently ineligible — such nodes
221
+ // never enter a level (INV-RS-01).
222
+ const isVerifiedNow = (depBlock) => depBlock.items.every((id) => isVerifiedCompleteStatus(items[id]?.status));
223
+ const isPending = (depBlock) => depBlock.items.some((id) => items[id]?.status === "pending");
224
+ const permanentlyIneligible = (block) => {
225
+ for (const depId of block.dependencies ?? []) {
226
+ const dep = blockById.get(depId);
227
+ if (!dep)
228
+ continue; // dangling edge never strands the DAG
229
+ if (!isVerifiedNow(dep) && !isPending(dep))
230
+ return true; // skipped/blocked dep
231
+ }
232
+ return false;
233
+ };
234
+ const levels = [];
235
+ const placed = new Set();
236
+ let remaining = pendingBlocks.filter((b) => !permanentlyIneligible(b));
237
+ while (remaining.length > 0) {
238
+ const ready = remaining.filter((block) => (block.dependencies ?? []).every((depId) => {
239
+ const dep = blockById.get(depId);
240
+ if (!dep)
241
+ return true; // dangling edge
242
+ // Satisfied if already verified-complete, or every pending item of the
243
+ // dep was placed in an earlier level (so it will be verified by then).
244
+ if (isVerifiedNow(dep))
245
+ return true;
246
+ return dep.items.every((id) => isVerifiedCompleteStatus(items[id]?.status) ||
247
+ (items[id]?.status === "pending" && placed.has(dep.block_id)));
248
+ }));
249
+ if (ready.length === 0) {
250
+ // A cycle among the remaining pending nodes: no further level can form.
251
+ // Leave them unplaced — `handlePlanning` marks them blocked deterministically.
252
+ break;
253
+ }
254
+ levels.push(ready);
255
+ for (const block of ready)
256
+ placed.add(block.block_id);
257
+ remaining = remaining.filter((b) => !placed.has(b.block_id));
258
+ }
259
+ return levels;
260
+ }
261
+ /**
262
+ * Drive a rolling per-node dispatch run IN PROCESS over the precomputed
263
+ * dependency levels, wiring onto the shared `createRollingDispatcher`
264
+ * (quota-only throttle; transient-429 re-queue + empty-pool stranding owned by
265
+ * the shared engine). The driver's own responsibilities are the two properties
266
+ * the shared engine does not own:
267
+ * 1. SHARED-REBUILD-BETWEEN-LEVELS — after a level completes, rebuild the
268
+ * upstream surface before the next level dispatches, so dependents
269
+ * typecheck/run against the realized upstream output.
270
+ * 2. SINGLE-FLIGHT BUILD (CE-001) — the rebuild runs exactly once per
271
+ * inter-level boundary, never twice or concurrently.
272
+ *
273
+ * Within a level, concurrency is whatever the shared engine's quota headroom
274
+ * allows over `confirmedPools` — there is no wave-size cap (INV-S05).
275
+ */
276
+ export async function driveRollingDispatch(levels, options) {
277
+ if (options.quotaStateDir) {
278
+ setQuotaStateDir(options.quotaStateDir);
279
+ }
280
+ const estimateTokens = options.estimateTokens ?? (() => 2000);
281
+ const out = { levels: [], rebuilds: 0 };
282
+ let rebuildInFlight = false; // single-flight guard (CE-001)
283
+ for (let levelIndex = 0; levelIndex < levels.length; levelIndex++) {
284
+ const level = levels[levelIndex];
285
+ // Interpose the shared rebuild BEFORE every level after the first. Guarded so
286
+ // it can never run twice or concurrently for the same boundary.
287
+ if (levelIndex > 0) {
288
+ if (rebuildInFlight) {
289
+ throw new Error("driveRollingDispatch: shared rebuild already in flight — single-flight invariant violated (CE-001).");
290
+ }
291
+ rebuildInFlight = true;
292
+ try {
293
+ await options.rebuildSharedBetweenLevels();
294
+ out.rebuilds += 1;
295
+ }
296
+ finally {
297
+ rebuildInFlight = false;
298
+ }
299
+ }
300
+ const blockByPacketId = new Map(level.map((b) => [b.block_id, b]));
301
+ const packets = level.map((block) => ({
302
+ id: block.block_id,
303
+ payload: { block_id: block.block_id },
304
+ estimatedTokens: estimateTokens(block),
305
+ complexity: 0.5,
306
+ }));
307
+ const dispatcher = createRollingDispatcher({
308
+ confirmedPools: options.confirmedPools,
309
+ sessionConfig: options.sessionConfig,
310
+ dispatchPacket: async (packet, slot) => {
311
+ const block = blockByPacketId.get(packet.payload.block_id);
312
+ return options.dispatchNode(block, slot);
313
+ },
314
+ });
315
+ dispatcher.enqueue(packets);
316
+ const results = await dispatcher.run();
317
+ out.levels.push({ blockIds: level.map((b) => b.block_id), results });
318
+ }
319
+ return out;
320
+ }
321
+ /**
322
+ * Backends the orchestrator can drive IN-PROCESS as the per-node implement worker
323
+ * via `driveRollingImplementDispatch` (it resolves + launches the provider with each
324
+ * node's worktree-rooted prompt, cwd-confined to that worktree). The conversation
325
+ * host (claude-code) and IDE-bound providers (vscode-task / antigravity) are
326
+ * excluded: claude-code self-blocks inside a session, and the IDE providers have no
327
+ * headless invocation. "auto" is intentionally absent — auto-resolution stays on the
328
+ * conversation host-subagent default, so the in-process driver is opt-in via an
329
+ * EXPLICIT backend provider in session config. When one is set, it takes precedence
330
+ * over the host-subagent driver: an operator who configured a backend (e.g. a NIM
331
+ * pool for headless autonomy) wants it to do the implement work, not the host.
332
+ */
333
+ const IN_PROCESS_DISPATCH_PROVIDERS = new Set([
334
+ "openai-compatible",
335
+ "codex",
336
+ "opencode",
337
+ "subprocess-template",
338
+ "local-subprocess",
339
+ ]);
340
+ function resolvesToInProcessDispatchProvider(sessionConfig) {
341
+ const provider = sessionConfig?.provider;
342
+ return provider !== undefined && IN_PROCESS_DISPATCH_PROVIDERS.has(provider);
343
+ }
344
+ /**
345
+ * Drive the implement phase through the in-process rolling engine. Engages the
346
+ * shared `createRollingDispatcher` (via `driveRollingDispatch`) over
347
+ * quota-derived `confirmedPools`, runs each node in an isolated worktree, gates
348
+ * acceptance on a per-node verify, and finally merges through the deterministic
349
+ * `mergeImplementResults`. Returns null when there is no eligible pending work.
350
+ *
351
+ * SAFETY: this never touches the main tree except through `mergeWorktree` (which
352
+ * cherry-picks a verified branch and aborts cleanly on conflict). A node whose
353
+ * verify fails is NOT merged; its worktree is removed and the deterministic merge
354
+ * marks it blocked (its result file is absent / unaccounted) so the run routes it
355
+ * to triage rather than landing an unverified change.
356
+ */
357
+ export async function driveRollingImplementDispatch(options) {
358
+ const { root, artifactsDir, runId } = options;
359
+ // Prepare the dispatch plan (eligible verified-complete frontier) with the SAME
360
+ // quota-derived sizing the wave path uses. This writes per-node prompts +
361
+ // dispatch-plan.json + dispatch-quota.json.
362
+ const plan = await prepareImplementDispatch({ root, artifactsDir }, runId, undefined, {
363
+ hostMaxConcurrent: options.waveOptions?.hostMaxConcurrent,
364
+ sessionConfig: options.sessionConfig,
365
+ hostContextTokens: options.waveOptions?.hostContextTokens,
366
+ hostOutputTokens: options.waveOptions?.hostOutputTokens,
367
+ hostModels: options.waveOptions?.hostModels,
368
+ hostModelId: options.waveOptions?.hostModelId,
369
+ // Each node runs in its own worktree, so its prompt is rooted there.
370
+ worktreeRootedPrompts: true,
371
+ });
372
+ if (plan.items.length === 0) {
373
+ return null;
374
+ }
375
+ // Map each planned block id to its result path so the per-node dispatcher
376
+ // writes where the merge expects to read.
377
+ const resultPathByBlock = new Map(plan.items
378
+ .filter((i) => typeof i.block_id === "string")
379
+ .map((i) => [i.block_id, i.result_path]));
380
+ // Map each planned block id to its worktree-rooted prompt path so the
381
+ // provider-backed dispatcher launches the worker with the right prompt.
382
+ const promptPathByBlock = new Map(plan.items
383
+ .filter((i) => typeof i.block_id === "string")
384
+ .map((i) => [i.block_id, i.prompt_path]));
385
+ // The live per-node worker: the configured provider, launched with the node's
386
+ // worktree-rooted prompt and cwd = its worktree. Tests inject `options.dispatchNode`
387
+ // to exercise the engine without spawning a real worker.
388
+ const dispatchNode = options.dispatchNode ??
389
+ makeProviderNodeDispatcher({
390
+ root,
391
+ artifactsDir,
392
+ runId,
393
+ sessionConfig: options.sessionConfig,
394
+ promptPathByBlock,
395
+ });
396
+ // Confirmed pools: quota-derived concurrency, never the raw host flag (INV-QD-11).
397
+ const confirmedPools = await buildConfirmedPools({
398
+ sessionConfig: options.sessionConfig,
399
+ hostMaxConcurrent: options.waveOptions?.hostMaxConcurrent,
400
+ hostContextTokens: options.waveOptions?.hostContextTokens,
401
+ hostOutputTokens: options.waveOptions?.hostOutputTokens,
402
+ hostModels: options.waveOptions?.hostModels,
403
+ hostModelId: options.waveOptions?.hostModelId,
404
+ });
405
+ // Load state to partition the eligible frontier into rolling dependency levels.
406
+ const state = await new StateStore(artifactsDir).loadState();
407
+ if (!state)
408
+ return null;
409
+ const plannedBlockIds = new Set(resultPathByBlock.keys());
410
+ const allLevels = rollingDependencyLevels(state);
411
+ // Keep only the blocks that were actually planned this dispatch (eligible now).
412
+ const levels = allLevels
413
+ .map((level) => level.filter((b) => plannedBlockIds.has(b.block_id)))
414
+ .filter((level) => level.length > 0);
415
+ const nodeOutcomes = [];
416
+ // Per-node worktree dispatch + verify-before-accept, wrapped so the rolling
417
+ // engine's dispatchNode callback always RESOLVES (never rejects).
418
+ const dispatchNodeWithWorktree = async (block, slot) => {
419
+ const branch = worktreeBranchForBlock(block.block_id, runId);
420
+ const wt = worktreePath(root, block.block_id, runId);
421
+ const resultPath = resultPathByBlock.get(block.block_id);
422
+ try {
423
+ // Idempotent reset of any worktree dir AND leftover branch from a prior
424
+ // attempt before creating this node's isolated worktree. A `rate_limited`
425
+ // re-queue re-enters this dispatcher for the same block with the branch
426
+ // still present; a bare `createWorktree -b` would then fail with "branch
427
+ // already exists". `resetNodeWorktreeAndBranch` clears both (+ prunes stale
428
+ // admin entries) so every (re-)dispatch starts clean from HEAD.
429
+ resetNodeWorktreeAndBranch(root, wt, branch);
430
+ createWorktree(root, wt, branch);
431
+ // A fresh worktree has no node_modules (gitignored); link the main checkout's
432
+ // so this node's verify commands can run.
433
+ ensureWorktreeNodeModules(root, wt);
434
+ const result = await dispatchNode({
435
+ block,
436
+ slot,
437
+ worktreeRoot: wt,
438
+ resultPath,
439
+ });
440
+ // Shared post-worker lifecycle (commit → verify → merge), identical to the
441
+ // host-subagent driver's `accept-node` callback. Records the LIFECYCLE
442
+ // outcome but returns the worker's TRANSPORT result to the engine (so a
443
+ // rate_limited worker re-queues; a verify-failure routes to triage via merge).
444
+ const targeted = uniqueStrings(block.items.flatMap((id) => {
445
+ const finding = state.plan?.findings.find((f) => f.id === id);
446
+ return finding?.targeted_commands ?? [];
447
+ }));
448
+ const accept = acceptNodeWorktree({
449
+ root,
450
+ runId,
451
+ blockId: block.block_id,
452
+ worktreeRoot: wt,
453
+ branch,
454
+ workerOutcome: result.outcome,
455
+ targetedCommands: targeted,
456
+ });
457
+ // Persist the tool-owned verify/merge outcome so finalization blocks a node
458
+ // that self-reported resolved but never actually landed (OBL-DS-06). Parity
459
+ // with the host-subagent driver's `accept-node` callback.
460
+ await recordNodeAcceptOutcome(artifactsDir, runId, block.block_id, accept);
461
+ nodeOutcomes.push({
462
+ block_id: block.block_id,
463
+ outcome: accept.outcome,
464
+ verify_passed: accept.verifyPassed,
465
+ merged: accept.merged,
466
+ });
467
+ return result;
468
+ }
469
+ catch (err) {
470
+ removeWorktree(root, wt);
471
+ await recordNodeAcceptOutcome(artifactsDir, runId, block.block_id, {
472
+ outcome: "error",
473
+ verifyPassed: false,
474
+ merged: false,
475
+ });
476
+ nodeOutcomes.push({ block_id: block.block_id, outcome: "error", verify_passed: false, merged: false });
477
+ return {
478
+ packet: { id: block.block_id, payload: { block_id: block.block_id }, estimatedTokens: 0, complexity: 0.5 },
479
+ outcome: "error",
480
+ error: err,
481
+ };
482
+ }
483
+ };
484
+ await driveRollingDispatch(levels, {
485
+ confirmedPools,
486
+ sessionConfig: options.sessionConfig ?? {},
487
+ dispatchNode: dispatchNodeWithWorktree,
488
+ rebuildSharedBetweenLevels: options.rebuildSharedBetweenLevels,
489
+ quotaStateDir: artifactsDir,
490
+ });
491
+ // Deterministic merge: same path the wave flow uses (tolerant remap, write-scope
492
+ // gate against each verified branch, lost-update detection). Worktrees are
493
+ // already removed; the merge reads each node's result file + branch diff.
494
+ const merged = await mergeImplementResults({ root, artifactsDir }, runId);
495
+ return {
496
+ nodes: nodeOutcomes,
497
+ rebuilds: Math.max(0, levels.length - 1),
498
+ state_status: merged.status,
499
+ };
500
+ }
501
+ /** Dedupe a string list preserving order (local helper for verify command sets). */
502
+ function uniqueStrings(values) {
503
+ return [...new Set(values.filter((v) => typeof v === "string" && v.length > 0))];
504
+ }
505
+ /**
506
+ * Whether `root` is the audit-tools monorepo — the repo the tool-owned final
507
+ * gate's suite (INV-RS-10, literally the audit-tools build/check/per-package
508
+ * commands) applies to. The gate's command list is audit-tools-specific by
509
+ * design (this remediation run remediates the audit-tools monorepo), so it is
510
+ * scoped to that structure rather than fabricated for an arbitrary target repo.
511
+ */
512
+ export function isAuditToolsMonorepo(root) {
513
+ // Single-package layout: the three subsystems are inlined under src/ and both
514
+ // bins live at the repo root. (Name kept for continuity; it is now one package.)
515
+ return (existsSync(join(root, "src", "shared")) &&
516
+ existsSync(join(root, "src", "audit")) &&
517
+ existsSync(join(root, "src", "remediate")) &&
518
+ existsSync(join(root, "audit-code.mjs")) &&
519
+ existsSync(join(root, "remediate-code.mjs")));
520
+ }
521
+ /**
522
+ * The tool-owned final-gate command list (INV-RS-10) for the audit-tools
523
+ * monorepo. Pure and deterministic so tests can assert: it is non-vacuous
524
+ * (always > 0 build + check + unit commands) for the audit-tools structure,
525
+ * never references `plan.test_command`, every UNIT command is build-free, and no
526
+ * package's unit suite appears twice (single-flight — CE-001). Returns `[]` when
527
+ * `root` is not the audit-tools monorepo (the audit-tools-specific suite is
528
+ * inapplicable there — see `runToolOwnedFinalGate`).
529
+ */
530
+ export function toolOwnedFinalGateCommands(root) {
531
+ if (!isAuditToolsMonorepo(root))
532
+ return [];
533
+ return [
534
+ { argv: ["npm", "run", "build"], build_free: false, layer: "build" },
535
+ { argv: ["npm", "run", "check"], build_free: true, layer: "check" },
536
+ // BUILD-FREE unit suites at the repo root (single package — no `npm -w`, never
537
+ // `npm test`, which prepends a build). node:test for shared+audit, vitest for remediate.
538
+ {
539
+ argv: ["node", "--import", "tsx/esm", "--test", "tests/shared/*.test.mjs", "tests/audit/*.test.mjs"],
540
+ build_free: true,
541
+ layer: "unit",
542
+ },
543
+ {
544
+ argv: ["npx", "vitest", "run"],
545
+ build_free: true,
546
+ layer: "unit",
547
+ },
548
+ ];
549
+ }
550
+ /**
551
+ * Run the tool-owned final gate (INV-RS-10). Each command runs through
552
+ * `runCommand` → shared `runTracked`, which scrubs CLAUDECODE / CLAUDE_CODE_*.
553
+ * The first failing command short-circuits the floor (a broken build makes the
554
+ * later layers meaningless). A `runner` may be injected for tests. When the
555
+ * audit-tools suite does not apply (non-monorepo target), the gate is
556
+ * `scoped_out` (does not block) rather than vacuously passing.
557
+ */
558
+ export async function runToolOwnedFinalGate(root, opts = {}) {
559
+ const runtime_residual = {
560
+ surface: "runtime/packaged-bin smokes (verify:release)",
561
+ commands: [
562
+ "npm run smoke:packaged-audit-code",
563
+ "npm run smoke:packaged-remediate-code",
564
+ ],
565
+ };
566
+ const commands = toolOwnedFinalGateCommands(root);
567
+ if (commands.length === 0) {
568
+ // Audit-tools-specific suite does not apply here — declared scope, not a
569
+ // vacuous pass (it never substitutes for a real gate on the audit-tools repo).
570
+ return { passed: true, results: [], scoped_out: true, runtime_residual };
571
+ }
572
+ const runner = opts.runner ??
573
+ ((argv, cwd, packageDir) => {
574
+ const [command, ...args] = argv;
575
+ // Package-scoped unit suites run with cwd at the package (no `npm -w`); the
576
+ // monorepo-root build/check commands run at the repo root.
577
+ const effectiveCwd = packageDir ? join(root, packageDir) : cwd;
578
+ // runCommand → runTracked strips CLAUDECODE / CLAUDE_CODE_* (INV-RS-10).
579
+ const result = runCommand(command, args, {
580
+ cwd: effectiveCwd,
581
+ stdio: ["ignore", "pipe", "pipe"],
582
+ });
583
+ return { status: result.status };
584
+ });
585
+ const results = [];
586
+ let passed = true;
587
+ for (const spec of commands) {
588
+ const { status } = runner(spec.argv, root, spec.package_dir);
589
+ const cmdPassed = status === 0;
590
+ results.push({
591
+ argv: spec.argv,
592
+ layer: spec.layer,
593
+ ...(spec.package_dir ? { package_dir: spec.package_dir } : {}),
594
+ exit_code: status,
595
+ passed: cmdPassed,
596
+ });
597
+ if (!cmdPassed) {
598
+ passed = false;
599
+ break; // short-circuit: later layers are meaningless on a broken floor
600
+ }
601
+ }
602
+ return { passed, results, scoped_out: false, runtime_residual };
603
+ }
604
+ /**
605
+ * The bound on coarse re-block iterations before the run converges to a terminal
606
+ * `blocked` close (CE-003). Two re-block attempts give a flaky-but-recoverable
607
+ * suite a chance to settle; the third unattributable red terminates
608
+ * deterministically rather than livelocking.
609
+ */
610
+ export const COARSE_REBLOCK_BOUND = 2;
611
+ const FINAL_GATE_STATE_FILENAME = "final-gate.json";
612
+ async function readFinalGateSidecar(artifactsDir) {
613
+ const sidecar = await readOptionalJsonFile(join(artifactsDir, FINAL_GATE_STATE_FILENAME));
614
+ const n = sidecar?.coarse_reblock_count;
615
+ return {
616
+ count: typeof n === "number" && Number.isFinite(n) && n >= 0 ? n : 0,
617
+ terminated: sidecar?.terminated === true,
618
+ };
619
+ }
620
+ async function writeFinalGateSidecar(artifactsDir, count, terminated) {
621
+ await writeJsonFile(join(artifactsDir, FINAL_GATE_STATE_FILENAME), {
622
+ schema_version: "remediate-code-final-gate/v1alpha1",
623
+ coarse_reblock_count: count,
624
+ terminated,
625
+ });
626
+ }
627
+ /**
628
+ * Coarse re-block-ALL-non-terminal on an unattributable final-gate red
629
+ * (INV-RS-09) with a bounded, monotonic auto-terminate (CE-003).
630
+ *
631
+ * The tool-owned gate is whole-repo, so a red is inherently unattributable to a
632
+ * single node. Below the bound, EVERY non-skip item (including `resolved` ones —
633
+ * a resolved item's own change may have caused the red) is re-opened to `pending`
634
+ * and the run re-attempts the whole repo through the rolling scheduler
635
+ * (`reattempt_all` → `implementing`). At or above the bound, the run STOPS
636
+ * re-attempting and converges DETERMINISTICALLY: every non-skip item becomes
637
+ * terminal `blocked` and the run advances to `closing`.
638
+ *
639
+ * CE-003 no-human-host guarantee: the loop is owned entirely by the gate + the
640
+ * rolling scheduler — it NEVER routes through the human triage prompt
641
+ * (`waiting_for_triage`) and is bounded by `bound`, so a permanently-red sibling
642
+ * converges to a terminal `blocked` close deterministically: never livelocking,
643
+ * never stranding on a human prompt, and never force-closed to green (a RED gate
644
+ * always leaves `blocked` items, so close.ts's `!anyBlocked` guard keeps the run
645
+ * out of the fully-green path). User SKIP dispositions (ignored /
646
+ * deemed_inappropriate) are settled decisions and are left alone. Pure (the
647
+ * counter is supplied / returned).
648
+ */
649
+ export function applyCoarseReblock(state, currentCount, gateSummary, bound = COARSE_REBLOCK_BOUND) {
650
+ const now = new Date().toISOString();
651
+ if (currentCount >= bound) {
652
+ // Bounded auto-terminate: converge DETERMINISTICALLY to a terminal `blocked`
653
+ // close for a no-human host — never livelock, never a triage prompt, never green.
654
+ for (const it of Object.values(state.items ?? {})) {
655
+ if (isSkipStatus(it.status))
656
+ continue; // settled user decision — never overturn
657
+ it.status = "blocked";
658
+ it.started_at ??= now;
659
+ it.completed_at = now;
660
+ it.failure_reason =
661
+ `Tool-owned final gate failed and the coarse re-block backstop reached its ` +
662
+ `bound (${bound}); converging to a terminal blocked close (no-human host). ${gateSummary}`;
663
+ }
664
+ return { state, action: "terminal_blocked", next_count: currentCount };
665
+ }
666
+ // Below the bound: re-open every non-skip item to `pending` and re-attempt the
667
+ // whole repo via the rolling scheduler (NOT the human triage prompt).
668
+ for (const it of Object.values(state.items ?? {})) {
669
+ if (isSkipStatus(it.status))
670
+ continue;
671
+ it.status = "pending";
672
+ it.failure_context =
673
+ `Re-attempted by the coarse final-gate backstop (unattributable whole-repo red). ${gateSummary}`;
674
+ delete it.completed_at;
675
+ }
676
+ return { state, action: "reattempt_all", next_count: currentCount + 1 };
677
+ }
678
+ function resolvedOrTerminalItems(state) {
679
+ return Object.values(state.items ?? {}).filter((item) => isTerminalStatus(item.status));
680
+ }
681
+ function allItemsTerminal(state) {
682
+ const items = Object.values(state.items ?? {});
683
+ return items.length > 0 && resolvedOrTerminalItems(state).length === items.length;
684
+ }
685
+ function normalizeExtractedPlan(value) {
686
+ if (!isRecord(value)) {
687
+ throw new Error("extracted-plan.json must be an object.");
688
+ }
689
+ const rawFindings = Array.isArray(value.findings) ? value.findings : [];
690
+ const findings = rawFindings.map((finding) => {
691
+ if (!isRecord(finding))
692
+ return finding;
693
+ return {
694
+ category: "General",
695
+ affected_files: [],
696
+ evidence: [],
697
+ ...finding,
698
+ };
699
+ });
700
+ const rawBlocks = Array.isArray(value.blocks) ? value.blocks : [];
701
+ const blocks = rawBlocks.length > 0
702
+ ? rawBlocks.map((block) => {
703
+ if (!isRecord(block))
704
+ return block;
705
+ return {
706
+ parallel_safe: true,
707
+ dependencies: [],
708
+ ...block,
709
+ };
710
+ })
711
+ : findings.map((finding, index) => ({
712
+ block_id: `B-${String(index + 1).padStart(3, "0")}`,
713
+ items: [finding.id],
714
+ parallel_safe: true,
715
+ }));
716
+ const dedup = deduplicateCrossLensFindings(findings);
717
+ const dedupBlocks = fixupBlocksAfterDedup(blocks, dedup.mergeMap);
718
+ const plan = {
719
+ plan_id: typeof value.plan_id === "string" ? value.plan_id : randomRunId("PLAN"),
720
+ ...(typeof value.goal_id === "string" ? { goal_id: value.goal_id } : {}),
721
+ ...(typeof value.source === "string" ? { source: value.source } : {}),
722
+ findings: dedup.findings,
723
+ blocks: dedupBlocks,
724
+ project_type: typeof value.project_type === "string" ? value.project_type : "unknown",
725
+ test_command: typeof value.test_command === "string" ? value.test_command : undefined,
726
+ e2e_command: typeof value.e2e_command === "string" ? value.e2e_command : undefined,
727
+ candidate_closing_actions: ["none"],
728
+ block_strategy: value.block_strategy === "test_graph" ||
729
+ value.block_strategy === "git_cocommit" ||
730
+ value.block_strategy === "file_overlap" ||
731
+ value.block_strategy === "manual"
732
+ ? value.block_strategy
733
+ : undefined,
734
+ };
735
+ const issues = validateRemediationPlan(plan).filter((issue) => issue.severity === "error");
736
+ if (issues.length > 0) {
737
+ throw new Error(`Invalid extracted plan:\n${formatValidationIssues(issues)}`);
738
+ }
739
+ if (plan.findings.length === 0) {
740
+ throw new Error("Extracted plan contains zero findings.");
741
+ }
742
+ return { plan, sourceFindings: findings, mergeMap: dedup.mergeMap };
743
+ }
744
+ async function saveStateForPlan(artifactsDir, existing, plan, planCoverage) {
745
+ const items = {};
746
+ for (const finding of plan.findings) {
747
+ const block = plan.blocks.find((candidate) => candidate.items.includes(finding.id));
748
+ items[finding.id] = {
749
+ finding_id: finding.id,
750
+ status: "pending",
751
+ block_id: block?.block_id ?? "UNKNOWN",
752
+ };
753
+ }
754
+ const state = {
755
+ ...existing,
756
+ status: "planning",
757
+ plan,
758
+ items,
759
+ closing_plan: { action: "none" },
760
+ ...(planCoverage ? { plan_coverage: planCoverage } : {}),
761
+ };
762
+ await new StateStore(artifactsDir).saveState(state);
763
+ await writeJsonFile(join(artifactsDir, "remediation_plan.json"), plan);
764
+ return state;
765
+ }
766
+ // Plan-time bookkeeping recomputed on every plan pass; it must not participate
767
+ // in the carry-forward identity of a finding.
768
+ const PLAN_TIME_BOOKKEEPING_KEYS = new Set([
769
+ "hash_at_plan_time",
770
+ "evidence_grounded",
771
+ ]);
772
+ function stripPlanTimeBookkeeping(value) {
773
+ if (Array.isArray(value)) {
774
+ return value.map((entry) => stripPlanTimeBookkeeping(entry));
775
+ }
776
+ if (!isRecord(value)) {
777
+ return value;
778
+ }
779
+ const stripped = {};
780
+ for (const key of Object.keys(value).sort()) {
781
+ if (PLAN_TIME_BOOKKEEPING_KEYS.has(key))
782
+ continue;
783
+ stripped[key] = stripPlanTimeBookkeeping(value[key]);
784
+ }
785
+ return stripped;
786
+ }
787
+ function findingCarryForwardKey(finding) {
788
+ return JSON.stringify(stripPlanTimeBookkeeping(finding));
789
+ }
790
+ function blockIdsByFinding(plan) {
791
+ const byFinding = new Map();
792
+ for (const block of plan.blocks) {
793
+ for (const id of block.items) {
794
+ byFinding.set(id, block.block_id);
795
+ }
796
+ }
797
+ return byFinding;
798
+ }
799
+ function carryForwardMatchingItems(previous, replanned) {
800
+ if (!previous.plan || !previous.items || !replanned.plan || !replanned.items) {
801
+ return replanned;
802
+ }
803
+ const previousFindings = new Map(previous.plan.findings.map((finding) => [finding.id, finding]));
804
+ const replannedBlockIds = blockIdsByFinding(replanned.plan);
805
+ const items = { ...replanned.items };
806
+ let carried = false;
807
+ for (const finding of replanned.plan.findings) {
808
+ const previousFinding = previousFindings.get(finding.id);
809
+ const previousItem = previous.items[finding.id];
810
+ // Skip items that were never documented (pending with no item_spec). Under
811
+ // N-R13 (document phase dissolved), a pending item that already has an
812
+ // item_spec from a prior planning/document pass should carry forward
813
+ // together with its spec rather than being discarded.
814
+ if (!previousFinding || !previousItem) {
815
+ continue;
816
+ }
817
+ if (previousItem.status === "pending" && !previousItem.item_spec) {
818
+ continue;
819
+ }
820
+ if (findingCarryForwardKey(previousFinding) !== findingCarryForwardKey(finding)) {
821
+ continue;
822
+ }
823
+ items[finding.id] = {
824
+ ...previousItem,
825
+ block_id: replannedBlockIds.get(finding.id) ?? previousItem.block_id,
826
+ };
827
+ carried = true;
828
+ }
829
+ if (!carried) {
830
+ return replanned;
831
+ }
832
+ const hasPending = replanned.plan.findings.some((finding) => items[finding.id]?.status === "pending");
833
+ return {
834
+ ...replanned,
835
+ items,
836
+ status: hasPending ? "planning" : replanned.status,
837
+ };
838
+ }
839
+ async function forceReplanFromExistingIntake(root, artifactsDir, previous, store) {
840
+ const pendingState = {
841
+ status: "pending",
842
+ started_at: previous.started_at,
843
+ step_count: previous.step_count,
844
+ };
845
+ const extractedPlan = await readExtractedPlanIfPresent(artifactsDir);
846
+ if (!extractedPlan) {
847
+ await store.saveState(pendingState);
848
+ return null;
849
+ }
850
+ const replanned = await handlePendingExtractedPlan(root, artifactsDir, pendingState, extractedPlan);
851
+ if (!replanned) {
852
+ return null;
853
+ }
854
+ const carried = carryForwardMatchingItems(previous, replanned);
855
+ await store.saveState(carried);
856
+ return carried;
857
+ }
858
+ async function presentReportStep(root, artifactsDir, state) {
859
+ const reportPath = join(dirname(artifactsDir), "remediation-report.md");
860
+ return writeCurrentStep({
861
+ stepKind: "present_report",
862
+ status: "complete",
863
+ runId: stateRunId(state),
864
+ repoRoot: root,
865
+ artifactsDir,
866
+ prompt: `
867
+ # Present Remediation Report
868
+
869
+ Read \`${reportPath}\` and summarize the remediation outcome for the user.
870
+ Mention the resolved, ignored, and deemed-inappropriate counts plus the closing action.
871
+ Stop after presenting the summary.
872
+ `,
873
+ allowedCommands: [],
874
+ stopCondition: "Stop after presenting the remediation report summary.",
875
+ artifactPaths: {
876
+ final_report: reportPath,
877
+ },
878
+ });
879
+ }
880
+ async function buildImplementDispatchStep(ctx) {
881
+ const { root, artifactsDir, state, options, store } = ctx;
882
+ const sessionConfigImpl = options.sessionConfig ??
883
+ await readOptionalJsonFile(join(root, ".remediation-artifacts", "session-config.json")) ?? await readOptionalJsonFile(join(root, "session-config.json"));
884
+ const canDispatchImpl = resolveHostDispatchCapability({
885
+ hostCanDispatchSubagents: options.hostCanDispatchSubagents,
886
+ sessionConfig: sessionConfigImpl,
887
+ });
888
+ // A8 host-subagent rolling driver: when the rolling engine is enabled AND the
889
+ // host can dispatch subagents, drive a FULL-ROLLING, worktree-isolated flow via
890
+ // the `accept-node` per-completion callback — the conversation-first co-equal of
891
+ // the in-process provider engine (`driveRollingImplementDispatch`), sharing the
892
+ // same `acceptNodeWorktree` core. Gated behind the flag so the default stays the
893
+ // proven host-fanned wave step until the rolling path is validated end-to-end.
894
+ const rollingEngineEnabled = resolveRollingEngineEnabled({
895
+ rollingEngine: options.rollingEngine,
896
+ sessionConfig: sessionConfigImpl,
897
+ });
898
+ const runId = stateRunId(state);
899
+ const waveOptsImpl = {
900
+ hostMaxConcurrent: options.hostMaxConcurrent,
901
+ sessionConfig: sessionConfigImpl ?? null,
902
+ hostContextTokens: options.hostContextTokens,
903
+ hostOutputTokens: options.hostOutputTokens,
904
+ hostModels: options.hostModels,
905
+ hostModelId: options.hostModelId,
906
+ };
907
+ // A8 in-process provider driver: when the rolling engine is enabled AND the
908
+ // operator EXPLICITLY configured a programmatic backend provider (openai-compatible
909
+ // / codex / opencode / …), the orchestrator drives the FULL rolling implement
910
+ // dispatch ITSELF — the configured provider is the per-node worker, cwd-confined to
911
+ // each node's worktree, sharing the same `acceptNodeWorktree` core (commit → verify
912
+ // → merge, verify-fail → triage) as the host-subagent driver. Checked BEFORE the
913
+ // host-subagent branch so an explicit backend (e.g. a NIM pool for headless
914
+ // autonomy) drives the work rather than the conversation host's subagents.
915
+ if (rollingEngineEnabled && resolvesToInProcessDispatchProvider(sessionConfigImpl)) {
916
+ const driven = await driveRollingImplementDispatch({
917
+ root,
918
+ artifactsDir,
919
+ runId,
920
+ sessionConfig: sessionConfigImpl ?? null,
921
+ // Per-node verify (targeted_commands) owns each node's build/test; an
922
+ // inter-level "shared surface" rebuild is a monorepo-self-remediation concern
923
+ // the host-driven paths handle, not a generic target-repo step → no-op here.
924
+ rebuildSharedBetweenLevels: async () => { },
925
+ waveOptions: {
926
+ hostMaxConcurrent: options.hostMaxConcurrent,
927
+ hostContextTokens: options.hostContextTokens,
928
+ hostOutputTokens: options.hostOutputTokens,
929
+ hostModels: options.hostModels,
930
+ hostModelId: options.hostModelId,
931
+ },
932
+ });
933
+ // null = no eligible pending work this pass; the engine merges internally once
934
+ // it has run, so only the empty-frontier case needs a merge here. Either way the
935
+ // implement frontier is resolved — transition on the freshly-merged state so the
936
+ // engine re-scans (triage / closing) without recursion.
937
+ if (driven === null) {
938
+ await mergeImplementResults({ root, artifactsDir }, runId);
939
+ }
940
+ return { kind: "transition", state: await store.loadState() };
941
+ }
942
+ if (rollingEngineEnabled && canDispatchImpl) {
943
+ const rolling = await prepareHostRollingDispatch({ root, artifactsDir }, runId, waveOptsImpl);
944
+ // Everything eligible may already be done/skipped — fold straight to merge
945
+ // rather than emitting a dispatch step with zero nodes.
946
+ if (rolling.session.frontier.length === 0) {
947
+ await mergeImplementResults({ root, artifactsDir }, runId);
948
+ return { kind: "transition", state: await store.loadState() };
949
+ }
950
+ const rollMerge = loaderCommand(`merge-implement-results --run-id ${runId}`);
951
+ const rollNext = loaderCommand("next-step");
952
+ const acceptCmd = loaderCommand("accept-node --id <BLOCK_ID>");
953
+ const nodeLines = rolling.initial
954
+ .map((n) => `- \`${n.block_id}\` — prompt: \`${n.prompt_path}\` — worktree (subagent cwd): \`${n.worktree_root}\``)
955
+ .join("\n");
956
+ return { kind: "emit", step: await writeCurrentStep({
957
+ stepKind: "dispatch_implement_rolling",
958
+ status: "ready",
959
+ runId,
960
+ repoRoot: root,
961
+ artifactsDir,
962
+ prompt: `
963
+ # Dispatch Implementation Work (host-subagent rolling, worktree-isolated)
964
+
965
+ Each eligible node runs in its OWN git worktree (hard isolation between nodes). The
966
+ TOOL owns commit -> verify -> merge + write-scope; you only spawn a subagent per
967
+ node and call \`accept-node\` as each finishes.
968
+
969
+ Concurrency target: **${rolling.session.slots}** subagents at once (the quota
970
+ scheduler's \`max_concurrent_agents\`), NOT a wave cap.
971
+
972
+ Spawn ONE subagent for EACH initial node below. Give the subagent that node's
973
+ \`prompt\`, and set its working directory to the node's **worktree** path. The
974
+ subagent edits source files INSIDE that worktree and writes ONLY its result file.
975
+ Do NOT let any subagent edit the main repository tree.
976
+
977
+ Initial nodes (worktrees already created):
978
+ ${nodeLines}
979
+
980
+ As EACH subagent finishes, run (substituting the finished node's block id):
981
+
982
+ \`${acceptCmd}\`
983
+
984
+ It runs the commit -> verify -> merge lifecycle for that node and prints a JSON
985
+ directive on stdout:
986
+ - \`{"directive":"dispatch","node":{...},"worktree_root":"..."}\` — spawn a subagent
987
+ for that next node (its worktree is already created), keeping up to
988
+ ${rolling.session.slots} running.
989
+ - \`{"directive":"wait",...}\` — other nodes are still in flight; do not spawn more yet.
990
+ - \`{"directive":"done",...}\` — every node has been accepted. Then run:
991
+
992
+ ${DO_NOT_TOKEN_WRAP_NOTE}
993
+
994
+ \`${rollMerge}\`
995
+
996
+ Then run:
997
+
998
+ \`${rollNext}\`
999
+
1000
+ ${DISPATCH_PROMPT_HANDOFF_NOTE}
1001
+ `,
1002
+ allowedCommands: [acceptCmd, rollMerge, rollNext],
1003
+ stopCondition: "Stop after every node has been accepted (accept-node returns done), results merged, and next-step has been run.",
1004
+ artifactPaths: { dispatch_plan: rolling.planPath, dispatch_quota: rolling.quotaPath },
1005
+ }) };
1006
+ }
1007
+ // Rolling per-node dispatch: prepare EVERY currently-eligible node (deps all
1008
+ // verified-complete), never a single artificially-serialized block. There is
1009
+ // no wave-size cap — concurrency is owned by the quota scheduler
1010
+ // (`dispatch-quota.json` max_concurrent_agents). `prepareImplementDispatch`
1011
+ // itself only admits verified-complete-eligible blocks
1012
+ // (`dependencyVerifiedComplete`), so this is the rolling-eligible frontier.
1013
+ const dispatchPlan = await prepareImplementDispatch({ root, artifactsDir }, runId, undefined, waveOptsImpl);
1014
+ // Everything eligible may already be done or skipped (e.g. every Tier 3
1015
+ // finding excluded) — fold straight to merge rather than dispatching a wave
1016
+ // of zero workers.
1017
+ if (dispatchPlan.items.length === 0) {
1018
+ await mergeImplementResults({ root, artifactsDir }, runId);
1019
+ return { kind: "transition", state: await store.loadState() };
1020
+ }
1021
+ const planPath = join(artifactsDir, "runs", runId, "implement", "dispatch-plan.json");
1022
+ const mergeCommand = loaderCommand(`merge-implement-results --run-id ${runId}`);
1023
+ const nextCommand = loaderCommand("next-step");
1024
+ const implQuotaPath = join(artifactsDir, "runs", runId, "implement", "dispatch-quota.json");
1025
+ if (!canDispatchImpl) {
1026
+ // A host that cannot dispatch parallel subagents runs the eligible nodes
1027
+ // ITSELF, one at a time — but the orchestrator still emits the FULL eligible
1028
+ // frontier (not one node per next-step). The shared rebuild between
1029
+ // dependency levels happens naturally on the next next-step pass: this
1030
+ // level's results are merged, and the next pass emits the now-eligible
1031
+ // downstream level after the host rebuilds the shared surface.
1032
+ return { kind: "emit", step: await writeCurrentStep({
1033
+ stepKind: "implement_rolling_sequential",
1034
+ status: "ready",
1035
+ runId,
1036
+ repoRoot: root,
1037
+ artifactsDir,
1038
+ prompt: `
1039
+ # Implement Eligible Remediation Nodes (sequential)
1040
+
1041
+ Read the dispatch plan:
1042
+
1043
+ \`${planPath}\`
1044
+
1045
+ Every item in \`items\` is a node whose dependencies are all verified-complete, so
1046
+ they are safe to implement now. Work through them ONE AT A TIME, in order: for each
1047
+ item, read and follow only its \`prompt_path\`, then move to the next.
1048
+
1049
+ ${SHARED_REBUILD_BETWEEN_LEVELS_NOTE}
1050
+
1051
+ After all results in this plan exist:
1052
+
1053
+ \`${mergeCommand}\`
1054
+
1055
+ Then run:
1056
+
1057
+ \`${nextCommand}\`
1058
+ `,
1059
+ allowedCommands: [mergeCommand, nextCommand],
1060
+ stopCondition: "Stop after every eligible node's result has been merged and next-step has been run.",
1061
+ artifactPaths: {
1062
+ dispatch_plan: planPath,
1063
+ dispatch_quota: implQuotaPath,
1064
+ },
1065
+ }) };
1066
+ }
1067
+ return { kind: "emit", step: await writeCurrentStep({
1068
+ stepKind: "dispatch_implement",
1069
+ status: "ready",
1070
+ runId,
1071
+ repoRoot: root,
1072
+ artifactsDir,
1073
+ prompt: `
1074
+ # Dispatch Implementation Work (rolling)
1075
+
1076
+ Read the dispatch plan and quota JSONs:
1077
+
1078
+ \`${planPath}\`
1079
+ \`${implQuotaPath}\`
1080
+
1081
+ Every item in \`items\` is a node whose dependencies are all VERIFIED-COMPLETE
1082
+ (INV-RS-01), so all of them are eligible to run now. Concurrency is owned by the
1083
+ quota scheduler — maintain up to \`max_concurrent_agents\` subagents running
1084
+ simultaneously (from the quota file), with no separate wave-size cap. Each item's
1085
+ \`model_hint.tier\` suggests which model to use (small/standard/deep). If your
1086
+ provider has rate limits, pace launches accordingly.
1087
+
1088
+ For each item in \`items\`, dispatch one subagent with that item's
1089
+ \`prompt_path\`. Each subagent may edit source files needed for that bounded
1090
+ block and must write only its assigned \`result_path\`.
1091
+
1092
+ ${SHARED_REBUILD_BETWEEN_LEVELS_NOTE}
1093
+
1094
+ ${DISPATCH_PROMPT_HANDOFF_NOTE}
1095
+
1096
+ After all results exist:
1097
+
1098
+ ${DO_NOT_TOKEN_WRAP_NOTE}
1099
+
1100
+ \`${mergeCommand}\`
1101
+
1102
+ Then run:
1103
+
1104
+ \`${nextCommand}\`
1105
+ `,
1106
+ allowedCommands: [mergeCommand, nextCommand],
1107
+ stopCondition: "Stop after all implementation results have been merged and next-step has been run.",
1108
+ artifactPaths: { dispatch_plan: planPath, dispatch_quota: implQuotaPath },
1109
+ }) };
1110
+ }
1111
+ // --- Per-state handlers -----------------------------------------------------
1112
+ // Each handler owns one branch of the original decideNextStepInner dispatch.
1113
+ // Handlers that emit a step return RemediationStep directly; handlers that need
1114
+ // the loop to continue with mutated state return { continueWithState }.
1115
+ async function handleComplete(root, artifactsDir, state) {
1116
+ return presentReportStep(root, artifactsDir, state);
1117
+ }
1118
+ async function handlePendingExtractedPlan(root, artifactsDir, existing, extractedPlan) {
1119
+ try {
1120
+ const { plan, sourceFindings, mergeMap } = normalizeExtractedPlan(extractedPlan);
1121
+ // Deterministic grounding for the LLM-extracted plan (this path never sees
1122
+ // structured audit findings): strip phantom affected_files paths, drop
1123
+ // findings whose every cited path was phantom, and classify evidence. No
1124
+ // bounded LLM repair here — the host re-extracts with the corrected prompt
1125
+ // if the whole plan grounds to nothing. Contract-pipeline-promoted plans
1126
+ // are grounded by construction (the traceability gate ties every node to
1127
+ // obligations/accepted counterexamples), so their obligation-reference
1128
+ // evidence is exempt from the path-citation check.
1129
+ const grounding = await groundExtractedFindings(plan.findings, {
1130
+ root,
1131
+ evidenceGrounding: plan.source !== "contract_pipeline",
1132
+ });
1133
+ if (grounding.dropped.length > 0) {
1134
+ process.stderr.write(`[remediate-code] Grounding dropped ${grounding.dropped.length} extracted finding(s) whose cited paths do not exist: ${grounding.dropped.map((d) => `${d.finding.id} (${d.phantomPaths.join(", ")})`).join("; ")}\n`);
1135
+ }
1136
+ plan.findings = grounding.findings;
1137
+ const keptIds = new Set(plan.findings.map((f) => f.id));
1138
+ plan.blocks = plan.blocks
1139
+ .map((b) => ({ ...b, items: (b.items ?? []).filter((id) => keptIds.has(id)) }))
1140
+ .filter((b) => (b.items ?? []).length > 0);
1141
+ if (plan.findings.length === 0) {
1142
+ throw new Error("Every extracted finding cited only phantom paths; re-extract with real repo-relative paths.");
1143
+ }
1144
+ const pipelined = await applyPlanPipeline(plan, { root, artifactsDir });
1145
+ const reviewDecision = await readOptionalJsonFile(reviewDecisionPath(artifactsDir));
1146
+ // Coverage ledger. Path A (structured_audit): the single filter pass ran at
1147
+ // intake over the ORIGINAL findings and persisted its dispositions — build
1148
+ // coverage over those originals so every audit finding gets exactly one
1149
+ // disposition (planned / folded_into / dropped_* / dropped_by_checkpoint /
1150
+ // declined_by_review), reconciling to the original count. Path B (no persisted
1151
+ // dispositions): build over the post-pipeline node findings as before. Either
1152
+ // way declined findings are recorded; their payloads recover at close from the
1153
+ // unfiltered intake source.
1154
+ const filterDisp = await readOptionalJsonFile(reviewFilterDispositionsPath(artifactsDir));
1155
+ const coverage = filterDisp
1156
+ ? buildCoverageLedger({
1157
+ planId: pipelined.plan_id,
1158
+ sourceFindings: filterDisp.originals,
1159
+ droppedNoEvidence: filterDisp.droppedNoEvidence,
1160
+ droppedByCheckpoint: filterDisp.droppedByCheckpoint,
1161
+ declinedByReview: reviewDecision?.declined ?? [],
1162
+ droppedPhantomPaths: new Map(filterDisp.droppedPhantomPaths),
1163
+ phantomPathsRemoved: new Map(filterDisp.phantomPathsRemoved),
1164
+ mergeMap: new Map(filterDisp.mergeMap),
1165
+ items: {}, // originals carry no node block_id; planned entries omit it
1166
+ })
1167
+ : buildCoverageLedger({
1168
+ planId: pipelined.plan_id,
1169
+ sourceFindings,
1170
+ droppedNoEvidence: [],
1171
+ droppedByCheckpoint: [],
1172
+ declinedByReview: reviewDecision?.declined ?? [],
1173
+ droppedPhantomPaths: new Map(grounding.dropped.map((d) => [d.finding.id, d.phantomPaths])),
1174
+ phantomPathsRemoved: grounding.phantomPathsByFinding,
1175
+ mergeMap,
1176
+ items: Object.fromEntries(pipelined.findings.map((finding) => [
1177
+ finding.id,
1178
+ {
1179
+ finding_id: finding.id,
1180
+ status: "pending",
1181
+ block_id: pipelined.blocks.find((b) => b.items.includes(finding.id))
1182
+ ?.block_id ?? "UNKNOWN",
1183
+ },
1184
+ ])),
1185
+ });
1186
+ return await saveStateForPlan(artifactsDir, existing, pipelined, coverage);
1187
+ }
1188
+ catch (error) {
1189
+ const paths = intakePaths(artifactsDir);
1190
+ try {
1191
+ const { unlink } = await import("node:fs/promises");
1192
+ await unlink(paths.extractedPlan);
1193
+ }
1194
+ catch { /* already gone */ }
1195
+ process.stderr.write(`[remediate-code] Corrupted extracted-plan.json removed (${error instanceof Error ? error.message : String(error)}). Re-emitting extraction step.\n`);
1196
+ return null;
1197
+ }
1198
+ }
1199
+ // ── Review-approval gate (go-forward program item 1) ───────────────────────────
1200
+ //
1201
+ // Between the audit findings and the contract pipeline, every ORIGINAL finding is
1202
+ // presented to the user bucketed by review-necessity (src/review/reviewGate.ts).
1203
+ // Approved findings seed the pipeline; disapproved findings are excluded from it
1204
+ // AND recorded as a declined disposition (review_decision.json) — never silently
1205
+ // swept to a terminal status inside a quality-tail node, the 2026-06-15 failure
1206
+ // this gate exists to prevent.
1207
+ //
1208
+ // Fires only on Path A (structured_audit) — the only intake path with a
1209
+ // pre-existing finding set; document/conversation runs derive findings inside the
1210
+ // pipeline. File-driven and pre-state (no RemediationState exists at intake yet),
1211
+ // mirroring the intake-clarification gate rather than waiting_for_clarification.
1212
+ const REVIEW_DECISION_SCHEMA_VERSION = "remediate-code-review-decision/v1";
1213
+ /** Stable, informational plan id for the pre-plan review request/decision pair. */
1214
+ const REVIEW_GATE_PLAN_ID = "path-a-review";
1215
+ function reviewRequestPath(artifactsDir) {
1216
+ return join(artifactsDir, "review_request.json");
1217
+ }
1218
+ function reviewResolutionPath(artifactsDir) {
1219
+ return join(artifactsDir, "review_resolution.json");
1220
+ }
1221
+ function reviewDecisionPath(artifactsDir) {
1222
+ return join(artifactsDir, "review_decision.json");
1223
+ }
1224
+ /** Pull the Finding[] out of a parsed audit-findings.json payload. */
1225
+ function extractAuditFindings(parsed) {
1226
+ if (isRecord(parsed) && Array.isArray(parsed.findings)) {
1227
+ return parsed.findings.filter((f) => isRecord(f) && typeof f.id === "string");
1228
+ }
1229
+ return [];
1230
+ }
1231
+ async function handleWaitingForReviewApproval(root, artifactsDir, request) {
1232
+ return writeCurrentStep({
1233
+ stepKind: "collect_review_approval",
1234
+ status: "blocked",
1235
+ runId: randomRunId("REVIEW"),
1236
+ repoRoot: root,
1237
+ artifactsDir,
1238
+ prompt: reviewApprovalPrompt(request, reviewResolutionPath(artifactsDir)),
1239
+ allowedCommands: [loaderCommand("next-step")],
1240
+ stopCondition: "Stop after presenting the findings for approval and collecting the user's approve/disapprove decision, unless the decision is already recorded and the prompt told you to continue.",
1241
+ artifactPaths: {
1242
+ review_request: reviewRequestPath(artifactsDir),
1243
+ review_resolution: reviewResolutionPath(artifactsDir),
1244
+ },
1245
+ });
1246
+ }
1247
+ /**
1248
+ * Run the review-approval gate over the SURVIVOR finding set (already passed
1249
+ * through the single filter pass: deduped, evidence-bearing, path-grounded,
1250
+ * checkpoint-kept). Returns a halt step while awaiting the user's decision, or a
1251
+ * `proceed` splitting the survivors into approved (seed the pipeline) and declined
1252
+ * (recorded, never acted on).
1253
+ *
1254
+ * Idempotent across the many pipeline next-step calls: once review_decision.json
1255
+ * exists the gate consumes it directly and proceeds, so it fires (and halts) at
1256
+ * most once per run. Empty survivors → nothing to review → approve-none/proceed.
1257
+ */
1258
+ async function runReviewApprovalGate(root, artifactsDir, survivors) {
1259
+ const decisionPath = reviewDecisionPath(artifactsDir);
1260
+ // First crossing only: no decision yet AND the pipeline has not started.
1261
+ const gateOpen = survivors.length > 0 &&
1262
+ !existsSync(decisionPath) &&
1263
+ !contractArtifactExists(artifactsDir, "goal_spec");
1264
+ if (gateOpen) {
1265
+ const resolutionPath = reviewResolutionPath(artifactsDir);
1266
+ const requestPath = reviewRequestPath(artifactsDir);
1267
+ if (!existsSync(resolutionPath)) {
1268
+ // Halt: present the tiered survivors and wait for the user's decision.
1269
+ const request = buildReviewRequest(survivors, REVIEW_GATE_PLAN_ID);
1270
+ await writeJsonFile(requestPath, request);
1271
+ return {
1272
+ kind: "halt",
1273
+ step: await handleWaitingForReviewApproval(root, artifactsDir, request),
1274
+ };
1275
+ }
1276
+ // Consume the resolution into a durable, reasoned decision record.
1277
+ const request = (await readOptionalJsonFile(requestPath)) ??
1278
+ buildReviewRequest(survivors, REVIEW_GATE_PLAN_ID);
1279
+ const resolution = await readOptionalJsonFile(resolutionPath);
1280
+ const decision = applyReviewResolution(request, resolution);
1281
+ const record = {
1282
+ schema_version: REVIEW_DECISION_SCHEMA_VERSION,
1283
+ plan_id: REVIEW_GATE_PLAN_ID,
1284
+ approved_ids: decision.approved_ids,
1285
+ declined: decision.declined,
1286
+ created_at: new Date().toISOString(),
1287
+ };
1288
+ await writeJsonFile(decisionPath, record);
1289
+ // Archive the consumed inputs so the gate cannot re-halt.
1290
+ for (const p of [resolutionPath, requestPath]) {
1291
+ if (existsSync(p)) {
1292
+ await withFsRetry(() => rename(p, `${p}.consumed-${Date.now()}`));
1293
+ }
1294
+ }
1295
+ }
1296
+ // Decision recorded (now or on a prior call): split the survivors.
1297
+ const decision = await readOptionalJsonFile(decisionPath);
1298
+ const declined = decision?.declined ?? [];
1299
+ const declinedIds = new Set(declined.map((d) => d.finding_id));
1300
+ return {
1301
+ kind: "proceed",
1302
+ approved: survivors.filter((f) => !declinedIds.has(f.id)),
1303
+ declined,
1304
+ };
1305
+ }
1306
+ // ── Path-A filter dispositions (persisted for the coverage ledger) ──────────────
1307
+ // The single filter pass runs at intake over the ORIGINAL findings; its
1308
+ // dispositions are persisted here so handlePendingExtractedPlan can build the
1309
+ // coverage ledger over the originals (every audit finding → exactly one
1310
+ // disposition), even though it runs after the pipeline has collapsed the approved
1311
+ // survivors into DAG nodes. Maps are serialized as entry arrays for JSON.
1312
+ const REVIEW_FILTER_DISPOSITIONS_FILENAME = "review_filter_dispositions.json";
1313
+ function reviewFilterDispositionsPath(artifactsDir) {
1314
+ return join(artifactsDir, REVIEW_FILTER_DISPOSITIONS_FILENAME);
1315
+ }
1316
+ async function persistReviewFilterDispositions(artifactsDir, originals, filter) {
1317
+ const payload = {
1318
+ originals,
1319
+ mergeMap: [...filter.mergeMap.entries()],
1320
+ droppedNoEvidence: filter.droppedNoEvidence,
1321
+ droppedPhantomPaths: [...filter.droppedPhantomPaths.entries()],
1322
+ phantomPathsRemoved: [...filter.phantomPathsRemoved.entries()],
1323
+ droppedByCheckpoint: filter.droppedByCheckpoint,
1324
+ };
1325
+ await writeJsonFile(reviewFilterDispositionsPath(artifactsDir), payload);
1326
+ }
1327
+ async function handleReadyIntakeContractPipeline(root, artifactsDir) {
1328
+ // Fast path: if an extracted-plan.json already exists (pipeline complete or
1329
+ // promoted from a previous contract pipeline run), consume it directly without
1330
+ // requiring intake artifacts. This handles both "plan promoted, ready to
1331
+ // ground+plan" and the grounding tests that write extracted-plan.json directly.
1332
+ const earlyExtractedPlan = await readExtractedPlanIfPresent(artifactsDir);
1333
+ if (earlyExtractedPlan) {
1334
+ return handlePendingExtractedPlan(root, artifactsDir, { status: "pending" }, earlyExtractedPlan);
1335
+ }
1336
+ const intake = await readIntakeArtifacts(artifactsDir);
1337
+ if (!intake.summary || !isIntakeReady(intake.summary)) {
1338
+ return null;
1339
+ }
1340
+ const pipeline = shouldEnterContractPipeline(artifactsDir, intake.summary.source_type);
1341
+ if (!pipeline.shouldHandleContractPipeline) {
1342
+ return null;
1343
+ }
1344
+ // Path A: run the single filter pass over the ORIGINAL findings, present the
1345
+ // SURVIVORS at the review gate (deduped / evidence-bearing / path-grounded /
1346
+ // checkpoint-kept, tiered by review-necessity), then seed the pipeline with the
1347
+ // approved survivors. The filter dispositions are persisted so the coverage
1348
+ // ledger is built over the originals (every audit finding → exactly one
1349
+ // disposition). The gate may halt to collect the user's decision.
1350
+ let reviewSourceSwap;
1351
+ if (intake.summary.source_type === "structured_audit" && intake.manifest) {
1352
+ const auditSource = resolveManifestSources(root, intake.manifest).resolved.find((s) => s.type === "structured_audit");
1353
+ if (auditSource) {
1354
+ let auditFindings;
1355
+ try {
1356
+ auditFindings = JSON.parse(await readFile(auditSource.path, "utf8"));
1357
+ }
1358
+ catch {
1359
+ auditFindings = undefined;
1360
+ }
1361
+ const originals = extractAuditFindings(auditFindings);
1362
+ if (originals.length > 0) {
1363
+ const checkpoint = await readOptionalJsonFile(join(artifactsDir, "intent_checkpoint.json"));
1364
+ const filter = await runFindingFilterPass(originals, {
1365
+ root,
1366
+ checkpoint: checkpoint ?? undefined,
1367
+ evidenceGrounding: true,
1368
+ });
1369
+ const gate = await runReviewApprovalGate(root, artifactsDir, filter.survivors);
1370
+ if (gate.kind === "halt") {
1371
+ return gate.step;
1372
+ }
1373
+ // Persist the filter dispositions so coverage is built over the originals.
1374
+ await persistReviewFilterDispositions(artifactsDir, originals, filter);
1375
+ // A1 — conservative lean fast path. When the approved set is a handful
1376
+ // of grounded, high-confidence, localized, non-cross-cutting findings,
1377
+ // skip the contract pipeline and synthesize the extracted plan directly;
1378
+ // the plan→implement→close machinery (per-node verify-before-merge + the
1379
+ // final whole-repo gate) is the retained safety net. Any doubt routes to
1380
+ // the full pipeline below. Runs only here — on Path A (structured_audit),
1381
+ // the only intake with a pre-existing finding set to judge.
1382
+ const fast = evaluateFastPath(gate.approved);
1383
+ if (fast.eligible) {
1384
+ const leanPlan = buildLeanExtractedPlan(gate.approved, randomRunId("LEAN"));
1385
+ await writeJsonFile(intakePaths(artifactsDir).extractedPlan, leanPlan);
1386
+ process.stderr.write(`[remediate-code] Lean fast path: ${fast.reason}. Skipping the contract pipeline; routing straight to plan→implement.\n`);
1387
+ const planned = await handlePendingExtractedPlan(root, artifactsDir, { status: "pending" }, leanPlan);
1388
+ if (planned) {
1389
+ return planned;
1390
+ }
1391
+ // Defensive: a deterministically-built lean plan should always
1392
+ // normalize. If it somehow didn't, handlePendingExtractedPlan removed
1393
+ // the file; fall through to the full pipeline (the safety net) rather
1394
+ // than stalling the run.
1395
+ process.stderr.write("[remediate-code] Lean fast-path plan failed to materialize; falling back to the contract pipeline.\n");
1396
+ }
1397
+ // Seed the pipeline with the approved survivors only. When that set is
1398
+ // narrower than the originals (anything filtered or declined), route the
1399
+ // seed AND the pipeline's source inputs at a filtered file so a removed
1400
+ // finding can never re-enter via the raw audit-findings.json (tool-enforced).
1401
+ const approvedPayload = isRecord(auditFindings)
1402
+ ? { ...auditFindings, findings: gate.approved }
1403
+ : { findings: gate.approved };
1404
+ let seedSourcePath = auditSource.path;
1405
+ if (gate.approved.length < originals.length) {
1406
+ await mkdir(contractPipelineDir(artifactsDir), { recursive: true });
1407
+ seedSourcePath = join(contractPipelineDir(artifactsDir), "approved-findings.json");
1408
+ await writeJsonFile(seedSourcePath, approvedPayload);
1409
+ reviewSourceSwap = { from: auditSource.path, to: seedSourcePath };
1410
+ }
1411
+ try {
1412
+ await writePathASeedFromFindings(artifactsDir, seedSourcePath, approvedPayload);
1413
+ }
1414
+ catch {
1415
+ // If the seed cannot be written, the pipeline still runs; the LLM
1416
+ // phases use the source files from sourcePaths.
1417
+ }
1418
+ }
1419
+ }
1420
+ }
1421
+ const paths = intakePaths(artifactsDir);
1422
+ const sourcePaths = new Set();
1423
+ if (existsSync(paths.brief)) {
1424
+ sourcePaths.add(paths.brief);
1425
+ }
1426
+ if (intake.manifest) {
1427
+ for (const source of resolveManifestSources(root, intake.manifest).resolved) {
1428
+ // Swap the raw audit-findings.json for the approved-only filtered file so a
1429
+ // declined finding can never re-enter the pipeline as a source input.
1430
+ sourcePaths.add(reviewSourceSwap && source.path === reviewSourceSwap.from
1431
+ ? reviewSourceSwap.to
1432
+ : source.path);
1433
+ }
1434
+ }
1435
+ const step = await buildNextContractPipelineStep({
1436
+ root,
1437
+ artifactsDir,
1438
+ runId: randomRunId("CONTRACT"),
1439
+ sourcePaths: [...sourcePaths],
1440
+ });
1441
+ if (step) {
1442
+ return step;
1443
+ }
1444
+ const extractedPlan = await readExtractedPlanIfPresent(artifactsDir);
1445
+ if (!extractedPlan) {
1446
+ return null;
1447
+ }
1448
+ return handlePendingExtractedPlan(root, artifactsDir, { status: "pending" }, extractedPlan);
1449
+ }
1450
+ async function handlePendingIntake(root, artifactsDir, options) {
1451
+ // Short-circuit: if an extracted-plan.json already exists (promoted from the
1452
+ // contract pipeline), consume it directly without requiring intake artifacts.
1453
+ // This allows decideNextStep to resume a plan-grounding pass even when the
1454
+ // full intake artifact set is no longer present.
1455
+ const earlyExtractedPlan = await readExtractedPlanIfPresent(artifactsDir);
1456
+ if (earlyExtractedPlan) {
1457
+ return handleReadyIntakeContractPipeline(root, artifactsDir);
1458
+ }
1459
+ const inputResolution = resolveInputPaths(root, options.input);
1460
+ const intakeResult = await resolveIntakeStep({
1461
+ root,
1462
+ artifactsDir,
1463
+ input: options.input,
1464
+ inputResolution,
1465
+ loaderCommand,
1466
+ randomRunId,
1467
+ collectStartingPointPrompt,
1468
+ synthesizeIntakePrompt,
1469
+ collectIntakeClarificationsPrompt,
1470
+ });
1471
+ if (intakeResult.kind === "step") {
1472
+ return intakeResult.step;
1473
+ }
1474
+ // Intake is complete — route both paths through the contract pipeline.
1475
+ return handleReadyIntakeContractPipeline(root, artifactsDir);
1476
+ }
1477
+ async function handleNoState(root, artifactsDir) {
1478
+ const paths = intakePaths(artifactsDir);
1479
+ return writeCurrentStep({
1480
+ stepKind: "collect_starting_point",
1481
+ status: "blocked",
1482
+ runId: randomRunId("INPUT"),
1483
+ repoRoot: root,
1484
+ artifactsDir,
1485
+ prompt: collectStartingPointPrompt(root, defaultInputCandidates(root), [], paths),
1486
+ allowedCommands: [loaderCommand("next-step"), loaderCommand("next-step --input <path>")],
1487
+ stopCondition: "Stop after collecting a remediation starting point and rerunning next-step.",
1488
+ artifactPaths: {
1489
+ source_manifest: paths.sourceManifest,
1490
+ conversation_start: paths.conversationStart,
1491
+ },
1492
+ });
1493
+ }
1494
+ async function handleInputConflict(root, artifactsDir, state, inputResolution) {
1495
+ const planId = state.plan?.plan_id ?? "(none)";
1496
+ const itemCount = state.items ? Object.keys(state.items).length : 0;
1497
+ const suppliedInline = inputResolution.checked.length > 0
1498
+ ? inputResolution.checked.map((p) => `\`${p}\``).join(", ")
1499
+ : "(input supplied)";
1500
+ return writeCurrentStep({
1501
+ stepKind: "input_conflict",
1502
+ status: "blocked",
1503
+ runId: stateRunId(state),
1504
+ repoRoot: root,
1505
+ artifactsDir,
1506
+ prompt: `
1507
+ # New \`--input\` given, but a remediation run is already in progress
1508
+
1509
+ A remediation run already exists in \`${artifactsDir}\` and has advanced past intake,
1510
+ so the new \`--input\` you passed will **not** replace it — it would be ignored and the
1511
+ existing plan resumed.
1512
+
1513
+ - **Current state**: \`${state.status}\`
1514
+ - **Plan**: \`${planId}\` (${itemCount} item(s))
1515
+ - **Supplied input**: ${suppliedInline}
1516
+
1517
+ Choose one explicitly and report the choice to the user:
1518
+
1519
+ 1. **Resume the existing run** — re-run WITHOUT \`--input\`: \`${loaderCommand("next-step")}\`
1520
+ 2. **Start fresh from the new input** — first move aside or delete the existing
1521
+ \`${artifactsDir}\` directory (and the stale \`remediation-report.md\` /
1522
+ \`remediation-report.json\` in \`.audit-tools/\`, which would otherwise be overwritten on completion),
1523
+ then re-run \`${loaderCommand("next-step --input <path>")}\`.
1524
+
1525
+ Stop after presenting this choice. Do not advance the run until the user decides.
1526
+ `,
1527
+ allowedCommands: [
1528
+ loaderCommand("next-step"),
1529
+ loaderCommand("next-step --input <path>"),
1530
+ ],
1531
+ stopCondition: "Stop after presenting the resume-vs-restart choice to the user.",
1532
+ artifactPaths: {
1533
+ state_file: join(artifactsDir, "state.json"),
1534
+ },
1535
+ });
1536
+ }
1537
+ function normalizePlanClarificationResolutions(value) {
1538
+ if (Array.isArray(value)) {
1539
+ return value.filter(isRecord).flatMap((entry) => {
1540
+ if (typeof entry.finding_id === "string" &&
1541
+ (entry.action === "clarified" || entry.action === "deemed_inappropriate")) {
1542
+ return [
1543
+ {
1544
+ finding_id: entry.finding_id,
1545
+ action: entry.action,
1546
+ rationale: typeof entry.rationale === "string" ? entry.rationale : undefined,
1547
+ },
1548
+ ];
1549
+ }
1550
+ return [];
1551
+ });
1552
+ }
1553
+ if (!isRecord(value))
1554
+ return [];
1555
+ if (Array.isArray(value.resolutions)) {
1556
+ return normalizePlanClarificationResolutions(value.resolutions);
1557
+ }
1558
+ if (Array.isArray(value.items)) {
1559
+ return normalizePlanClarificationResolutions(value.items);
1560
+ }
1561
+ return Object.entries(value).flatMap(([findingId, entry]) => {
1562
+ if (!isRecord(entry))
1563
+ return [];
1564
+ if (entry.action !== "clarified" && entry.action !== "deemed_inappropriate")
1565
+ return [];
1566
+ return [{
1567
+ finding_id: typeof entry.finding_id === "string" ? entry.finding_id : findingId,
1568
+ action: entry.action,
1569
+ rationale: typeof entry.rationale === "string" ? entry.rationale : undefined,
1570
+ }];
1571
+ });
1572
+ }
1573
+ /**
1574
+ * Consume clarification_resolution.json for plan-phase clarifications.
1575
+ * Mirrors the triage resolution consume: deemed_inappropriate → terminal,
1576
+ * clarified → re-open (pending) for implement dispatch. Archives the file.
1577
+ */
1578
+ async function applyPlanClarificationResolution(artifactsDir, state, store) {
1579
+ if (!state.plan || !state.items)
1580
+ return state;
1581
+ const resolutionPath = join(artifactsDir, "clarification_resolution.json");
1582
+ const resolutions = normalizePlanClarificationResolutions(await readOptionalJsonFile(resolutionPath));
1583
+ const now = new Date().toISOString();
1584
+ for (const res of resolutions) {
1585
+ const item = state.items[res.finding_id];
1586
+ if (!item)
1587
+ continue;
1588
+ if (res.action === "deemed_inappropriate") {
1589
+ item.status = "deemed_inappropriate";
1590
+ item.failure_reason = res.rationale;
1591
+ item.started_at ??= now;
1592
+ item.completed_at = now;
1593
+ }
1594
+ else {
1595
+ item.status = "pending";
1596
+ item.clarification_context = res.rationale;
1597
+ }
1598
+ }
1599
+ if (existsSync(resolutionPath)) {
1600
+ await withFsRetry(() => rename(resolutionPath, `${resolutionPath}.consumed-${Date.now()}`));
1601
+ }
1602
+ const remainingPending = state.plan.findings.some((f) => state.items?.[f.id]?.status === "pending");
1603
+ state.status = remainingPending ? "implementing" : "closing";
1604
+ state.clarifications = [];
1605
+ state.closing_plan ??= { action: "none" };
1606
+ await store.saveState(state);
1607
+ return state;
1608
+ }
1609
+ async function handleWaitingForClarification(root, artifactsDir, state) {
1610
+ const clarifications = state.clarifications ??
1611
+ (await readOptionalJsonFile(join(artifactsDir, "clarification_request.json"))) ??
1612
+ [];
1613
+ const resolutionPath = join(artifactsDir, "clarification_resolution.json");
1614
+ return writeCurrentStep({
1615
+ stepKind: "collect_clarifications",
1616
+ status: "blocked",
1617
+ runId: stateRunId(state),
1618
+ repoRoot: root,
1619
+ artifactsDir,
1620
+ prompt: clarificationPrompt(clarifications, resolutionPath),
1621
+ allowedCommands: [loaderCommand("next-step")],
1622
+ stopCondition: "Stop after asking the user for clarification answers, unless the answers are already available and the prompt told you to continue.",
1623
+ artifactPaths: {
1624
+ clarification_request: join(artifactsDir, "clarification_request.json"),
1625
+ clarification_resolution: resolutionPath,
1626
+ },
1627
+ });
1628
+ }
1629
+ async function handleWaitingForTriage(root, artifactsDir, state) {
1630
+ const resolutionPath = join(artifactsDir, "triage_resolution.json");
1631
+ return writeCurrentStep({
1632
+ stepKind: "collect_triage",
1633
+ status: "blocked",
1634
+ runId: stateRunId(state),
1635
+ repoRoot: root,
1636
+ artifactsDir,
1637
+ prompt: triagePrompt(state, resolutionPath),
1638
+ allowedCommands: [loaderCommand("next-step")],
1639
+ stopCondition: "Stop after asking the user for triage decisions, unless the decisions are already available and the prompt told you to continue.",
1640
+ artifactPaths: {
1641
+ triage_batch: join(artifactsDir, "triage_batch.json"),
1642
+ triage_resolution: resolutionPath,
1643
+ },
1644
+ });
1645
+ }
1646
+ /** Stable, informational plan id for the Path-B (planning-point) review pair. */
1647
+ const REVIEW_GATE_PLAN_ID_PATH_B = "path-b-review";
1648
+ /**
1649
+ * Path-B (document / conversation) review-necessity gate, fired at the PLANNING
1650
+ * point over the deduped/grounded node findings. Path A records its review
1651
+ * decision at intake over the ORIGINAL findings — before the contract pipeline
1652
+ * collapses them into DAG nodes (`runReviewApprovalGate`). Path B has no
1653
+ * pre-pipeline finding set (its findings are DERIVED inside the pipeline), so it
1654
+ * is gated here instead. The decision is applied to the existing plan state:
1655
+ * declined nodes become a RECORDED terminal disposition (`ignored`) rather than
1656
+ * being silently bulk-dispositioned inside a quality-tail node — the 2026-06-15
1657
+ * failure this gate exists to prevent.
1658
+ *
1659
+ * The caller fires this only when `review_decision.json` is ABSENT, so Path A
1660
+ * (decision already written at intake) never reaches it — no double review.
1661
+ * Returns a halt step while awaiting the user's decision, or null to proceed
1662
+ * (decision recorded, any declined nodes marked terminal).
1663
+ */
1664
+ async function runPlanningReviewGate(root, artifactsDir, state, store) {
1665
+ const findings = state.plan?.findings ?? [];
1666
+ if (findings.length === 0)
1667
+ return null;
1668
+ const requestPath = reviewRequestPath(artifactsDir);
1669
+ const resolutionPath = reviewResolutionPath(artifactsDir);
1670
+ const decisionPath = reviewDecisionPath(artifactsDir);
1671
+ if (!existsSync(resolutionPath)) {
1672
+ // Halt: present the tiered node findings and wait for the user's decision.
1673
+ const request = buildReviewRequest(findings, REVIEW_GATE_PLAN_ID_PATH_B);
1674
+ await writeJsonFile(requestPath, request);
1675
+ return handleWaitingForReviewApproval(root, artifactsDir, request);
1676
+ }
1677
+ // Resolution present: consume it into a durable, reasoned decision record.
1678
+ const request = (await readOptionalJsonFile(requestPath)) ??
1679
+ buildReviewRequest(findings, REVIEW_GATE_PLAN_ID_PATH_B);
1680
+ const resolution = await readOptionalJsonFile(resolutionPath);
1681
+ const decision = applyReviewResolution(request, resolution);
1682
+ const record = {
1683
+ schema_version: REVIEW_DECISION_SCHEMA_VERSION,
1684
+ plan_id: REVIEW_GATE_PLAN_ID_PATH_B,
1685
+ approved_ids: decision.approved_ids,
1686
+ declined: decision.declined,
1687
+ created_at: new Date().toISOString(),
1688
+ };
1689
+ await writeJsonFile(decisionPath, record);
1690
+ // Archive the consumed inputs so the gate cannot re-halt.
1691
+ for (const p of [resolutionPath, requestPath]) {
1692
+ if (existsSync(p)) {
1693
+ await withFsRetry(() => rename(p, `${p}.consumed-${Date.now()}`));
1694
+ }
1695
+ }
1696
+ // Declined nodes → recorded terminal disposition (never a silent close).
1697
+ let changed = false;
1698
+ for (const { finding_id, reason } of decision.declined) {
1699
+ const it = state.items?.[finding_id];
1700
+ if (it && !isTerminalStatus(it.status)) {
1701
+ const now = new Date().toISOString();
1702
+ it.status = "ignored";
1703
+ it.failure_reason = reason;
1704
+ it.started_at ??= now;
1705
+ it.completed_at = now;
1706
+ changed = true;
1707
+ }
1708
+ }
1709
+ if (changed)
1710
+ await store.saveState(state);
1711
+ return null;
1712
+ }
1713
+ async function handlePlanning(root, artifactsDir, state, store) {
1714
+ // Review-necessity gate (Path B). Path A records its review decision at intake,
1715
+ // over the ORIGINAL findings, before the contract pipeline collapses them into
1716
+ // DAG nodes; Path B (document / conversation) derives findings INSIDE the
1717
+ // pipeline, so it is gated here, at the planning point, over the deduped/
1718
+ // grounded node findings. Fires only when no decision exists yet, so Path A
1719
+ // (decision already written) never double-reviews. Declined nodes get a
1720
+ // recorded terminal disposition.
1721
+ if (state.plan && !existsSync(reviewDecisionPath(artifactsDir))) {
1722
+ const halt = await runPlanningReviewGate(root, artifactsDir, state, store);
1723
+ if (halt)
1724
+ return { kind: "emit", step: halt };
1725
+ }
1726
+ // Document phase dissolved: planning transitions directly to implementing.
1727
+ // The rolling implement dispatch reads item_spec from the plan DAG node when
1728
+ // present, or uses finding context directly when absent.
1729
+ const implementBlocks = implementableBlocks(state);
1730
+ if (implementBlocks.length > 0) {
1731
+ if (state.plan) {
1732
+ const integrity = await checkAffectedFileIntegrity(root, state.plan.findings);
1733
+ if (!integrity.is_clean) {
1734
+ const details = [
1735
+ ...integrity.changed.map((p) => `changed: ${p}`),
1736
+ ...integrity.missing.map((p) => `missing: ${p}`),
1737
+ ...integrity.io_errors.map((p) => `io-error: ${p}`),
1738
+ ];
1739
+ const replanCommand = loaderCommand("next-step --force-replan");
1740
+ return { kind: "emit", step: await writeCurrentStep({
1741
+ stepKind: "collect_starting_point",
1742
+ status: "blocked",
1743
+ runId: stateRunId(state),
1744
+ repoRoot: root,
1745
+ artifactsDir,
1746
+ prompt: [
1747
+ "## File integrity check failed",
1748
+ "",
1749
+ "The following files have changed since the remediation plan was created:",
1750
+ ...details.map((d) => `- ${d}`),
1751
+ "",
1752
+ "Re-run planning to pick up the current file state before implementation begins.",
1753
+ "Run:",
1754
+ "",
1755
+ `\`${replanCommand}\``,
1756
+ ].join("\n"),
1757
+ allowedCommands: [replanCommand],
1758
+ stopCondition: "Stop after re-planning completes.",
1759
+ }) };
1760
+ }
1761
+ }
1762
+ }
1763
+ // Transition directly to implementing — no separate document round.
1764
+ // Any pending item whose node is NOT eligible for any rolling dispatch pass is
1765
+ // dead-ended (INV-RS-01): a prerequisite was skipped/blocked, so its
1766
+ // verified-complete edge can never be satisfied — never dispatch a dependent
1767
+ // against an upstream surface that did not land. Mark it blocked so the run
1768
+ // advances to close rather than looping forever. A node that is merely
1769
+ // waiting on a still-running prerequisite is NOT here (it would appear in a
1770
+ // later eligible pass); only nodes with a permanently-unsatisfiable edge are.
1771
+ if (implementBlocks.length === 0) {
1772
+ for (const block of blockedByUnsatisfiedDependency(state)) {
1773
+ for (const findingId of block.items) {
1774
+ const it = state.items?.[findingId];
1775
+ if (!it || it.status !== "pending")
1776
+ continue;
1777
+ it.status = "blocked";
1778
+ it.failure_reason =
1779
+ it.failure_reason ??
1780
+ "A dependency node did not reach a verified-complete disposition " +
1781
+ "(a prerequisite was skipped, blocked, or the dependencies are cyclic); " +
1782
+ "the rolling scheduler will not dispatch this node against an upstream " +
1783
+ "surface that never landed (INV-RS-01).";
1784
+ }
1785
+ }
1786
+ }
1787
+ state.status = "implementing";
1788
+ await store.saveState(state);
1789
+ return { kind: "transition", state };
1790
+ }
1791
+ async function handleImplementing(root, artifactsDir, state, runLogger, store) {
1792
+ const triageStart = Date.now();
1793
+ runLogger.event({ phase: "next-step", kind: "executor_start", obligation: state.status, note: "triage" });
1794
+ const triaged = await runTriagePhase(state, { root, artifactsDir });
1795
+ runLogger.event({ phase: "next-step", kind: "executor_end", obligation: state.status, note: "triage", duration_ms: Date.now() - triageStart });
1796
+ await store.saveState(triaged);
1797
+ return { kind: "transition", state: triaged };
1798
+ }
1799
+ function hasResolvedItems(state) {
1800
+ return Object.values(state.items ?? {}).some((it) => isVerifiedCompleteStatus(it.status));
1801
+ }
1802
+ async function handleAllTerminalTransition(root, artifactsDir, state, store, options, runLogger) {
1803
+ const gateDisabled = options.skipFinalGate === true ||
1804
+ process.env.REMEDIATE_SKIP_FINAL_GATE === "1" ||
1805
+ process.env.REMEDIATE_SKIP_FINAL_GATE === "true";
1806
+ const sidecar = await readFinalGateSidecar(artifactsDir);
1807
+ // The tool-owned final gate (INV-RS-10) runs at the single all-terminal →
1808
+ // closing funnel, exactly once per arrival here. It is skipped when:
1809
+ // - there is nothing resolved to validate (everything blocked/skipped), or
1810
+ // - the bounded backstop already terminated (CE-003 — never re-run after), or
1811
+ // - it is explicitly disabled for test hermeticity.
1812
+ // The gate is INDEPENDENT of plan.test_command and runs through the
1813
+ // env-scrubbing runTracked path.
1814
+ if (!gateDisabled && !sidecar.terminated && hasResolvedItems(state)) {
1815
+ const gateStart = Date.now();
1816
+ runLogger.event({
1817
+ phase: "next-step",
1818
+ kind: "executor_start",
1819
+ obligation: state.status,
1820
+ note: "tool_owned_final_gate",
1821
+ });
1822
+ const gate = await runToolOwnedFinalGate(root, { runner: options.finalGateRunner });
1823
+ runLogger.event({
1824
+ phase: "next-step",
1825
+ kind: "executor_end",
1826
+ obligation: state.status,
1827
+ note: `tool_owned_final_gate passed=${gate.passed}`,
1828
+ duration_ms: Date.now() - gateStart,
1829
+ });
1830
+ if (!gate.passed) {
1831
+ // INV-RS-09: a whole-repo gate red is unattributable → coarse re-block.
1832
+ // CE-003: bounded, monotonic auto-terminate to terminal `blocked`.
1833
+ const failedCmd = gate.results.find((r) => !r.passed);
1834
+ const summary = failedCmd
1835
+ ? `Failing command: ${failedCmd.argv.join(" ")} (exit ${failedCmd.exit_code}).`
1836
+ : "Tool-owned final gate failed.";
1837
+ const decision = applyCoarseReblock(state, sidecar.count, summary);
1838
+ await writeFinalGateSidecar(artifactsDir, decision.next_count, decision.action === "terminal_blocked");
1839
+ runLogger.event({
1840
+ phase: "next-step",
1841
+ kind: "outcome",
1842
+ obligation: state.status,
1843
+ note: `coarse_reblock action=${decision.action} count=${decision.next_count}`,
1844
+ });
1845
+ // reattempt_all → re-open items to pending and re-run the rolling scheduler
1846
+ // (NEVER the human triage prompt — CE-003 no-human-host path); terminal_blocked
1847
+ // → everything non-skip is now blocked, so close writes the partial report.
1848
+ decision.state.status =
1849
+ decision.action === "reattempt_all" ? "implementing" : "closing";
1850
+ await store.saveState(decision.state);
1851
+ return { kind: "transition", state: decision.state };
1852
+ }
1853
+ }
1854
+ state.status = "closing";
1855
+ await store.saveState(state);
1856
+ return { kind: "transition", state };
1857
+ }
1858
+ async function handleClosing(root, artifactsDir, state, runLogger, store) {
1859
+ const closeStart = Date.now();
1860
+ runLogger.event({ phase: "next-step", kind: "executor_start", obligation: state.status, note: "close" });
1861
+ const closed = await runClosePhase(state, { root, artifactsDir }, runLogger);
1862
+ runLogger.event({ phase: "next-step", kind: "executor_end", obligation: state.status, note: "close", duration_ms: Date.now() - closeStart });
1863
+ if (closed.status !== "complete") {
1864
+ // Not done (preview / re-blocked to triage): persist and re-scan.
1865
+ await store.saveState(closed);
1866
+ return { kind: "transition", state: closed };
1867
+ }
1868
+ // Close-complete CROSSES the engine boundary: `complete` is a pre-intake
1869
+ // obligation, unreachable from a main-engine transition. Emit the durable
1870
+ // report directly, passing exactly what the original recursion reloaded — the
1871
+ // artifact dir is DELETED on a fully-green close (reload → null → randomRunId)
1872
+ // and PRESERVED on a not-green complete (reload → the saved complete state →
1873
+ // its plan_id). `store.loadState()` reproduces both, so present_report is
1874
+ // identical to the cascade. (Regression-locked in next-step-implement-dispatch.)
1875
+ return {
1876
+ kind: "emit",
1877
+ step: await handleComplete(root, artifactsDir, await store.loadState()),
1878
+ };
1879
+ }
1880
+ async function handleZeroDocumentableFindings(root, artifactsDir, state) {
1881
+ const nextStepCommand = loaderCommand("next-step");
1882
+ const nextStepInputCommand = loaderCommand("next-step --input <path>");
1883
+ const checkpointPath = join(artifactsDir, "intent_checkpoint.json");
1884
+ return writeCurrentStep({
1885
+ stepKind: "zero_documentable_findings",
1886
+ status: "blocked",
1887
+ runId: stateRunId(state),
1888
+ repoRoot: root,
1889
+ artifactsDir,
1890
+ prompt: `
1891
+ # No Documentable Findings
1892
+
1893
+ The remediation plan is in the \`planning\` state but there are no findings with
1894
+ status \`pending\` — every finding has already been documented, ignored, or
1895
+ deemed inappropriate.
1896
+
1897
+ Choose one of the following options:
1898
+
1899
+ 1. **Adjust or remove the intent checkpoint** — edit or delete
1900
+ \`${checkpointPath}\`, then re-run:
1901
+
1902
+ \`${nextStepCommand}\`
1903
+
1904
+ 2. **Supply a different input file** — provide a new audit report or feedback
1905
+ file as the remediation source, then re-run with:
1906
+
1907
+ \`${nextStepInputCommand}\`
1908
+
1909
+ 3. **Stop** — no further remediation work is needed. You may stop now.
1910
+
1911
+ Report this situation to the user and let them choose.
1912
+ `,
1913
+ allowedCommands: [nextStepCommand, nextStepInputCommand],
1914
+ stopCondition: "Stop after presenting the three choices to the user and waiting for their decision.",
1915
+ });
1916
+ }
1917
+ async function handleUnhandledState(root, artifactsDir, state) {
1918
+ const itemsByStatus = {};
1919
+ for (const item of Object.values(state.items ?? {})) {
1920
+ (itemsByStatus[item.status] ??= []).push(item.finding_id);
1921
+ }
1922
+ const statusBreakdown = Object.entries(itemsByStatus)
1923
+ .map(([status, ids]) => `- **${status}**: ${ids.join(", ")}`)
1924
+ .join("\n");
1925
+ return writeCurrentStep({
1926
+ stepKind: "unhandled_state",
1927
+ status: "blocked",
1928
+ runId: stateRunId(state),
1929
+ repoRoot: root,
1930
+ artifactsDir,
1931
+ prompt: `
1932
+ # Unhandled State
1933
+
1934
+ The remediation workflow reached a state it has no transition for.
1935
+
1936
+ - **State status**: \`${state.status}\`
1937
+ - **State file**: \`${join(artifactsDir, "state.json")}\`
1938
+
1939
+ ## Item Breakdown
1940
+
1941
+ ${statusBreakdown || "No items in state."}
1942
+
1943
+ Report this diagnostic to the user and stop. Do not attempt to advance the run.
1944
+ `,
1945
+ allowedCommands: [],
1946
+ stopCondition: "Stop after reporting the diagnostic to the user.",
1947
+ });
1948
+ }
1949
+ export async function decideNextStep(options = {}) {
1950
+ const normalizedOptions = coerceJsonObjectArg(options, "decideNextStep options");
1951
+ const root = resolveRoot(normalizedOptions.root);
1952
+ const artifactsDir = resolveArtifactsDir(root, normalizedOptions.artifactsDir);
1953
+ const sessionConfig = normalizedOptions.sessionConfig ??
1954
+ (await readOptionalJsonFile(join(root, "session-config.json")));
1955
+ const runLogger = new RunLogger(join(artifactsDir, "run.log.jsonl"), {
1956
+ enabled: sessionConfig?.observability?.run_log ?? true,
1957
+ });
1958
+ const startedAt = Date.now();
1959
+ try {
1960
+ const step = await decideNextStepLoop(normalizedOptions, runLogger);
1961
+ runLogger.event({
1962
+ phase: "next-step",
1963
+ kind: "step",
1964
+ obligation: step.step_kind,
1965
+ note: step.status,
1966
+ duration_ms: Date.now() - startedAt,
1967
+ });
1968
+ return step;
1969
+ }
1970
+ catch (error) {
1971
+ runLogger.event({
1972
+ phase: "next-step",
1973
+ kind: "error",
1974
+ duration_ms: Date.now() - startedAt,
1975
+ note: error instanceof Error ? error.message : String(error),
1976
+ });
1977
+ throw error;
1978
+ }
1979
+ }
1980
+ async function buildConfirmResumeOrRestartStep(ctx) {
1981
+ const { root, artifactsDir, state, ackPath } = ctx;
1982
+ const runId = stateRunId(state);
1983
+ const nextCommand = loaderCommand("next-step");
1984
+ const itemsByStatus = {};
1985
+ for (const item of Object.values(state.items ?? {})) {
1986
+ itemsByStatus[item.status] = (itemsByStatus[item.status] ?? 0) + 1;
1987
+ }
1988
+ const statusLines = Object.entries(itemsByStatus)
1989
+ .map(([status, count]) => `- **${status}**: ${count}`)
1990
+ .join("\n");
1991
+ return writeCurrentStep({
1992
+ stepKind: "confirm_resume_or_restart",
1993
+ status: "blocked",
1994
+ runId,
1995
+ repoRoot: root,
1996
+ artifactsDir,
1997
+ prompt: [
1998
+ "# Remediation Run Already In Progress",
1999
+ "",
2000
+ "A remediation run is already in progress. Choose what to do:",
2001
+ "",
2002
+ `- **Current state**: \`${state.status}\``,
2003
+ `- **Plan**: \`${state.plan?.plan_id ?? "(none)"}\``,
2004
+ `- **Started**: ${state.started_at ?? "(unknown)"}`,
2005
+ "",
2006
+ "## Item Counts",
2007
+ "",
2008
+ statusLines || "No items in state.",
2009
+ "",
2010
+ "## Choices",
2011
+ "",
2012
+ "1. **Resume** — continue the existing run. Write to the ack file:",
2013
+ " ```json",
2014
+ ' { "choice": "resume" }',
2015
+ " ```",
2016
+ " Then re-run without `--input`:",
2017
+ ` \`${nextCommand}\``,
2018
+ "",
2019
+ "2. **Restart from new input** — delete the existing run and start fresh.",
2020
+ " Write to the ack file:",
2021
+ " ```json",
2022
+ ' { "choice": "restart" }',
2023
+ " ```",
2024
+ ` Then delete \`${artifactsDir}\` and re-run with \`--input <path>\`.`,
2025
+ "",
2026
+ "3. **Merge new recommendations into existing plan** — carry the current plan",
2027
+ " forward with additional findings merged in. Write to the ack file:",
2028
+ " ```json",
2029
+ ' { "choice": "merge" }',
2030
+ " ```",
2031
+ ` Then re-run with \`--input <path>\` pointing at your new recommendations.`,
2032
+ "",
2033
+ `Write your choice to: \`${ackPath}\``,
2034
+ ].join("\n"),
2035
+ allowedCommands: [nextCommand, loaderCommand("next-step --input <path>")],
2036
+ stopCondition: "Stop after presenting the resume/restart/merge choice to the user and writing the ack.",
2037
+ artifactPaths: {
2038
+ state_file: join(artifactsDir, "state.json"),
2039
+ confirm_resume_ack: ackPath,
2040
+ },
2041
+ });
2042
+ }
2043
+ async function buildConfirmIntentStep(ctx) {
2044
+ const { root, artifactsDir, state } = ctx;
2045
+ const runId = stateRunId(state);
2046
+ const nextCommand = loaderCommand("next-step");
2047
+ const checkpointPath = join(artifactsDir, "intent_checkpoint.json");
2048
+ // Read the pre-drafted checkpoint if one exists (confirmed_by: "draft").
2049
+ const draft = await readOptionalJsonFile(checkpointPath);
2050
+ const isDraft = draft?.confirmed_by === "draft";
2051
+ let prompt;
2052
+ if (isDraft && draft) {
2053
+ // Build a consolidated single-stop proposal from the draft.
2054
+ const draftRaw = draft;
2055
+ const preDraftQuestions = Array.isArray(draftRaw.pre_draft_questions)
2056
+ ? draftRaw.pre_draft_questions
2057
+ : [];
2058
+ // INV-remediate-state-06: only explicit blocking===true is blocking.
2059
+ const blockingQs = preDraftQuestions.filter((q) => q.blocking === true);
2060
+ const nonBlockingQs = preDraftQuestions.filter((q) => q.blocking !== true);
2061
+ const intentInterpretation = typeof draftRaw.intent_interpretation === "string" ? draftRaw.intent_interpretation : undefined;
2062
+ const suggestedClosingAction = typeof draftRaw.closing_action === "string" ? draftRaw.closing_action : undefined;
2063
+ const questionLines = [
2064
+ ...blockingQs.map((q) => `- **[blocking] ${q.id}**: ${q.question}`),
2065
+ ...nonBlockingQs.map((q) => `- **[FYI] ${q.id}**: ${q.question}`),
2066
+ ].join("\n") || "- None";
2067
+ const filtersBlock = draft.filters && Object.keys(draft.filters).length > 0
2068
+ ? `\`\`\`json\n${JSON.stringify(draft.filters, null, 2)}\n\`\`\``
2069
+ : "(none — remediating all findings)";
2070
+ const closingOptions = "`commit` or `none`";
2071
+ prompt = `
2072
+ # Confirm Remediation Scope and Intent
2073
+
2074
+ The intake worker has pre-populated the following proposal. Review each section
2075
+ and adjust where needed, then confirm by writing the final \`intent_checkpoint.json\`.
2076
+
2077
+ ## Proposed Scope
2078
+
2079
+ ${draft.scope_summary ?? "(not set)"}
2080
+
2081
+ ## Proposed Intent
2082
+
2083
+ ${draft.intent_summary ?? "(not set)"}
2084
+ ${intentInterpretation ? `\n**How free-form intent was interpreted:** ${intentInterpretation}\n` : ""}
2085
+ ## Proposed Filters
2086
+
2087
+ ${filtersBlock}
2088
+
2089
+ ## Open Questions
2090
+
2091
+ ${questionLines}
2092
+
2093
+ ## Suggested Closing Action
2094
+
2095
+ ${suggestedClosingAction ?? "commit"} (valid options: ${closingOptions})
2096
+
2097
+ ---
2098
+
2099
+ To confirm, write the final checkpoint to:
2100
+
2101
+ \`${checkpointPath}\`
2102
+
2103
+ \`\`\`json
2104
+ {
2105
+ "schema_version": "intent-checkpoint/v1",
2106
+ "confirmed_at": "<ISO-8601 timestamp>",
2107
+ "confirmed_by": "host",
2108
+ "scope_summary": "${draft.scope_summary ?? "<the files/areas in scope>"}",
2109
+ "intent_summary": "${draft.intent_summary ?? "<the goal>"}",
2110
+ "free_form_intent": "<optional: additional guidance>",
2111
+ "filters": ${JSON.stringify(draft.filters ?? {}, null, 2)},
2112
+ "excluded_scope": [],
2113
+ "must_not_touch": []
2114
+ }
2115
+ \`\`\`
2116
+
2117
+ Adjust \`filters\`, \`excluded_scope\`, \`must_not_touch\`, or \`free_form_intent\` to
2118
+ narrow scope. Valid severities: \`critical\`, \`high\`, \`medium\`, \`low\`, \`info\`.
2119
+ Valid lenses: \`correctness\`, \`architecture\`, \`maintainability\`, \`security\`,
2120
+ \`reliability\`, \`performance\`, \`data_integrity\`, \`tests\`, \`operability\`,
2121
+ \`config_deployment\`, \`observability\`.
2122
+
2123
+ Once written with \`"confirmed_by": "host"\`, run:
2124
+
2125
+ \`${nextCommand}\`
2126
+ `;
2127
+ }
2128
+ else {
2129
+ // Fallback for when there is no pre-drafted checkpoint.
2130
+ prompt = `
2131
+ # Confirm Remediation Scope and Intent
2132
+
2133
+ Please review the intake summary at \`.audit-tools/remediation/intake/intake-summary.json\` (and the audit report, if this run consumes one).
2134
+
2135
+ Confirm or refine the remediation scope and intent by writing a valid \`intent_checkpoint.json\` artifact under \`.audit-tools/remediation/\`.
2136
+
2137
+ Only \`scope_summary\` and \`intent_summary\` are required; add the optional fields to narrow what gets remediated:
2138
+
2139
+ \`\`\`json
2140
+ {
2141
+ "schema_version": "intent-checkpoint/v1",
2142
+ "confirmed_at": "<ISO-8601 timestamp>",
2143
+ "confirmed_by": "host",
2144
+ "scope_summary": "<the files/areas in scope>",
2145
+ "intent_summary": "<the goal, e.g. full-remediation / security-only>",
2146
+ "free_form_intent": "<optional: guidance threaded into remediation worker prompts>",
2147
+ "filters": {
2148
+ "severity": ["critical", "high"],
2149
+ "lenses": ["security", "reliability"],
2150
+ "packages": ["<package or path prefix>"],
2151
+ "themes": ["<theme id>"]
2152
+ },
2153
+ "excluded_scope": [{ "path": "<path or prefix>", "reason": "<why>" }],
2154
+ "must_not_touch": ["<glob>"]
2155
+ }
2156
+ \`\`\`
2157
+
2158
+ - \`filters\` drop findings that don't match BEFORE planning, so only the work you want is remediated. Valid severities: \`critical\`, \`high\`, \`medium\`, \`low\`, \`info\`. Valid lenses: \`correctness\`, \`architecture\`, \`maintainability\`, \`security\`, \`reliability\`, \`performance\`, \`data_integrity\`, \`tests\`, \`operability\`, \`config_deployment\`, \`observability\`. Draw \`packages\`/\`themes\` from the findings in the audit report.
2159
+ - \`excluded_scope\` drops findings whose files match a path or directory prefix; \`must_not_touch\` globs are never written.
2160
+ - Skipped findings are listed in the final remediation report under "Skipped by Intent Checkpoint".
2161
+ - Leave the optional fields out to remediate everything in the report.
2162
+
2163
+ Once the file is written, run:
2164
+
2165
+ \`${nextCommand}\`
2166
+ `;
2167
+ }
2168
+ return writeCurrentStep({
2169
+ stepKind: "confirm_intent",
2170
+ status: "ready",
2171
+ runId,
2172
+ repoRoot: root,
2173
+ artifactsDir,
2174
+ prompt,
2175
+ allowedCommands: [nextCommand],
2176
+ stopCondition: "Stop after writing intent_checkpoint.json and running next-step.",
2177
+ artifactPaths: {
2178
+ intent_checkpoint: checkpointPath,
2179
+ },
2180
+ });
2181
+ }
2182
+ // ---------------------------------------------------------------------------
2183
+ // Deterministic free_form_intent interpretation at the call site (INV-S04)
2184
+ // ---------------------------------------------------------------------------
2185
+ //
2186
+ // The IntentCheckpoint contract states `free_form_intent` is "interpreted into
2187
+ // priority/lens/scope signals at planning time via freeFormIntentInterpreter.
2188
+ // Never threaded verbatim into worker or dispatch prompts (INV-S04)." This is
2189
+ // the call site that honours that: when a CONFIRMED checkpoint carries a
2190
+ // free_form_intent, we run the shared deterministic interpreter HERE — never
2191
+ // pass the raw string downstream — and persist the structured signals so
2192
+ // planning consumes the encoded lens-weights/priority/scope, and so the
2193
+ // unencodable clauses are surfaced (never silently dropped) rather than relying
2194
+ // on an LLM-authored free-text `intent_interpretation`.
2195
+ /** Sidecar artifact recording the deterministic interpretation of free_form_intent. */
2196
+ export const INTENT_INTERPRETATION_FILENAME = "intent-interpretation.json";
2197
+ export const INTENT_INTERPRETATION_SCHEMA_VERSION = "remediate-code-intent-interpretation/v1alpha1";
2198
+ /**
2199
+ * Interpret a confirmed checkpoint's `free_form_intent` via the shared
2200
+ * deterministic interpreter and persist the structured signals to a sidecar
2201
+ * artifact. Idempotent and best-effort: returns the persisted interpretation (or
2202
+ * null when there is nothing to interpret / no confirmed checkpoint) and never
2203
+ * throws into the decide loop. The raw `free_form_intent` string is NOT returned
2204
+ * or threaded anywhere — only the structured `InterpretedIntent` is (INV-S04).
2205
+ */
2206
+ export async function interpretConfirmedCheckpointIntent(artifactsDir, checkpoint) {
2207
+ if (!checkpoint || checkpoint.confirmed_by !== "host")
2208
+ return null;
2209
+ const raw = checkpoint.free_form_intent;
2210
+ if (typeof raw !== "string" || raw.trim().length === 0)
2211
+ return null;
2212
+ const interpreted = interpretFreeFormIntent(raw);
2213
+ const persisted = {
2214
+ schema_version: INTENT_INTERPRETATION_SCHEMA_VERSION,
2215
+ interpreted,
2216
+ unencodable_clauses: interpreted.unencodableClauses,
2217
+ created_at: new Date().toISOString(),
2218
+ };
2219
+ try {
2220
+ await writeJsonFile(join(artifactsDir, INTENT_INTERPRETATION_FILENAME), persisted);
2221
+ }
2222
+ catch {
2223
+ // Best-effort sidecar: a write failure must never block the decide loop.
2224
+ }
2225
+ if (interpreted.unencodableClauses.length > 0) {
2226
+ process.stderr.write(`[remediate-code] free_form_intent: ${interpreted.unencodableClauses.length} ` +
2227
+ `clause(s) could not be encoded as lens/priority/scope signals and are ` +
2228
+ `surfaced for promotion to constraints: ` +
2229
+ `${interpreted.unencodableClauses.join("; ")}\n`);
2230
+ }
2231
+ return persisted;
2232
+ }
2233
+ /**
2234
+ * Narrow a nullable engine state to non-null inside an executor whose `derive`
2235
+ * only marks it actionable when the state is present — a violation is an engine
2236
+ * contract bug, not a runtime condition.
2237
+ */
2238
+ function requireState(state) {
2239
+ if (!state) {
2240
+ throw new Error("remediate obligation executor reached with a null state — derive() contract violated");
2241
+ }
2242
+ return state;
2243
+ }
2244
+ /**
2245
+ * Priority order for the pre-intake obligations — mirrors the original cascade's
2246
+ * top-down guard order exactly so selection cannot drift.
2247
+ */
2248
+ const PRE_INTAKE_PRIORITY = [
2249
+ "input_conflict",
2250
+ "confirm_resume",
2251
+ "confirm_intent",
2252
+ "interpret_intent",
2253
+ "complete_redelivery",
2254
+ "report_warning",
2255
+ "complete",
2256
+ "pending_intake",
2257
+ ];
2258
+ /**
2259
+ * The linear pre-intake gates as declarative obligations (A3 slice 1). Built per
2260
+ * call so each `derive` can close over `ctx` paths + the pre-read `snapshot` and
2261
+ * read the remaining signals (existsSync, status, inputResolution) synchronously.
2262
+ * The matching executors are the original cascade handlers, classified emit vs
2263
+ * transition; the host-facing behaviour is unchanged.
2264
+ */
2265
+ function buildPreIntakeObligations(ctx, snapshot) {
2266
+ const { artifactsDir, inputResolution } = ctx;
2267
+ const { existingCheckpoint, resumeAck, entryState } = snapshot;
2268
+ const ip = intakePaths(artifactsDir);
2269
+ const checkpointPath = join(artifactsDir, "intent_checkpoint.json");
2270
+ const ackPath = join(artifactsDir, "confirm_resume_ack.json");
2271
+ const interpretationPath = join(artifactsDir, INTENT_INTERPRETATION_FILENAME);
2272
+ const reportPath = join(dirname(artifactsDir), "remediation-report.md");
2273
+ // Fires at most once per host call; gates the leftover-report warning so a
2274
+ // re-scan after a transition cannot re-print it (mirrors the cascade's
2275
+ // single fall-through hit).
2276
+ const warned = { value: false };
2277
+ return [
2278
+ {
2279
+ // A new --input against a run already past intake must not silently resume
2280
+ // the old plan; require an explicit resume-vs-restart choice. Derives from
2281
+ // the frozen entry state — never an intake-created one.
2282
+ id: "input_conflict",
2283
+ derive: () => inputResolution.supplied &&
2284
+ entryState != null &&
2285
+ entryState.status !== "pending"
2286
+ ? "missing"
2287
+ : "satisfied",
2288
+ execute: async (_state, c) => {
2289
+ const s = requireState(entryState);
2290
+ await c.countStep(s);
2291
+ return {
2292
+ kind: "emit",
2293
+ step: await handleInputConflict(c.root, c.artifactsDir, s, c.inputResolution),
2294
+ };
2295
+ },
2296
+ },
2297
+ {
2298
+ // Bare re-invocation of an in-progress run: present resume/restart/merge
2299
+ // once (gated on the ack file) rather than silently resuming. An ack of
2300
+ // choice==='resume' is satisfied — fall through to normal dispatch. Derives
2301
+ // from the frozen entry state (a resume is of a *pre-existing* run).
2302
+ id: "confirm_resume",
2303
+ derive: () => {
2304
+ if (inputResolution.supplied ||
2305
+ entryState == null ||
2306
+ entryState.status === "complete" ||
2307
+ entryState.status === "pending") {
2308
+ return "satisfied";
2309
+ }
2310
+ return !resumeAck || resumeAck.choice !== "resume" ? "missing" : "satisfied";
2311
+ },
2312
+ execute: async (_state, c) => {
2313
+ const s = requireState(entryState);
2314
+ await c.countStep(s);
2315
+ return {
2316
+ kind: "emit",
2317
+ step: await buildConfirmResumeOrRestartStep({
2318
+ root: c.root,
2319
+ artifactsDir: c.artifactsDir,
2320
+ state: s,
2321
+ ackPath,
2322
+ }),
2323
+ };
2324
+ },
2325
+ },
2326
+ {
2327
+ // Intent gate: fire when no confirmed checkpoint exists (no checkpoint + any
2328
+ // intake artifact or an active run, or a draft checkpoint). Never for
2329
+ // complete/closing — those already confirmed their checkpoint.
2330
+ id: "confirm_intent",
2331
+ derive: (state) => {
2332
+ const checkpointIsDraft = existingCheckpoint?.confirmed_by === "draft";
2333
+ const activeRunState = state != null &&
2334
+ state.status !== "pending" &&
2335
+ state.status !== "complete" &&
2336
+ state.status !== "closing";
2337
+ const fires = checkpointIsDraft ||
2338
+ (!existsSync(checkpointPath) &&
2339
+ (existsSync(ip.summary) ||
2340
+ existsSync(ip.extractedPlan) ||
2341
+ activeRunState));
2342
+ return fires ? "missing" : "satisfied";
2343
+ },
2344
+ execute: async (state, c) => {
2345
+ await c.countStep(state);
2346
+ return {
2347
+ kind: "emit",
2348
+ step: await buildConfirmIntentStep({
2349
+ root: c.root,
2350
+ artifactsDir: c.artifactsDir,
2351
+ state,
2352
+ }),
2353
+ };
2354
+ },
2355
+ },
2356
+ {
2357
+ // Past the intent gate: interpret the confirmed checkpoint's
2358
+ // free_form_intent once (INV-S04) and persist the structured signals. A
2359
+ // transition (state unchanged) — the re-scan skips it once the sidecar
2360
+ // exists.
2361
+ id: "interpret_intent",
2362
+ derive: () => existingCheckpoint?.confirmed_by === "host" &&
2363
+ typeof existingCheckpoint.free_form_intent === "string" &&
2364
+ existingCheckpoint.free_form_intent.trim().length > 0 &&
2365
+ !existsSync(interpretationPath)
2366
+ ? "missing"
2367
+ : "satisfied",
2368
+ execute: async (state) => {
2369
+ await interpretConfirmedCheckpointIntent(artifactsDir, existingCheckpoint);
2370
+ return { kind: "transition", state };
2371
+ },
2372
+ },
2373
+ {
2374
+ // Finished runs delete the artifact dir but leave the root report. A bare
2375
+ // re-invocation with no fresh intent re-presents that report instead of
2376
+ // asking for a new starting point.
2377
+ id: "complete_redelivery",
2378
+ derive: (state) => {
2379
+ if (state != null || inputResolution.supplied || !existsSync(reportPath)) {
2380
+ return "satisfied";
2381
+ }
2382
+ const freshIntent = existsSync(ip.conversationStart) || existsSync(ip.extractedPlan);
2383
+ return freshIntent ? "satisfied" : "missing";
2384
+ },
2385
+ execute: async (state, c) => ({
2386
+ kind: "emit",
2387
+ step: await handleComplete(c.root, c.artifactsDir, state),
2388
+ }),
2389
+ },
2390
+ {
2391
+ // Diagnostic (not a gate): a leftover root report will be overwritten when a
2392
+ // fresh/active run completes. A transition (prints once, state unchanged);
2393
+ // its priority slot — after complete_redelivery, before complete — means a
2394
+ // re-presented/complete run never reaches it, exactly as the cascade's
2395
+ // fall-through ordering did.
2396
+ id: "report_warning",
2397
+ derive: (state) => !warned.value &&
2398
+ existsSync(reportPath) &&
2399
+ state?.status !== "complete"
2400
+ ? "missing"
2401
+ : "satisfied",
2402
+ execute: async (state) => {
2403
+ warned.value = true;
2404
+ process.stderr.write("[remediate-code] A previous remediation-report.md exists in .audit-tools/; it will be overwritten when this run completes.\n");
2405
+ return { kind: "transition", state };
2406
+ },
2407
+ },
2408
+ {
2409
+ id: "complete",
2410
+ derive: (state) => (state?.status === "complete" ? "missing" : "satisfied"),
2411
+ execute: async (state, c) => {
2412
+ await c.countStep(state);
2413
+ return {
2414
+ kind: "emit",
2415
+ step: await handleComplete(c.root, c.artifactsDir, state),
2416
+ };
2417
+ },
2418
+ },
2419
+ {
2420
+ // No state yet: resolve intake. A produced step is emitted; a produced state
2421
+ // transitions (the re-scan falls through to the inline tail); a null result
2422
+ // emits the collect-starting-point step (the folded old no-state branch).
2423
+ id: "pending_intake",
2424
+ derive: (state) => (state == null ? "missing" : "satisfied"),
2425
+ execute: async (_state, c) => {
2426
+ const outcome = await handlePendingIntake(c.root, c.artifactsDir, c.options);
2427
+ if (outcome && "step_kind" in outcome) {
2428
+ return { kind: "emit", step: outcome };
2429
+ }
2430
+ if (outcome) {
2431
+ return { kind: "transition", state: outcome };
2432
+ }
2433
+ return { kind: "emit", step: await handleNoState(c.root, c.artifactsDir) };
2434
+ },
2435
+ },
2436
+ ];
2437
+ }
2438
+ /**
2439
+ * Priority order for the main (post-intake) obligations — mirrors the original
2440
+ * cascade tail's guard order exactly so selection cannot drift.
2441
+ */
2442
+ const MAIN_PRIORITY = [
2443
+ "waiting_for_clarification",
2444
+ "waiting_for_triage",
2445
+ "planning_documentable",
2446
+ "partial_terminal",
2447
+ "implementing",
2448
+ "triage",
2449
+ "planning_zero",
2450
+ "all_terminal",
2451
+ "closing",
2452
+ "unhandled",
2453
+ ];
2454
+ /**
2455
+ * The post-intake cascade tail as declarative obligations (A3 slice 2). Runs on a
2456
+ * non-null state (pre-intake resolved it). Every phase handler returns a
2457
+ * `RemediateOutcome` — a `transition` (planning→implementing, triage, the
2458
+ * re-block/close funnel, the dispatch merge-then-reenter folds) or an `emit` (a
2459
+ * host-actionable step). `advance` drives the whole fold with ZERO recursion
2460
+ * (slice 2b). The one cross-engine case — `handleClosing` reaching `complete`,
2461
+ * which lives in the pre-intake engine — emits the report directly rather than
2462
+ * transitioning (a main transition could never select it).
2463
+ */
2464
+ function buildMainObligations(ctx) {
2465
+ const { root, artifactsDir, options, runLogger, store } = ctx;
2466
+ const clarificationResolutionPath = join(artifactsDir, "clarification_resolution.json");
2467
+ const triageResolutionPath = join(artifactsDir, "triage_resolution.json");
2468
+ return [
2469
+ {
2470
+ // Plan-phase clarification wait: apply a resolution if present (transition →
2471
+ // re-scan), else surface the wait step.
2472
+ id: "waiting_for_clarification",
2473
+ derive: (state) => state?.status === "waiting_for_clarification" ? "missing" : "satisfied",
2474
+ execute: async (state) => {
2475
+ const s = requireState(state);
2476
+ if (existsSync(clarificationResolutionPath)) {
2477
+ const next = await applyPlanClarificationResolution(artifactsDir, s, store);
2478
+ return { kind: "transition", state: next };
2479
+ }
2480
+ return {
2481
+ kind: "emit",
2482
+ step: await handleWaitingForClarification(root, artifactsDir, s),
2483
+ };
2484
+ },
2485
+ },
2486
+ {
2487
+ // Triage wait: apply a resolution (→ triage, transition) if present, else
2488
+ // surface the wait step.
2489
+ id: "waiting_for_triage",
2490
+ derive: (state) => state?.status === "waiting_for_triage" ? "missing" : "satisfied",
2491
+ execute: async (state) => {
2492
+ const s = requireState(state);
2493
+ if (existsSync(triageResolutionPath)) {
2494
+ s.status = "triage";
2495
+ await store.saveState(s);
2496
+ return { kind: "transition", state: s };
2497
+ }
2498
+ return {
2499
+ kind: "emit",
2500
+ step: await handleWaitingForTriage(root, artifactsDir, s),
2501
+ };
2502
+ },
2503
+ },
2504
+ {
2505
+ id: "planning_documentable",
2506
+ derive: (state) => state != null &&
2507
+ state.status === "planning" &&
2508
+ documentableFindings(state).length > 0
2509
+ ? "missing"
2510
+ : "satisfied",
2511
+ execute: async (state) => handlePlanning(root, artifactsDir, requireState(state), store),
2512
+ },
2513
+ {
2514
+ // Partial-completion terminal consume (OBL-S09 / INV-X06): block the
2515
+ // precisely-named stranded ids + every other non-terminal item (the
2516
+ // no-livelock guarantee), clear the flag, then force the close transition
2517
+ // via handleAllTerminalTransition (blocked is non-terminal, so all_terminal
2518
+ // would not otherwise fire).
2519
+ id: "partial_terminal",
2520
+ derive: (state) => state != null &&
2521
+ state.partial_completion_terminal != null &&
2522
+ !allItemsTerminal(state)
2523
+ ? "missing"
2524
+ : "satisfied",
2525
+ execute: async (state) => {
2526
+ const s = requireState(state);
2527
+ const terminal = s.partial_completion_terminal;
2528
+ if (!terminal)
2529
+ return { kind: "transition", state: s };
2530
+ const strandedSet = new Set(terminal.stranded_ids ?? []);
2531
+ for (const it of Object.values(s.items ?? {})) {
2532
+ if (isTerminalStatus(it.status))
2533
+ continue;
2534
+ it.status = "blocked";
2535
+ const stranded = strandedSet.has(it.finding_id);
2536
+ it.failure_reason =
2537
+ it.failure_reason ??
2538
+ (stranded
2539
+ ? `Stranded by partial-completion terminal (${terminal.reason}): the provider pool was exhausted before this item could be dispatched (no pool survived re-routing).`
2540
+ : `Blocked after partial-completion terminal (${terminal.reason}): no provider pool remained to dispatch this item.`);
2541
+ }
2542
+ delete s.partial_completion_terminal;
2543
+ await store.saveState(s);
2544
+ return handleAllTerminalTransition(root, artifactsDir, s, store, options, runLogger);
2545
+ },
2546
+ },
2547
+ {
2548
+ id: "implementing",
2549
+ derive: (state) => state?.status === "implementing" ? "missing" : "satisfied",
2550
+ execute: async (state) => {
2551
+ const s = requireState(state);
2552
+ // Pending implementable blocks dispatch; triage only runs once every item
2553
+ // has left "pending".
2554
+ const pendingBlocks = implementableBlocks(s);
2555
+ if (pendingBlocks.length > 0) {
2556
+ return buildImplementDispatchStep({
2557
+ root,
2558
+ artifactsDir,
2559
+ state: s,
2560
+ options,
2561
+ store,
2562
+ });
2563
+ }
2564
+ // Dead-end pending nodes whose dependency never reached verified-complete
2565
+ // (INV-RS-01) so the implementing→triage loop can't livelock; transition
2566
+ // so the engine re-scans on the updated state.
2567
+ const deadEnded = blockedByUnsatisfiedDependency(s);
2568
+ if (deadEnded.length > 0) {
2569
+ const now = new Date().toISOString();
2570
+ let changed = false;
2571
+ for (const block of deadEnded) {
2572
+ for (const findingId of block.items) {
2573
+ const it = s.items?.[findingId];
2574
+ if (!it || it.status !== "pending")
2575
+ continue;
2576
+ it.status = "blocked";
2577
+ it.started_at ??= now;
2578
+ it.completed_at = now;
2579
+ it.failure_reason =
2580
+ it.failure_reason ??
2581
+ "A dependency node did not reach a verified-complete disposition " +
2582
+ "(a prerequisite was skipped, blocked, or the dependencies are cyclic); " +
2583
+ "the rolling scheduler will not dispatch this node (INV-RS-01).";
2584
+ changed = true;
2585
+ }
2586
+ }
2587
+ if (changed) {
2588
+ await store.saveState(s);
2589
+ return { kind: "transition", state: s };
2590
+ }
2591
+ }
2592
+ return handleImplementing(root, artifactsDir, s, runLogger, store);
2593
+ },
2594
+ },
2595
+ {
2596
+ id: "triage",
2597
+ derive: (state) => (state?.status === "triage" ? "missing" : "satisfied"),
2598
+ execute: async (state) => handleImplementing(root, artifactsDir, requireState(state), runLogger, store),
2599
+ },
2600
+ {
2601
+ // planning with zero documentable findings is a user question, not a
2602
+ // dead-end — must fire BEFORE all_terminal so an all-resolved planning state
2603
+ // doesn't silently advance to close.
2604
+ id: "planning_zero",
2605
+ derive: (state) => state != null &&
2606
+ state.status === "planning" &&
2607
+ documentableFindings(state).length === 0
2608
+ ? "missing"
2609
+ : "satisfied",
2610
+ execute: async (state) => ({
2611
+ kind: "emit",
2612
+ step: await handleZeroDocumentableFindings(root, artifactsDir, requireState(state)),
2613
+ }),
2614
+ },
2615
+ {
2616
+ id: "all_terminal",
2617
+ derive: (state) => state != null && allItemsTerminal(state) && state.status !== "closing"
2618
+ ? "missing"
2619
+ : "satisfied",
2620
+ execute: async (state) => handleAllTerminalTransition(root, artifactsDir, requireState(state), store, options, runLogger),
2621
+ },
2622
+ {
2623
+ id: "closing",
2624
+ derive: (state) => (state?.status === "closing" ? "missing" : "satisfied"),
2625
+ execute: async (state) => handleClosing(root, artifactsDir, requireState(state), runLogger, store),
2626
+ },
2627
+ {
2628
+ // Catch-all: reached only when no specific obligation matched. Always
2629
+ // actionable on a non-null state (the lowest-priority slot), so `advance`
2630
+ // surfaces the diagnostic rather than returning a null step.
2631
+ id: "unhandled",
2632
+ derive: (state) => (state != null ? "missing" : "satisfied"),
2633
+ execute: async (state) => ({
2634
+ kind: "emit",
2635
+ step: await handleUnhandledState(root, artifactsDir, requireState(state)),
2636
+ }),
2637
+ },
2638
+ ];
2639
+ }
2640
+ async function decideNextStepLoop(options, runLogger) {
2641
+ const root = resolveRoot(options.root);
2642
+ const artifactsDir = resolveArtifactsDir(root, options.artifactsDir);
2643
+ await mkdir(artifactsDir, { recursive: true });
2644
+ const store = new StateStore(artifactsDir);
2645
+ let state = await store.loadState();
2646
+ runLogger.event({
2647
+ phase: "next-step",
2648
+ kind: "state",
2649
+ obligation: state?.status ?? "pending",
2650
+ });
2651
+ // step_count is incremented once per host invocation. The `counted` flag guards
2652
+ // the shared `countStep` closure so the forceReplan preamble, the pre-intake
2653
+ // obligation executors, and the post-intake count point can never double-count
2654
+ // within a call. step_count is not embedded in the emitted step, so the
2655
+ // count-vs-build ordering is unobservable. (Every phase handler now returns a
2656
+ // transition/emit outcome, so `advance` drives the whole fold in ONE call —
2657
+ // there is no recursive re-entry to guard against.)
2658
+ const counted = { value: false };
2659
+ const countStep = async (current) => {
2660
+ if (!current || counted.value)
2661
+ return;
2662
+ if (!current.started_at)
2663
+ current.started_at = new Date().toISOString();
2664
+ current.step_count = (current.step_count ?? 0) + 1;
2665
+ counted.value = true;
2666
+ await store.saveState(current);
2667
+ };
2668
+ const inputResolution = resolveInputPaths(root, options.input);
2669
+ // Preamble — forceReplan re-grounds from existing intake. The whole decide loop
2670
+ // runs once per host call (the engine folds planning → implementing → … through
2671
+ // transitions, never a recursive decideNextStepLoop), so this fires at most once.
2672
+ if (options.forceReplan && state != null) {
2673
+ await countStep(state);
2674
+ state = await forceReplanFromExistingIntake(root, artifactsDir, state, store);
2675
+ }
2676
+ // Pre-read the once-async signals the pre-intake derive()s consume
2677
+ // synchronously (no transition inside this advance call rewrites either file).
2678
+ const checkpointPath = join(artifactsDir, "intent_checkpoint.json");
2679
+ const existingCheckpoint = existsSync(checkpointPath)
2680
+ ? await readOptionalJsonFile(checkpointPath)
2681
+ : undefined;
2682
+ const resumeAck = await readOptionalJsonFile(join(artifactsDir, "confirm_resume_ack.json"));
2683
+ // The linear pre-intake gates run as obligations through the shared advance
2684
+ // loop. An emit returns to the host; a transition re-scans within this call;
2685
+ // exhausting them (step === null) means the run is past intake and falls
2686
+ // through to the post-intake `advance` (MAIN_PRIORITY) below.
2687
+ const ctx = {
2688
+ root,
2689
+ artifactsDir,
2690
+ options,
2691
+ runLogger,
2692
+ store,
2693
+ inputResolution,
2694
+ countStep,
2695
+ };
2696
+ const preIntake = await advance({
2697
+ priority: PRE_INTAKE_PRIORITY,
2698
+ obligations: buildPreIntakeObligations(ctx, {
2699
+ existingCheckpoint,
2700
+ resumeAck,
2701
+ entryState: state,
2702
+ }),
2703
+ }, state, ctx);
2704
+ if (preIntake.step)
2705
+ return preIntake.step;
2706
+ state = preIntake.state;
2707
+ // pending_intake folds the old no-state branch (it emits handleNoState on a
2708
+ // null intake), so advance only falls through here with a non-null state; keep
2709
+ // the guard as the type narrowing + a defensive fallback.
2710
+ if (!state) {
2711
+ return handleNoState(root, artifactsDir);
2712
+ }
2713
+ await countStep(state);
2714
+ const main = await advance({ priority: MAIN_PRIORITY, obligations: buildMainObligations(ctx) }, state, ctx);
2715
+ if (main.step)
2716
+ return main.step;
2717
+ // The unhandled catch-all always emits on a non-null state, so a null step here
2718
+ // is unreachable; keep an explicit fallback rather than a non-null assertion.
2719
+ return handleUnhandledState(root, artifactsDir, state);
2720
+ }
2721
+ //# sourceMappingURL=nextStep.js.map