@smartergpt/lexrunner 1.0.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 (1433) hide show
  1. package/.changes/ci-debug-added.txt +1 -0
  2. package/.changeset/tsconfig-solution-build.md +5 -0
  3. package/.editorconfig +9 -0
  4. package/.env.example +8 -0
  5. package/.github/COST_EFFICIENCY.md +60 -0
  6. package/.github/ISSUE_TEMPLATE/bug_report.md +28 -0
  7. package/.github/ISSUE_TEMPLATE/epic.yml +123 -0
  8. package/.github/ISSUE_TEMPLATE/feature_request.md +26 -0
  9. package/.github/ISSUE_TEMPLATE/issue-A1-gate-input-validation.md +380 -0
  10. package/.github/ISSUE_TEMPLATE/issue-B1-scope-validation.md +509 -0
  11. package/.github/ISSUE_TEMPLATE/issue-C1-command-whitelist.md +463 -0
  12. package/.github/ISSUE_TEMPLATE/subtask.yml +153 -0
  13. package/.github/PULL_REQUEST_TEMPLATE.md +9 -0
  14. package/.github/copilot-instructions-old.md +429 -0
  15. package/.github/copilot-instructions.md +33 -0
  16. package/.github/instructions/tests.instructions.md +10 -0
  17. package/.github/workflows/auto-delete-merged-branches.yml +103 -0
  18. package/.github/workflows/benchmarks.yml +72 -0
  19. package/.github/workflows/ci-debug.yml +33 -0
  20. package/.github/workflows/ci.yml +167 -0
  21. package/.github/workflows/cli-smoke-test.yml +345 -0
  22. package/.github/workflows/copilot-setup-steps.yml +20 -0
  23. package/.github/workflows/frame-emission-gate.yml +242 -0
  24. package/.github/workflows/project-auto.yml +24 -0
  25. package/.github/workflows/release.yml +260 -0
  26. package/.github/workflows/slow-cli-tests.yml +37 -0
  27. package/.github/workflows/tag-guard.yml +44 -0
  28. package/.husky/pre-commit +1 -0
  29. package/.nvmrc +2 -0
  30. package/.prettierignore +28 -0
  31. package/.prettierrc.json +10 -0
  32. package/.smartergpt/CONTROL_DECK_VISION.md +226 -0
  33. package/.smartergpt/allowed-commands.json +41 -0
  34. package/.smartergpt/allowed-commands.strict.json +56 -0
  35. package/.smartergpt/deliverables/.live.md +426 -0
  36. package/.smartergpt/deliverables/ISSUE_STATUS_2025-12-28.md +193 -0
  37. package/.smartergpt/deliverables/_research/snapshot-contract-feedback/ADR_DISCUSSION.md +379 -0
  38. package/.smartergpt/deliverables/_research/snapshot-contract-feedback/Answer_claude-haiku.md +109 -0
  39. package/.smartergpt/deliverables/_research/snapshot-contract-feedback/Answer_gemini-flash.md +42 -0
  40. package/.smartergpt/deliverables/_research/snapshot-contract-feedback/Answer_gpt-codex-mini.md +19 -0
  41. package/.smartergpt/deliverables/_research/snapshot-contract-feedback/Answer_raptor-mini.md +37 -0
  42. package/.smartergpt/deliverables/_research/snapshot-contract-feedback/Question.md +37 -0
  43. package/.smartergpt/deliverables/merge-weave-04469e41-24ba-4ed5-b0ff-13c7ea12858d.ndjson +2 -0
  44. package/.smartergpt/deps.yml +3 -0
  45. package/.smartergpt/docs/fanout-templates.md +213 -0
  46. package/.smartergpt/docs/merge-weave-interventions.md +261 -0
  47. package/.smartergpt/docs/test-fix-patterns.md +240 -0
  48. package/.smartergpt/fanout-templates.yml +263 -0
  49. package/.smartergpt/gates.yml +9 -0
  50. package/.smartergpt/intent.md +1 -0
  51. package/.smartergpt/issues/QOL-001-analysis-script-filtering.md +36 -0
  52. package/.smartergpt/issues/QOL-002-log-retention-policy.md +92 -0
  53. package/.smartergpt/issues/QOL-003-realtime-console-feedback.md +44 -0
  54. package/.smartergpt/issues/QOL-004-governance-report-cli.md +44 -0
  55. package/.smartergpt/issues/QOL-005-schema-versioning.md +46 -0
  56. package/.smartergpt/issues/QOL-006-debug-verbose-mode.md +45 -0
  57. package/.smartergpt/issues/QOL-COMPLETION-REPORT.md +359 -0
  58. package/.smartergpt/issues/QOL-REVIEW-SUMMARY.md +111 -0
  59. package/.smartergpt/issues/QOL-ROADMAP.md +71 -0
  60. package/.smartergpt/merge-policy.yml +41 -0
  61. package/.smartergpt/merge-weave-policy.yml +255 -0
  62. package/.smartergpt/o1.json +0 -0
  63. package/.smartergpt/o2.json +0 -0
  64. package/.smartergpt/personas/eager-pm.md +123 -0
  65. package/.smartergpt/personas/example.md +81 -0
  66. package/.smartergpt/personas/senior-dev.md +107 -0
  67. package/.smartergpt/profile.yml +2 -0
  68. package/.smartergpt/prompts/create-project.md +112 -0
  69. package/.smartergpt/prompts/idea.md +64 -0
  70. package/.smartergpt/pull-request-template.md +25 -0
  71. package/.smartergpt/schemas/behavior-rule.schema.d.ts +54 -0
  72. package/.smartergpt/schemas/behavior-rule.schema.js +56 -0
  73. package/.smartergpt/schemas/behavior-rule.schema.json +105 -0
  74. package/.smartergpt/schemas/behavior-rule.schema.ts +60 -0
  75. package/.smartergpt/schemas/execution-plan-v1.d.ts +47 -0
  76. package/.smartergpt/schemas/execution-plan-v1.js +22 -0
  77. package/.smartergpt/schemas/execution-plan-v1.json +113 -0
  78. package/.smartergpt/schemas/execution-plan-v1.ts +32 -0
  79. package/.smartergpt/schemas/execution-plan.schema.json +116 -0
  80. package/.smartergpt/schemas/feature-spec-v0.d.ts +13 -0
  81. package/.smartergpt/schemas/feature-spec-v0.js +12 -0
  82. package/.smartergpt/schemas/feature-spec-v0.json +58 -0
  83. package/.smartergpt/schemas/feature-spec-v0.ts +16 -0
  84. package/.smartergpt/schemas/feature-spec.schema.json +111 -0
  85. package/.smartergpt/schemas/gates.schema.d.ts +48 -0
  86. package/.smartergpt/schemas/gates.schema.js +20 -0
  87. package/.smartergpt/schemas/gates.schema.json +47 -0
  88. package/.smartergpt/schemas/gates.schema.ts +26 -0
  89. package/.smartergpt/schemas/idea.schema.json +81 -0
  90. package/.smartergpt/schemas/runner.scope.schema.d.ts +54 -0
  91. package/.smartergpt/schemas/runner.scope.schema.js +28 -0
  92. package/.smartergpt/schemas/runner.scope.schema.json +75 -0
  93. package/.smartergpt/schemas/runner.scope.schema.ts +36 -0
  94. package/.smartergpt/schemas/runner.stack.schema.d.ts +40 -0
  95. package/.smartergpt/schemas/runner.stack.schema.js +21 -0
  96. package/.smartergpt/schemas/runner.stack.schema.json +51 -0
  97. package/.smartergpt/schemas/runner.stack.schema.ts +27 -0
  98. package/.smartergpt/scope.yml +11 -0
  99. package/.smartergpt/stack.yml +16 -0
  100. package/.smartergpt/test-fix-patterns.yml +106 -0
  101. package/.tool-versions +13 -0
  102. package/AGENTS.md +402 -0
  103. package/CHANGELOG.md +256 -0
  104. package/CLAUDE.md +484 -0
  105. package/CONTRIBUTING.md +345 -0
  106. package/EAGER_PM_FANOUT_ANALYSIS.md +283 -0
  107. package/FAQ.md +292 -0
  108. package/FIXTURE_LIBRARY_SUMMARY.md +327 -0
  109. package/IMPLEMENTATION_SUMMARY.md +222 -0
  110. package/LICENSE +21 -0
  111. package/MANUAL_TEST_GUIDE.md +229 -0
  112. package/MCP-ALIGNMENT-SUMMARY.md +261 -0
  113. package/MCP-CONFIG.md +125 -0
  114. package/MERGE_WEAVE_QUICKSTART.md +450 -0
  115. package/MERGE_WEAVE_SUMMARY.md +259 -0
  116. package/MERGE_WEAVE_USAGE_GUIDE.md +368 -0
  117. package/NOTICE.md +43 -0
  118. package/README.mcp.md +770 -0
  119. package/README.md +1069 -0
  120. package/TEST_INFRASTRUCTURE_ASSESSMENT.md +225 -0
  121. package/bootstrap-lexrunner.sh +396 -0
  122. package/dist/api-7H7SJZIX.js +15 -0
  123. package/dist/api-U3X2WA6D.js +15 -0
  124. package/dist/audit-2TZ2LU72.js +60 -0
  125. package/dist/audit-5HH5BMKI.js +60 -0
  126. package/dist/audit-6K5K333I.js +60 -0
  127. package/dist/audit-DYQWS57J.js +60 -0
  128. package/dist/audit-JBWZ2GZ2.js +60 -0
  129. package/dist/audit-SJF3434D.js +60 -0
  130. package/dist/audit-TICGGVX5.js +60 -0
  131. package/dist/audit-YOBB27PY.js +60 -0
  132. package/dist/autopilot-3GAVXWWC.js +45 -0
  133. package/dist/autopilot-43NOYVQA.js +45 -0
  134. package/dist/autopilot-4UA3OWLU.js +45 -0
  135. package/dist/autopilot-54TK5CCG.js +45 -0
  136. package/dist/autopilot-5BHC2UQT.js +45 -0
  137. package/dist/autopilot-ABZUCVGY.js +45 -0
  138. package/dist/autopilot-ACJZP47Y.js +45 -0
  139. package/dist/autopilot-AL5F5AUS.js +46 -0
  140. package/dist/autopilot-BO67FWUC.js +45 -0
  141. package/dist/autopilot-BR6W4GEX.js +45 -0
  142. package/dist/autopilot-FOR2UKRY.js +45 -0
  143. package/dist/autopilot-GDTTXHEQ.js +45 -0
  144. package/dist/autopilot-GEAMFZBM.js +45 -0
  145. package/dist/autopilot-HDMBRZE6.js +45 -0
  146. package/dist/autopilot-IKI2Y6S4.js +44 -0
  147. package/dist/autopilot-ILTBWWOL.js +46 -0
  148. package/dist/autopilot-KI3MXIFI.js +44 -0
  149. package/dist/autopilot-LWNPZC3J.js +45 -0
  150. package/dist/autopilot-LXPJ4ZXF.js +45 -0
  151. package/dist/autopilot-MDIFIONK.js +46 -0
  152. package/dist/autopilot-NW3LDP6M.js +45 -0
  153. package/dist/autopilot-OKTSCG35.js +45 -0
  154. package/dist/autopilot-OR5PF5PD.js +45 -0
  155. package/dist/autopilot-PE65SBGN.js +45 -0
  156. package/dist/autopilot-PW7I4B6W.js +45 -0
  157. package/dist/autopilot-QMLBL5P6.js +45 -0
  158. package/dist/autopilot-QSN6ZU5O.js +45 -0
  159. package/dist/autopilot-R7EZJOGI.js +46 -0
  160. package/dist/autopilot-T544CPPD.js +44 -0
  161. package/dist/autopilot-TNQB6VGJ.js +44 -0
  162. package/dist/autopilot-UVIYCR6K.js +45 -0
  163. package/dist/autopilot-W3ZTTSH3.js +45 -0
  164. package/dist/autopilot-XPKWOFXO.js +44 -0
  165. package/dist/autopilot-XRX4QWRM.js +44 -0
  166. package/dist/autopilot-Y3BAGNI5.js +44 -0
  167. package/dist/autopilot-ZE64XW2K.js +44 -0
  168. package/dist/chunk-2ESYSVXG.js +48 -0
  169. package/dist/chunk-2VR554P7.js +668 -0
  170. package/dist/chunk-37DOWIVT.js +1084 -0
  171. package/dist/chunk-3DU2DWUP.js +400 -0
  172. package/dist/chunk-3DVXIZFM.js +11166 -0
  173. package/dist/chunk-3FABZF4V.js +811 -0
  174. package/dist/chunk-4FFGNTAV.js +515 -0
  175. package/dist/chunk-4GEC4HC3.js +11221 -0
  176. package/dist/chunk-4RVZNLD4.js +628 -0
  177. package/dist/chunk-55VWJYZY.js +39 -0
  178. package/dist/chunk-5CGWZH5X.js +340 -0
  179. package/dist/chunk-5QKWKK4M.js +11794 -0
  180. package/dist/chunk-5Z3XHND7.js +11755 -0
  181. package/dist/chunk-6A4IE3TI.js +302 -0
  182. package/dist/chunk-6KK5JFFE.js +106 -0
  183. package/dist/chunk-6YC2VSLE.js +11252 -0
  184. package/dist/chunk-7C4K2SHD.js +668 -0
  185. package/dist/chunk-ANXY4RGA.js +11091 -0
  186. package/dist/chunk-ASHKNUBR.js +11312 -0
  187. package/dist/chunk-B3OYDPOP.js +11793 -0
  188. package/dist/chunk-DBH7SQ2S.js +1084 -0
  189. package/dist/chunk-DEI7A5B4.js +11449 -0
  190. package/dist/chunk-DM4GHY3J.js +92 -0
  191. package/dist/chunk-EQKFCZLH.js +9823 -0
  192. package/dist/chunk-FAIJPBT5.js +40 -0
  193. package/dist/chunk-FDDKUDXR.js +11166 -0
  194. package/dist/chunk-FEAR6ETG.js +438 -0
  195. package/dist/chunk-FNBAHK5V.js +72 -0
  196. package/dist/chunk-FXL74C73.js +523 -0
  197. package/dist/chunk-GLJEDX4L.js +10247 -0
  198. package/dist/chunk-GTP4OHD7.js +1107 -0
  199. package/dist/chunk-HIHH7IVO.js +10557 -0
  200. package/dist/chunk-I3VXUVCB.js +10474 -0
  201. package/dist/chunk-I6BIFVWI.js +10519 -0
  202. package/dist/chunk-I72TRUTJ.js +1084 -0
  203. package/dist/chunk-J5B5KT2F.js +368 -0
  204. package/dist/chunk-JMTULZ66.js +11743 -0
  205. package/dist/chunk-JXIQ7HCK.js +11166 -0
  206. package/dist/chunk-K6HVPBDP.js +10692 -0
  207. package/dist/chunk-KBT5Y666.js +521 -0
  208. package/dist/chunk-LETPROKG.js +11092 -0
  209. package/dist/chunk-LLMY2BZF.js +1084 -0
  210. package/dist/chunk-NMNL4US2.js +1084 -0
  211. package/dist/chunk-O2XRP7JK.js +10247 -0
  212. package/dist/chunk-OGPWLFFO.js +11201 -0
  213. package/dist/chunk-OQJUWTZV.js +51 -0
  214. package/dist/chunk-PJRWPLQ6.js +669 -0
  215. package/dist/chunk-PYRVUCJR.js +370 -0
  216. package/dist/chunk-Q6Y524KH.js +669 -0
  217. package/dist/chunk-QF7DM5VW.js +106 -0
  218. package/dist/chunk-QGM4M3NI.js +37 -0
  219. package/dist/chunk-QIIELFTL.js +1107 -0
  220. package/dist/chunk-QUW6N7GR.js +10264 -0
  221. package/dist/chunk-QZASNLQX.js +11223 -0
  222. package/dist/chunk-RMN4IAWO.js +11808 -0
  223. package/dist/chunk-RN5NHU37.js +11465 -0
  224. package/dist/chunk-RNG3RILO.js +11755 -0
  225. package/dist/chunk-RSA6DEB4.js +9748 -0
  226. package/dist/chunk-RURYWSMX.js +10524 -0
  227. package/dist/chunk-SUEXK5U7.js +11201 -0
  228. package/dist/chunk-TVUF55OH.js +11807 -0
  229. package/dist/chunk-U5MMENCP.js +456 -0
  230. package/dist/chunk-U62I2R2D.js +434 -0
  231. package/dist/chunk-UHFMFO54.js +21 -0
  232. package/dist/chunk-UNZBDSEU.js +11166 -0
  233. package/dist/chunk-UOATTNQP.js +334 -0
  234. package/dist/chunk-UZFYNSMJ.js +334 -0
  235. package/dist/chunk-VP37GLU6.js +1084 -0
  236. package/dist/chunk-W6WDKBWO.js +11453 -0
  237. package/dist/chunk-XBKUFNVF.js +10745 -0
  238. package/dist/chunk-XOLVQTIE.js +670 -0
  239. package/dist/chunk-XVFTBVDS.js +257 -0
  240. package/dist/chunk-YABA7DB6.js +11091 -0
  241. package/dist/chunk-YWCJX5KL.js +10557 -0
  242. package/dist/chunk-Z5GP7FSR.js +309 -0
  243. package/dist/chunk-ZBT3DATZ.js +296 -0
  244. package/dist/chunk-ZDBAZXUQ.js +11201 -0
  245. package/dist/chunk-ZEMABYS4.js +92 -0
  246. package/dist/chunk-ZOA4HT7P.js +662 -0
  247. package/dist/cli.cjs +40431 -0
  248. package/dist/cli.d.cts +2709 -0
  249. package/dist/cli.d.ts +2709 -0
  250. package/dist/cli.js +21149 -0
  251. package/dist/commandValidator-42OUDFZ4.js +140 -0
  252. package/dist/commandValidator-7LQHTYL5.js +140 -0
  253. package/dist/commandValidator-AT5OYZFC.js +142 -0
  254. package/dist/commandValidator-DH3CX2OW.js +140 -0
  255. package/dist/commandValidator-GCQC7H4A.js +140 -0
  256. package/dist/commandValidator-K6VWB6O3.js +140 -0
  257. package/dist/commandValidator-L6WNDBYB.js +129 -0
  258. package/dist/commandValidator-O3KSNXD2.js +140 -0
  259. package/dist/commandValidator-ZHMUA5RQ.js +140 -0
  260. package/dist/constraints-M52FVL2X.js +11 -0
  261. package/dist/dist-CSOR2BL2.js +1144 -0
  262. package/dist/dist-PKOIS5NZ.js +1144 -0
  263. package/dist/fileAnalysis-3VMDDJ6I.js +9 -0
  264. package/dist/fileAnalysis-4QLHUT44.js +9 -0
  265. package/dist/fileAnalysis-H6M2Z7ZC.js +9 -0
  266. package/dist/fileAnalysis-HMI7IL6S.js +9 -0
  267. package/dist/fileAnalysis-JHABOPUQ.js +9 -0
  268. package/dist/gateMapping-E5MGNJH5.js +17 -0
  269. package/dist/jsonEnvelope-R4SWKX2N.js +62 -0
  270. package/dist/mergeTreeSimulator-ATOPJ3DU.js +11 -0
  271. package/dist/mergeTreeSimulator-AYUK4TZT.js +11 -0
  272. package/dist/mergeTreeSimulator-BBWJUQBK.js +11 -0
  273. package/dist/mergeTreeSimulator-DJJDRB5N.js +11 -0
  274. package/dist/mergeTreeSimulator-X4BA647P.js +11 -0
  275. package/dist/planDiff-37QHCPKO.js +109 -0
  276. package/dist/planDiff-BQHIUARB.js +109 -0
  277. package/dist/planDiff-QOK6KNB7.js +111 -0
  278. package/dist/planDiff-RXR4CWFS.js +109 -0
  279. package/dist/planDiff-W2BTH2MU.js +109 -0
  280. package/dist/planHistory-4J3Q6AJ3.js +126 -0
  281. package/dist/planHistory-DQRSB2Y7.js +118 -0
  282. package/dist/planHistory-GLCXP6AB.js +126 -0
  283. package/dist/planHistory-SMNRLEKG.js +126 -0
  284. package/dist/planHistory-UO4WZ6GO.js +126 -0
  285. package/dist/planReview-7BWVLABC.js +377 -0
  286. package/dist/planReview-7VB3OYKZ.js +385 -0
  287. package/dist/planReview-FAIBIAE6.js +377 -0
  288. package/dist/planReview-FXQBDNKJ.js +376 -0
  289. package/dist/planReview-HO4YYETA.js +377 -0
  290. package/dist/planReview-I26EKCUK.js +376 -0
  291. package/dist/planReview-JBOAJHSU.js +377 -0
  292. package/dist/planReview-SCNZWC6B.js +376 -0
  293. package/dist/planReview-TU7LMZIY.js +376 -0
  294. package/dist/planViewer-2YZCPVDM.js +155 -0
  295. package/dist/planViewer-72WZFUTU.js +154 -0
  296. package/dist/planViewer-G546TVHV.js +154 -0
  297. package/dist/planViewer-I7ZHNJQF.js +150 -0
  298. package/dist/planViewer-IRXHOY5U.js +155 -0
  299. package/dist/planViewer-IX2ICW45.js +154 -0
  300. package/dist/planViewer-PDWPUOP6.js +155 -0
  301. package/dist/planViewer-PEOADAGZ.js +155 -0
  302. package/dist/planViewer-PFYDEG6V.js +150 -0
  303. package/dist/planViewer-UIPOSRVW.js +151 -0
  304. package/dist/planViewer-V2JUKV7Q.js +154 -0
  305. package/dist/sarif-46TKOOJZ.js +9 -0
  306. package/dist/sarif-63JKTFFI.js +9 -0
  307. package/dist/sarif-CIYIWUNC.js +9 -0
  308. package/dist/sarif-OGAGDL6B.js +9 -0
  309. package/dist/sarif-XIREI5B5.js +9 -0
  310. package/dist/security-3V6FKJDA.js +423 -0
  311. package/dist/security-4JMEUM56.js +423 -0
  312. package/dist/security-QHPEWY5G.js +423 -0
  313. package/dist/security-V2LAL5TP.js +415 -0
  314. package/dist/security-WTASK6T6.js +423 -0
  315. package/dist/security-XE4GHVJD.js +423 -0
  316. package/dist/security-XLXM3UHT.js +423 -0
  317. package/dist/security-YDLHSMVY.js +441 -0
  318. package/dist/security-ZDAEZF7D.js +423 -0
  319. package/dist/signing-3EI734L4.js +14 -0
  320. package/dist/signing-5G7K6JXJ.js +14 -0
  321. package/dist/signing-7DK7SABM.js +14 -0
  322. package/dist/signing-JJJOUGCW.js +14 -0
  323. package/dist/signing-OAJ3MXGA.js +14 -0
  324. package/dist/verify-5F6PUXUQ.js +62 -0
  325. package/dist/verify-5ILURHV2.js +62 -0
  326. package/dist/verify-MRDZJUGO.js +62 -0
  327. package/dist/verify-SCUHB3SA.js +62 -0
  328. package/dist/verify-YZRHN2D3.js +62 -0
  329. package/docs/1.0.0-vertical-slice.md +214 -0
  330. package/docs/ADR-007-INTEGRATION-SUMMARY.md +232 -0
  331. package/docs/ALIASING_FOR_LEXRUNNER.md +709 -0
  332. package/docs/ALIASING_FOR_RUNNER.md +552 -0
  333. package/docs/AX.md +317 -0
  334. package/docs/CHECKPOINT_RESUME.md +208 -0
  335. package/docs/CLI_VERBS.md +219 -0
  336. package/docs/CONFLICT_DETECTION.md +198 -0
  337. package/docs/DISCIPLINED_FAILURE.md +224 -0
  338. package/docs/ENVIRONMENT_QUALITY.md +155 -0
  339. package/docs/ERROR_CODES.md +528 -0
  340. package/docs/EVENT_SCHEMA.md +659 -0
  341. package/docs/EXE-012-investigation-summary.md +300 -0
  342. package/docs/GATE_ATTESTATION_GUIDE.md +237 -0
  343. package/docs/JSON_OUTPUT_SCHEMAS.md +347 -0
  344. package/docs/LEXRUNNER_ALIASING.md +444 -0
  345. package/docs/LEX_INTEGRATION.md +83 -0
  346. package/docs/LEX_PUBLIC_API.md +306 -0
  347. package/docs/LICENSING.md +119 -0
  348. package/docs/MCP-CLI-PARITY.md +410 -0
  349. package/docs/MCP-MIGRATION.md +258 -0
  350. package/docs/MCP-PARITY.md +234 -0
  351. package/docs/MEMORY_TOOLS.md +278 -0
  352. package/docs/MERGE_WEAVE_SETUP.md +643 -0
  353. package/docs/MIGRATION_v0.1.md +760 -0
  354. package/docs/NAMING_CONVENTIONS.md +82 -0
  355. package/docs/PERSONA_FOUNDATION.md +124 -0
  356. package/docs/PHASE3_MEMORY_GUIDE.md +122 -0
  357. package/docs/PLAN_LOCK.md +114 -0
  358. package/docs/README.md +289 -0
  359. package/docs/RUNNER_LIFECYCLE.md +257 -0
  360. package/docs/SAFETY_MECHANISMS.md +325 -0
  361. package/docs/SECURITY_IMPLEMENTATION.md +535 -0
  362. package/docs/TERMS.md +34 -0
  363. package/docs/TOKEN_TRACKING.md +162 -0
  364. package/docs/WORKFLOW_GUIDANCE.md +277 -0
  365. package/docs/adr/ADR-000-product-naming-and-branding.md +115 -0
  366. package/docs/adr/ADR-001-plan-json-frozen-input.md +68 -0
  367. package/docs/adr/ADR-002-two-track-separation.md +84 -0
  368. package/docs/adr/ADR-003-gate-uniform-execution.md +69 -0
  369. package/docs/adr/ADR-004-runner-state-model.md +75 -0
  370. package/docs/adr/ADR-005-merge-pyramid-ordering.md +87 -0
  371. package/docs/adr/ADR-006-schema-versioning-semver.md +81 -0
  372. package/docs/adr/ADR-007-task-snapshot-contract.md +503 -0
  373. package/docs/adr/ADR-008-lex-packaging.md +243 -0
  374. package/docs/adr/ADR-009-ax-test-output-adapters.md +440 -0
  375. package/docs/adr/README.md +32 -0
  376. package/docs/advanced-cli.md +436 -0
  377. package/docs/agent-stall-detection.md +278 -0
  378. package/docs/architecture/executors.md +190 -0
  379. package/docs/architecture.md +316 -0
  380. package/docs/attestation/AX-SHARED-PLEDGE.md +83 -0
  381. package/docs/attestation/AX-SHARED-PLEDGE_v1.0.0.md +99 -0
  382. package/docs/attestation/AX-SHARED-PLEDGE_v1.0.0_VERIFICATION.md +115 -0
  383. package/docs/attestation/Lex_Guff_Version_Contract_Pact_v1.0.0.md +181 -0
  384. package/docs/attestation/README.md +87 -0
  385. package/docs/attestation/ax_pledge_2025-12-02.ots +0 -0
  386. package/docs/attestation/ax_pledge_timestamp_response.tsr +0 -0
  387. package/docs/attestation/copilot_summarization_2025-12-01.ots +0 -0
  388. package/docs/attestation/copilot_summarization_2025-12-01_VERIFICATION.md +100 -0
  389. package/docs/attestation/copilot_summarization_behavior_observation_2025-12-01.md +85 -0
  390. package/docs/attestation/copilot_summarization_screenshot_2025-12-01.png +0 -0
  391. package/docs/attestation/employment_separation_2025-11-26.ots +0 -0
  392. package/docs/attestation/employment_timestamp_response.tsr +0 -0
  393. package/docs/attestation/freetsa_cacert.pem +45 -0
  394. package/docs/attestation/freetsa_tsa.crt +45 -0
  395. package/docs/attestation/lex_employment_separation_2025-11-26.md +85 -0
  396. package/docs/attestation/lex_employment_separation_2025-11-26_VERIFICATION.md +126 -0
  397. package/docs/attestation/patent/2025-12-07-shadow-governance-pct-draft.md +350 -0
  398. package/docs/attestation/patent/2025-12-07-shadow-governance-pct-draft.md.ots +0 -0
  399. package/docs/attestation/patent/2025-12-07-shadow-governance-pct-draft_VERIFICATION.md +130 -0
  400. package/docs/attestation/patent/README.md +75 -0
  401. package/docs/attestation/patent/fig1_write_path.svg +58 -0
  402. package/docs/attestation/patent/fig2_read_normalize_rollup.svg +92 -0
  403. package/docs/attestation/timestamp_response.tsr +0 -0
  404. package/docs/attribution-README.md +264 -0
  405. package/docs/audit-compliance.md +283 -0
  406. package/docs/audit-outputs.md +1213 -0
  407. package/docs/audit-sdk.md +1134 -0
  408. package/docs/autopilot-levels.md +368 -0
  409. package/docs/autopilot.md +288 -0
  410. package/docs/ci-cd-integration.md +580 -0
  411. package/docs/ci-integration-guide.md +369 -0
  412. package/docs/ci-version-validation.md +198 -0
  413. package/docs/cli-mcp-weave-reporting.md +462 -0
  414. package/docs/cli.md +2262 -0
  415. package/docs/cluster-gates-rollback.md +222 -0
  416. package/docs/command-creation-guide.md +485 -0
  417. package/docs/command-whitelist.md +490 -0
  418. package/docs/commands/idea.md +253 -0
  419. package/docs/config.md +245 -0
  420. package/docs/conflict-clustering.md +225 -0
  421. package/docs/conflict-predictor.md +359 -0
  422. package/docs/context-diet.md +249 -0
  423. package/docs/counter-examples.md +199 -0
  424. package/docs/create-project.md +211 -0
  425. package/docs/deliverables-generator.md +299 -0
  426. package/docs/deliverables-management.md +474 -0
  427. package/docs/dependency-parser.md +354 -0
  428. package/docs/determinism.md +299 -0
  429. package/docs/diffgraph-planner.md +1211 -0
  430. package/docs/dogfood/README.md +33 -0
  431. package/docs/dogfood/wave-3-results.md +303 -0
  432. package/docs/dogfood-merge-weave-script.md +224 -0
  433. package/docs/enterprise-onboarding.md +291 -0
  434. package/docs/environment-variables.md +625 -0
  435. package/docs/error-recovery.md +466 -0
  436. package/docs/errors.md +288 -0
  437. package/docs/executor-authoring.md +854 -0
  438. package/docs/executor-decoupling.md +410 -0
  439. package/docs/front-end-capture-pipeline.md +312 -0
  440. package/docs/gate-report-examples.md +380 -0
  441. package/docs/gates.md +319 -0
  442. package/docs/github-automation.md +128 -0
  443. package/docs/governance-metrics.md +368 -0
  444. package/docs/integrations/README.md +588 -0
  445. package/docs/interactive-plan-review.md +493 -0
  446. package/docs/issue-orchestration.md +256 -0
  447. package/docs/lex_ax_session_key_rememberings_v0.1.md +195 -0
  448. package/docs/lexrunner-v1-summary.md +246 -0
  449. package/docs/lexrunner-v2-contract.md +404 -0
  450. package/docs/lexrunner-v2-migration-plan.md +388 -0
  451. package/docs/lexrunner-v2-salvage-map.md +355 -0
  452. package/docs/lexsona-rules.md +154 -0
  453. package/docs/merge-weave-analysis.md +403 -0
  454. package/docs/merge-weave-quickstart.md +770 -0
  455. package/docs/merge-weave-state-machine.md +390 -0
  456. package/docs/migration-guide.md +529 -0
  457. package/docs/monitoring-examples.md +470 -0
  458. package/docs/monitoring-implementation.md +252 -0
  459. package/docs/orchestration.md +234 -0
  460. package/docs/performance-scale.md +359 -0
  461. package/docs/plan-generation.md +407 -0
  462. package/docs/profile-resolution.md +455 -0
  463. package/docs/prompts.md +427 -0
  464. package/docs/quickstart.md +546 -0
  465. package/docs/release-process.md +310 -0
  466. package/docs/sample-prompts/merge-weave/cli-merge-weave-kickoff.md +274 -0
  467. package/docs/sample-prompts/merge-weave/mcp-merge-weave-kickoff.md +480 -0
  468. package/docs/sample-prompts/merge-weave/standalone-merge-weave-kickoff.md +237 -0
  469. package/docs/schemas.md +359 -0
  470. package/docs/scope-validation.md +444 -0
  471. package/docs/security/rotation-guide.md +325 -0
  472. package/docs/specs/Meeting_Control_Stack_Concept_v0.1.0.md +417 -0
  473. package/docs/specs/git-feature-flag-redesign.md +321 -0
  474. package/docs/specs/lex-pr-brief-behavior.md +269 -0
  475. package/docs/specs/smartergpt-structure-v1.md +705 -0
  476. package/docs/specs/task-brief-v0.1.md +224 -0
  477. package/docs/store-architecture.md +61 -0
  478. package/docs/templates/CONTRIBUTING-merge-weave-section.md +33 -0
  479. package/docs/templates/gates.example.yml +109 -0
  480. package/docs/templates/plan.example.json +77 -0
  481. package/docs/thesis/00-EVOLUTION-NOTES.md +383 -0
  482. package/docs/thesis/01-CORE-THESIS.md +285 -0
  483. package/docs/thesis/02-TURN-COST.md +498 -0
  484. package/docs/thesis/03-PERMISSION-TO-FAIL.md +581 -0
  485. package/docs/thesis/04-CROSS-MODEL-CONTINUITY.md +517 -0
  486. package/docs/thesis/05-RULE-FILE-SPEC.md +732 -0
  487. package/docs/thesis/06-CAPABILITY-TIERS.md +723 -0
  488. package/docs/thesis/07-ROBERT-FIELD-REPORT.md +433 -0
  489. package/docs/thesis/08-IMPLEMENTATION-GUIDE.md +1093 -0
  490. package/docs/thesis/09-METRICS-AND-TELEMETRY.md +793 -0
  491. package/docs/thesis/10-FAILURE-MODES.md +716 -0
  492. package/docs/thesis/README.md +151 -0
  493. package/docs/thesis/lex_governance-collab_systems_paper_draft.md +952 -0
  494. package/docs/thesis/lex_governance-collab_systems_paper_draft.pdf +0 -0
  495. package/docs/tool-grounded/READINESS_ANALYSIS.md +527 -0
  496. package/docs/tool-grounded/enforcement.md +361 -0
  497. package/docs/tool-grounded/tool-grounded-a-view-from-the-inside.md +437 -0
  498. package/docs/tool-grounded/tool-grounded-prompt.md +122 -0
  499. package/docs/tool-grounded/tool-grounded-run-centric.md +474 -0
  500. package/docs/troubleshooting-planner.md +910 -0
  501. package/docs/troubleshooting.md +745 -0
  502. package/docs/tutorials/README.md +201 -0
  503. package/docs/tutorials/diffgraph-planner/01-simple-stack.md +460 -0
  504. package/docs/tutorials/diffgraph-planner/02-diamond-pattern.md +431 -0
  505. package/docs/tutorials/diffgraph-planner/03-large-batch.md +525 -0
  506. package/docs/tutorials/diffgraph-planner/04-fixing-cycles.md +526 -0
  507. package/docs/tutorials/diffgraph-planner/05-hybrid-workflow.md +555 -0
  508. package/docs/tutorials/quick-merge-pyramid.md +364 -0
  509. package/docs/tutorials/video-scripts/01-getting-started.md +286 -0
  510. package/docs/tutorials/video-scripts/02-understanding-dependencies.md +376 -0
  511. package/docs/weave-contract.md +116 -0
  512. package/docs/weave-execution-log.md +153 -0
  513. package/docs/workflows/README.md +139 -0
  514. package/docs/workflows/enterprise.md +545 -0
  515. package/docs/workflows/small-team.md +398 -0
  516. package/docs/workflows/solo-developer.md +419 -0
  517. package/dogfood-merge-weave.sh +122 -0
  518. package/examples/README.md +22 -0
  519. package/examples/WORKING_EXAMPLE.md +309 -0
  520. package/examples/analyze-pr-files.js +100 -0
  521. package/examples/autopilot-level4-example.md +234 -0
  522. package/examples/cluster-gates-demo.sh +178 -0
  523. package/examples/complete-security-workflow.ts +248 -0
  524. package/examples/error-recovery/README.md +202 -0
  525. package/examples/executor-manifest.example.yaml +81 -0
  526. package/examples/front-end-capture-pipeline/README.md +99 -0
  527. package/examples/front-end-capture-pipeline/create-project-example.sh +83 -0
  528. package/examples/front-end-capture-pipeline/idea-dark-mode.json +14 -0
  529. package/examples/front-end-capture-pipeline/idea-example.sh +57 -0
  530. package/examples/front-end-capture-pipeline/manual-test-checklist.md +426 -0
  531. package/examples/gates/README.md +165 -0
  532. package/examples/gates/lint-gate.sh +40 -0
  533. package/examples/gates/lint-gate.ts +99 -0
  534. package/examples/gates/test-runner.ts +113 -0
  535. package/examples/gates/vuln-scanner.ts +95 -0
  536. package/examples/github-integration/README.md +111 -0
  537. package/examples/github-integration/example-plan.json +95 -0
  538. package/examples/performance-config.md +388 -0
  539. package/examples/profile-setup/.gitignore.template +66 -0
  540. package/examples/profile-setup/.smartergpt-example/README.md +190 -0
  541. package/examples/profile-setup/.smartergpt.local-example/README.md +365 -0
  542. package/examples/profile-setup/README.md +492 -0
  543. package/examples/profile-setup/cross-repo-prompts/README.md +606 -0
  544. package/examples/safety-framework-demo.ts +130 -0
  545. package/examples/safety-mechanisms-example.ts +191 -0
  546. package/examples/sample-plan.json +87 -0
  547. package/examples/sample-stack.yml +66 -0
  548. package/examples/sarif/README.md +224 -0
  549. package/examples/scope-validation-demo.ts +199 -0
  550. package/examples/security-integration.ts +293 -0
  551. package/examples/token-tracking-example.ts +71 -0
  552. package/executors/senior-dev/ARCHITECTURE.md +182 -0
  553. package/executors/senior-dev/MEMORY_INTEGRATION.md +236 -0
  554. package/executors/senior-dev/QUICK_START.md +145 -0
  555. package/executors/senior-dev/README.md +76 -0
  556. package/executors/senior-dev/examples/sample-review-session.md +228 -0
  557. package/executors/senior-dev/executor-manifest.yaml +79 -0
  558. package/executors/senior-dev/prompts/code-review.prompt.md +78 -0
  559. package/executors/senior-dev/prompts/mentorship-feedback.prompt.md +97 -0
  560. package/executors/senior-dev/prompts/pattern-recognition.prompt.md +80 -0
  561. package/executors/senior-dev/prompts/pr-analysis.prompt.md +75 -0
  562. package/executors/senior-dev/scripts/capture-review-frame.sh +129 -0
  563. package/executors/senior-dev/scripts/prepare-review-context.sh +61 -0
  564. package/executors/senior-dev/scripts/recall-context.sh +87 -0
  565. package/lexrunner-launcher.sh +12 -0
  566. package/mcp-config-example.json +14 -0
  567. package/mcp-server.mjs +1221 -0
  568. package/merge-weave-current-prs.md +170 -0
  569. package/merge-weave-dogfood.json +46 -0
  570. package/merge-weave-plan.json +56 -0
  571. package/package.json +140 -0
  572. package/procedures/merge-weave-main.yaml +90 -0
  573. package/procedures/pr-review.yaml +68 -0
  574. package/project/README.md +50 -0
  575. package/prompts/tool-grounded-mode.md +185 -0
  576. package/schemas/allowed-commands.schema.json +108 -0
  577. package/schemas/audit-events.schema.json +138 -0
  578. package/schemas/audit-events.v1.0.0.schema.json +138 -0
  579. package/schemas/edit-plan.schema.json +80 -0
  580. package/schemas/executor-manifest.schema.json +236 -0
  581. package/schemas/flake-report.schema.json +95 -0
  582. package/schemas/gate-report.schema.json +85 -0
  583. package/schemas/gates/build.schema.json +32 -0
  584. package/schemas/gates/coverage.schema.json +42 -0
  585. package/schemas/gates/lint.schema.json +34 -0
  586. package/schemas/gates/security-scan.schema.json +33 -0
  587. package/schemas/gates/test.schema.json +35 -0
  588. package/schemas/next-option.schema.json +60 -0
  589. package/schemas/persona-snapshot.schema.json +66 -0
  590. package/schemas/plan.schema.json +300 -0
  591. package/schemas/status-response.schema.json +193 -0
  592. package/scripts/README.md +354 -0
  593. package/scripts/analyze-governance-logs.mjs +51 -0
  594. package/scripts/benchmark-ci.ts +339 -0
  595. package/scripts/check-determinism.sh +23 -0
  596. package/scripts/check-license-compliance.mjs +319 -0
  597. package/scripts/check-release-drift.mjs +81 -0
  598. package/scripts/ci-debug.sh +24 -0
  599. package/scripts/ci-smoke.mjs +304 -0
  600. package/scripts/create-sample-repo.sh +245 -0
  601. package/scripts/dogfood-merge-weave.sh +552 -0
  602. package/scripts/gen_mcp_servers.py +252 -0
  603. package/scripts/generate-executor-manifest-schema.ts +30 -0
  604. package/scripts/generate-flake-schema.ts +32 -0
  605. package/scripts/generate-gate-schema.ts +32 -0
  606. package/scripts/generate-plan-schema.ts +30 -0
  607. package/scripts/generate-run-schemas.ts +69 -0
  608. package/scripts/load-prompt.mjs +147 -0
  609. package/scripts/merge-weave-wrapper.sh +445 -0
  610. package/scripts/merge-weave.sh +489 -0
  611. package/scripts/metrics-template.ts +134 -0
  612. package/scripts/package-lex.sh +267 -0
  613. package/scripts/quick-start-merge-weave.sh +218 -0
  614. package/scripts/release-prepare.ts +350 -0
  615. package/scripts/rotate-secrets-example.ts +134 -0
  616. package/scripts/test-lexsona-shadow.mjs +100 -0
  617. package/scripts/validate-manifests.ts +188 -0
  618. package/scripts/verify-audit-phase2.js +175 -0
  619. package/src/ai/README.md +456 -0
  620. package/src/ai/conflictStrategy.ts +223 -0
  621. package/src/ai/conflictStrategyCache.ts +164 -0
  622. package/src/ai/conflictStrategyPrompt.ts +128 -0
  623. package/src/ai/conflictStrategySchema.ts +165 -0
  624. package/src/ai/heuristicFallback.ts +162 -0
  625. package/src/ai/index.ts +64 -0
  626. package/src/ai/riskScoring.ts +174 -0
  627. package/src/aliases/index.ts +16 -0
  628. package/src/aliases/resolver.ts +212 -0
  629. package/src/audit/context.ts +284 -0
  630. package/src/audit/emitter.ts +685 -0
  631. package/src/audit/events.ts +210 -0
  632. package/src/audit/gateMatrix.ts +158 -0
  633. package/src/audit/index.ts +44 -0
  634. package/src/audit/manifest.ts +78 -0
  635. package/src/audit/profiles.ts +93 -0
  636. package/src/audit/redaction.ts +216 -0
  637. package/src/audit/sarif.ts +213 -0
  638. package/src/audit/schema/events.ts +366 -0
  639. package/src/audit/schema/manifest.ts +47 -0
  640. package/src/audit/schema.ts +159 -0
  641. package/src/audit/sdk/index.ts +145 -0
  642. package/src/audit/sdk/types.ts +88 -0
  643. package/src/audit/sidecar.ts +111 -0
  644. package/src/audit/signing.ts +521 -0
  645. package/src/autopilot/README.md +113 -0
  646. package/src/autopilot/artifacts.ts +287 -0
  647. package/src/autopilot/base.ts +132 -0
  648. package/src/autopilot/deliverables.ts +392 -0
  649. package/src/autopilot/index.ts +29 -0
  650. package/src/autopilot/level1.ts +187 -0
  651. package/src/autopilot/level2.ts +262 -0
  652. package/src/autopilot/level3.ts +263 -0
  653. package/src/autopilot/level4.ts +393 -0
  654. package/src/autopilot/safety/README.md +512 -0
  655. package/src/autopilot/safety/SafetyFramework.ts +634 -0
  656. package/src/autopilot/safety/index.ts +16 -0
  657. package/src/autopilot/types.ts +250 -0
  658. package/src/budget/index.ts +56 -0
  659. package/src/budget/manager.ts +547 -0
  660. package/src/budget/schema.ts +305 -0
  661. package/src/budget/tracker.ts +155 -0
  662. package/src/cache/issue-cache.ts +150 -0
  663. package/src/cli/command-map.ts +221 -0
  664. package/src/cli/commands/gate/test.ts +214 -0
  665. package/src/cli/exitHandler.ts +98 -0
  666. package/src/cli/flags.ts +123 -0
  667. package/src/cli/formatSuggestions.ts +202 -0
  668. package/src/cli/formatters.ts +294 -0
  669. package/src/cli/jsonEnvelope.ts +152 -0
  670. package/src/cli/output.ts +61 -0
  671. package/src/cli/runnerLifecycle.ts +118 -0
  672. package/src/cli-audit.ts +76 -0
  673. package/src/cli-security.ts +114 -0
  674. package/src/cli.ts +1231 -0
  675. package/src/commands/audit/index.ts +5 -0
  676. package/src/commands/audit/verify.ts +87 -0
  677. package/src/commands/autopilot.ts +131 -0
  678. package/src/commands/budget.ts +327 -0
  679. package/src/commands/bulkOps.ts +204 -0
  680. package/src/commands/completion.ts +287 -0
  681. package/src/commands/config/validate.ts +428 -0
  682. package/src/commands/config.ts +368 -0
  683. package/src/commands/counterExamples.ts +104 -0
  684. package/src/commands/create-project.ts +338 -0
  685. package/src/commands/discover.ts +192 -0
  686. package/src/commands/doctor.ts +436 -0
  687. package/src/commands/execute.ts +558 -0
  688. package/src/commands/explain.ts +157 -0
  689. package/src/commands/fanout-analyze.ts +684 -0
  690. package/src/commands/fanout-harvest.ts +328 -0
  691. package/src/commands/fanout-monitor.ts +224 -0
  692. package/src/commands/gateAttest.ts +95 -0
  693. package/src/commands/gateImport.ts +142 -0
  694. package/src/commands/gateImportChecks.ts +208 -0
  695. package/src/commands/gateReport.ts +184 -0
  696. package/src/commands/governanceCleanup.ts +171 -0
  697. package/src/commands/governanceReport.ts +497 -0
  698. package/src/commands/guards.ts +50 -0
  699. package/src/commands/idea.ts +281 -0
  700. package/src/commands/init.ts +414 -0
  701. package/src/commands/issues.ts +165 -0
  702. package/src/commands/merge.ts +677 -0
  703. package/src/commands/mergeOrder.ts +68 -0
  704. package/src/commands/metrics.ts +232 -0
  705. package/src/commands/migrateProfile.ts +187 -0
  706. package/src/commands/orchestrate/analyze-issues.ts +203 -0
  707. package/src/commands/orchestrate/assign-batch.ts +204 -0
  708. package/src/commands/orchestrate/generate-deliverables.ts +66 -0
  709. package/src/commands/orchestrate/pinToolchain.ts +102 -0
  710. package/src/commands/orchestrate/plan-batch.ts +119 -0
  711. package/src/commands/orchestrate/predict-conflicts.ts +210 -0
  712. package/src/commands/orchestrate.ts +186 -0
  713. package/src/commands/plan.ts +403 -0
  714. package/src/commands/planDiff.ts +56 -0
  715. package/src/commands/planReview.ts +112 -0
  716. package/src/commands/planViewer.ts +180 -0
  717. package/src/commands/preview-constraints.ts +97 -0
  718. package/src/commands/query.ts +313 -0
  719. package/src/commands/report.ts +56 -0
  720. package/src/commands/retry.ts +60 -0
  721. package/src/commands/schema.ts +128 -0
  722. package/src/commands/security.ts +140 -0
  723. package/src/commands/seniorDev.ts +326 -0
  724. package/src/commands/status.ts +97 -0
  725. package/src/commands/tokenReport.ts +167 -0
  726. package/src/commands/validation.ts +66 -0
  727. package/src/commands/weave-checkpoints.ts +145 -0
  728. package/src/commands/weave-fanout.ts +273 -0
  729. package/src/commands/weave-policy.ts +277 -0
  730. package/src/commands/weave.ts +518 -0
  731. package/src/config/localOverlay.ts +167 -0
  732. package/src/config/pathResolver.ts +106 -0
  733. package/src/config/profileResolver.ts +194 -0
  734. package/src/config/promptsResolver.ts +312 -0
  735. package/src/config/rulesResolver.ts +257 -0
  736. package/src/config/schemas.ts +142 -0
  737. package/src/core/bootstrap.ts +287 -0
  738. package/src/core/enterprise.ts +453 -0
  739. package/src/core/errorRecovery.ts +509 -0
  740. package/src/core/githubPlan.ts +282 -0
  741. package/src/core/inputs.ts +314 -0
  742. package/src/core/multiRepoPlan.ts +353 -0
  743. package/src/core/plan.ts +106 -0
  744. package/src/core/snapshot.ts +189 -0
  745. package/src/errors/adapters.ts +897 -0
  746. package/src/errors/index.ts +231 -0
  747. package/src/executionState.ts +356 -0
  748. package/src/executors/README_FRAME_CONTRACT.md +446 -0
  749. package/src/executors/frameContract.ts +270 -0
  750. package/src/executors/guardrailEnforcement.ts +294 -0
  751. package/src/executors/seniorDev/core.ts +548 -0
  752. package/src/executors/seniorDev/index.ts +30 -0
  753. package/src/executors/seniorDev/types.ts +176 -0
  754. package/src/executors/toolBudget.ts +194 -0
  755. package/src/fanout/analyzer.ts +735 -0
  756. package/src/fanout/github-adapter.ts +262 -0
  757. package/src/fanout/harvest.ts +517 -0
  758. package/src/fanout/monitor.ts +350 -0
  759. package/src/fanout/types.ts +428 -0
  760. package/src/frames/controller.ts +160 -0
  761. package/src/frames/emitter.ts +455 -0
  762. package/src/frames/index.ts +58 -0
  763. package/src/frames/storage.ts +203 -0
  764. package/src/frames/types.ts +258 -0
  765. package/src/gates/checkRunConverter.ts +91 -0
  766. package/src/gates/test/adapters/errors.ts +32 -0
  767. package/src/gates/test/adapters/index.ts +36 -0
  768. package/src/gates/test/adapters/interface.ts +63 -0
  769. package/src/gates/test/adapters/jest-json.ts +370 -0
  770. package/src/gates/test/adapters/junit-xml.ts +400 -0
  771. package/src/gates/test/adapters/registry.ts +149 -0
  772. package/src/gates/test/adapters/vitest-json.ts +339 -0
  773. package/src/gates/test/enrichment/failureId.ts +74 -0
  774. package/src/gates/test/enrichment/index.ts +25 -0
  775. package/src/gates/test/enrichment/nextActions.ts +322 -0
  776. package/src/gates/test/enrichment/rerunTemplates.ts +105 -0
  777. package/src/gates/test/enrichment/signature.ts +58 -0
  778. package/src/gates/test/enrichment/stackParser.ts +149 -0
  779. package/src/gates/test/enrichment/types.ts +67 -0
  780. package/src/gates/test/formatters/markdown.spec.ts +942 -0
  781. package/src/gates/test/formatters/markdown.ts +296 -0
  782. package/src/gates/test/index.ts +54 -0
  783. package/src/gates/test/schema.spec.ts +372 -0
  784. package/src/gates/test/schema.ts +327 -0
  785. package/src/gates/validator.ts +92 -0
  786. package/src/gates.ts +1022 -0
  787. package/src/git/operations.ts +592 -0
  788. package/src/git/parseRemote.ts +22 -0
  789. package/src/github/api.ts +584 -0
  790. package/src/github/batch-ops.ts +215 -0
  791. package/src/github/client.ts +647 -0
  792. package/src/github/contextDiet.ts +205 -0
  793. package/src/github/diffHunks.ts +285 -0
  794. package/src/github/index.ts +11 -0
  795. package/src/github/minimalContext.ts +212 -0
  796. package/src/github/minimalContextClient.ts +105 -0
  797. package/src/github/symbolMap.ts +370 -0
  798. package/src/github/types.ts +166 -0
  799. package/src/governance/index.ts +42 -0
  800. package/src/governance/mcpStatus.ts +258 -0
  801. package/src/governance/timeoutAdjustment.ts +149 -0
  802. package/src/governance/turnCostSummary.ts +182 -0
  803. package/src/hooks/events.ts +374 -0
  804. package/src/hooks/index.ts +8 -0
  805. package/src/hostility/checks.ts +408 -0
  806. package/src/hostility/index.ts +108 -0
  807. package/src/hostility/score.ts +143 -0
  808. package/src/interactive/planDiff.ts +168 -0
  809. package/src/interactive/planHistory.ts +205 -0
  810. package/src/interactive/planReview.ts +531 -0
  811. package/src/learning/counter-example.ts +174 -0
  812. package/src/learning/prompts.ts +107 -0
  813. package/src/learning/storage.ts +230 -0
  814. package/src/lexsona/client.ts +367 -0
  815. package/src/lexsona/index.ts +44 -0
  816. package/src/lexsona/logger.ts +408 -0
  817. package/src/lexsona/types.ts +177 -0
  818. package/src/mcp/DEPRECATED.md +33 -0
  819. package/src/mcp/server.ts +3587 -0
  820. package/src/mcp/types/guided-response.ts +95 -0
  821. package/src/mcp/types.ts +468 -0
  822. package/src/mcp/workflow/state-machine.ts +277 -0
  823. package/src/mergeEligibility.ts +355 -0
  824. package/src/mergeOrder.ts +170 -0
  825. package/src/metrics/export.ts +472 -0
  826. package/src/metrics/index.ts +35 -0
  827. package/src/metrics/turncost.ts +284 -0
  828. package/src/monitoring/README.md +222 -0
  829. package/src/monitoring/audit.ts +98 -0
  830. package/src/monitoring/cache.ts +121 -0
  831. package/src/monitoring/dashboards/grafana-dashboard.json +172 -0
  832. package/src/monitoring/errorRecovery.ts +334 -0
  833. package/src/monitoring/errors.ts +105 -0
  834. package/src/monitoring/fileLogger.ts +194 -0
  835. package/src/monitoring/hallucinations.ts +45 -0
  836. package/src/monitoring/health.ts +171 -0
  837. package/src/monitoring/index.ts +16 -0
  838. package/src/monitoring/lock.ts +158 -0
  839. package/src/monitoring/logger.ts +178 -0
  840. package/src/monitoring/metrics.ts +245 -0
  841. package/src/monitoring/profiler.ts +156 -0
  842. package/src/monitoring/tokenLogger.ts +141 -0
  843. package/src/orchestrate/analyzer.ts +461 -0
  844. package/src/orchestrate/index.ts +6 -0
  845. package/src/orchestrate/types.ts +65 -0
  846. package/src/orchestration/README.md +480 -0
  847. package/src/orchestration/agentAssigner.ts +206 -0
  848. package/src/orchestration/batchPlanner.ts +201 -0
  849. package/src/orchestration/conflictClustering.ts +344 -0
  850. package/src/orchestration/conflictGraph.ts +63 -0
  851. package/src/orchestration/conflictPredictor.ts +170 -0
  852. package/src/orchestration/deliverablesGenerator.ts +345 -0
  853. package/src/orchestration/determinism.ts +232 -0
  854. package/src/orchestration/index.ts +45 -0
  855. package/src/orchestration/mergeTreeSimulator.ts +137 -0
  856. package/src/orchestration/mis.ts +123 -0
  857. package/src/orchestration/toolchainManifest.ts +169 -0
  858. package/src/orchestration/types.ts +103 -0
  859. package/src/performance.README.md +99 -0
  860. package/src/performance.ts +279 -0
  861. package/src/planner/README.md +215 -0
  862. package/src/planner/dependencyParser.ts +404 -0
  863. package/src/planner/dependencyScoring.ts +346 -0
  864. package/src/planner/fileAnalysis.ts +693 -0
  865. package/src/planner/index.ts +41 -0
  866. package/src/planner/scopeValidator.ts +308 -0
  867. package/src/planner/types.ts +80 -0
  868. package/src/planner/validation.ts +493 -0
  869. package/src/preview/constraints.ts +333 -0
  870. package/src/procedures/index.ts +47 -0
  871. package/src/procedures/loader.ts +252 -0
  872. package/src/procedures/schema.ts +191 -0
  873. package/src/procedures/stateMachine.ts +160 -0
  874. package/src/procedures/types.ts +178 -0
  875. package/src/receipts/emit.ts +354 -0
  876. package/src/receipts/index.ts +48 -0
  877. package/src/receipts/schema.ts +227 -0
  878. package/src/report/aggregate.ts +160 -0
  879. package/src/runs/artifacts.ts +315 -0
  880. package/src/runs/attribution.ts +132 -0
  881. package/src/runs/context.ts +54 -0
  882. package/src/runs/decisions.ts +407 -0
  883. package/src/runs/enforcement.ts +395 -0
  884. package/src/runs/failures.ts +517 -0
  885. package/src/runs/index.ts +141 -0
  886. package/src/runs/manager.ts +910 -0
  887. package/src/runs/statusBuilder.ts +233 -0
  888. package/src/runs/storage.ts +290 -0
  889. package/src/runs/types.ts +216 -0
  890. package/src/schema/flakeReport.ts +74 -0
  891. package/src/schema/gateMapping.ts +107 -0
  892. package/src/schema/gateReport.ts +236 -0
  893. package/src/schema/weaveLock.ts +51 -0
  894. package/src/schema.ts +313 -0
  895. package/src/schemas/executorManifest.ts +204 -0
  896. package/src/schemas/feature-spec-v0.ts +40 -0
  897. package/src/schemas/persona.ts +162 -0
  898. package/src/schemas/project.ts +91 -0
  899. package/src/schemas/runCentric.ts +402 -0
  900. package/src/schemas/task-contract.ts +626 -0
  901. package/src/schemas/vacuumReadyPrompt.ts +128 -0
  902. package/src/sdk/index.ts +113 -0
  903. package/src/sdk/parser.ts +101 -0
  904. package/src/sdk/query.ts +315 -0
  905. package/src/sdk/validator.ts +114 -0
  906. package/src/security/README.md +496 -0
  907. package/src/security/authentication.ts +173 -0
  908. package/src/security/authorization.ts +348 -0
  909. package/src/security/commandValidator.ts +195 -0
  910. package/src/security/compliance.ts +688 -0
  911. package/src/security/index.ts +85 -0
  912. package/src/security/policy.ts +399 -0
  913. package/src/security/sarif.ts +179 -0
  914. package/src/security/scanning.ts +362 -0
  915. package/src/security/secrets.ts +520 -0
  916. package/src/shared/git/index.ts +30 -0
  917. package/src/shared/git/runGit.ts +281 -0
  918. package/src/shared/git/runtime.ts +66 -0
  919. package/src/snapshot/builder.ts +229 -0
  920. package/src/snapshot/index.ts +8 -0
  921. package/src/store/CONTRACT.md +189 -0
  922. package/src/store/README.md +22 -0
  923. package/src/store/index.ts +99 -0
  924. package/src/store/inmemory/index.ts +10 -0
  925. package/src/store/inmemory/run-store.ts +268 -0
  926. package/src/store/postgres/.gitkeep +0 -0
  927. package/src/store/run-store.ts +405 -0
  928. package/src/store/sqlite/index.ts +7 -0
  929. package/src/store/sqlite/run-store.ts +525 -0
  930. package/src/store/sqlite/schema.sql +67 -0
  931. package/src/telemetry/frames.ts +179 -0
  932. package/src/telemetry/index.ts +5 -0
  933. package/src/tiers/index.ts +34 -0
  934. package/src/tiers/metrics.ts +156 -0
  935. package/src/tiers/schema.ts +95 -0
  936. package/src/tiers/suggest.ts +183 -0
  937. package/src/types/guardrails.ts +452 -0
  938. package/src/types/index.ts +42 -0
  939. package/src/util/canonicalJson.ts +29 -0
  940. package/src/util/colorControl.ts +46 -0
  941. package/src/util/envUtils.ts +139 -0
  942. package/src/util/hash.ts +69 -0
  943. package/src/util/lockHash.ts +90 -0
  944. package/src/util/minHeap.ts +108 -0
  945. package/src/util/progress.ts +89 -0
  946. package/src/util/tokenEstimator.ts +55 -0
  947. package/src/utils/fingerprint.ts +105 -0
  948. package/src/utils/paths.ts +209 -0
  949. package/src/utils/tokens.ts +151 -0
  950. package/src/utils/validation.ts +53 -0
  951. package/src/verification/diff-applier.ts +60 -0
  952. package/src/verification/engine-verifier.ts +171 -0
  953. package/src/verification/errors.ts +30 -0
  954. package/src/verification/index.ts +13 -0
  955. package/src/weave/audit/index.ts +17 -0
  956. package/src/weave/audit/logger.ts +206 -0
  957. package/src/weave/authority/evaluator.ts +660 -0
  958. package/src/weave/authority/index.ts +30 -0
  959. package/src/weave/authority/schema.ts +292 -0
  960. package/src/weave/checkpoint/index.ts +7 -0
  961. package/src/weave/checkpoint/storage.ts +223 -0
  962. package/src/weave/checkpoint/types.ts +121 -0
  963. package/src/weave/checkpoint/utils.ts +207 -0
  964. package/src/weave/clusterGates.ts +366 -0
  965. package/src/weave/draftPR.ts +214 -0
  966. package/src/weave/executor/d1-executor.ts +822 -0
  967. package/src/weave/executor/d2-executor.ts +381 -0
  968. package/src/weave/executor/index.ts +24 -0
  969. package/src/weave/executor/types.ts +135 -0
  970. package/src/weave/fanout/generator.ts +186 -0
  971. package/src/weave/fanout/index.ts +51 -0
  972. package/src/weave/fanout/loader.ts +134 -0
  973. package/src/weave/fanout/matcher.ts +239 -0
  974. package/src/weave/fanout/schema.ts +178 -0
  975. package/src/weave/frameHelper.ts +126 -0
  976. package/src/weave/gateFailureHandler.ts +405 -0
  977. package/src/weave/index.ts +89 -0
  978. package/src/weave/lockFile.ts +193 -0
  979. package/src/weave/mergeHelpers.ts +377 -0
  980. package/src/weave/mergeWeaveSequential.ts +282 -0
  981. package/src/weave/metrics/calculator.ts +362 -0
  982. package/src/weave/metrics/index.ts +44 -0
  983. package/src/weave/metrics/logger.ts +291 -0
  984. package/src/weave/metrics/schema.ts +505 -0
  985. package/src/weave/planner/index.ts +23 -0
  986. package/src/weave/planner/planner.ts +411 -0
  987. package/src/weave/planner/types.ts +181 -0
  988. package/src/weave/policy/index.ts +63 -0
  989. package/src/weave/policy/loader.ts +148 -0
  990. package/src/weave/policy/schema.ts +290 -0
  991. package/src/weave/post-merge-checks.ts +220 -0
  992. package/src/weave/preflightConflicts.ts +375 -0
  993. package/src/weave/receiptHelper.ts +287 -0
  994. package/src/weave/recovery.ts +232 -0
  995. package/src/weave/resolutionGuidance.ts +173 -0
  996. package/src/weave/stateMachine.ts +426 -0
  997. package/src/weave/testfix/applier.ts +195 -0
  998. package/src/weave/testfix/index.ts +18 -0
  999. package/src/weave/testfix/loader.ts +116 -0
  1000. package/src/weave/testfix/matcher.ts +158 -0
  1001. package/src/weave/testfix/schema.ts +218 -0
  1002. package/src/weave/types.ts +305 -0
  1003. package/src/weave/utils/copilot-completion.ts +76 -0
  1004. package/test-mcp-dogfood.mjs +128 -0
  1005. package/test-mcp.mjs +116 -0
  1006. package/tests/README.md +155 -0
  1007. package/tests/advanced-cli-e2e.spec.ts +218 -0
  1008. package/tests/agentAssigner.spec.ts +261 -0
  1009. package/tests/ai-conflict-strategy-cache.spec.ts +254 -0
  1010. package/tests/ai-conflict-strategy-risk.spec.ts +287 -0
  1011. package/tests/ai-conflict-strategy-schema.spec.ts +252 -0
  1012. package/tests/ai-conflict-strategy.spec.ts +442 -0
  1013. package/tests/aliases/resolver.spec.ts +238 -0
  1014. package/tests/audit/context.spec.ts +283 -0
  1015. package/tests/audit/emitter.spec.ts +347 -0
  1016. package/tests/audit/gateMatrix.spec.ts +335 -0
  1017. package/tests/audit/integration.spec.ts +236 -0
  1018. package/tests/audit/redaction.spec.ts +290 -0
  1019. package/tests/audit/sarif-integration.spec.ts +303 -0
  1020. package/tests/audit/sarif.spec.ts +458 -0
  1021. package/tests/audit/schema-events.spec.ts +421 -0
  1022. package/tests/audit/schema.spec.ts +434 -0
  1023. package/tests/audit/sdk-integration.spec.ts +598 -0
  1024. package/tests/audit/sdk.spec.ts +318 -0
  1025. package/tests/audit/signing-integration.spec.ts +276 -0
  1026. package/tests/audit/signing.spec.ts +350 -0
  1027. package/tests/audit-signing.spec.ts +406 -0
  1028. package/tests/audit-verify-cli.spec.ts +176 -0
  1029. package/tests/autopilot-e2e-level3-4.spec.ts +741 -0
  1030. package/tests/autopilot-integration.spec.ts +274 -0
  1031. package/tests/autopilot-level1.spec.ts +449 -0
  1032. package/tests/autopilot-level2.spec.ts +188 -0
  1033. package/tests/autopilot-level3.spec.ts +266 -0
  1034. package/tests/autopilot-level4.spec.ts +454 -0
  1035. package/tests/autopilot.spec.ts +379 -0
  1036. package/tests/ax-error-adapters.spec.ts +580 -0
  1037. package/tests/batch-planner.spec.ts +500 -0
  1038. package/tests/benchmark-infrastructure.spec.ts +445 -0
  1039. package/tests/benchmarks/README.md +103 -0
  1040. package/tests/benchmarks/baselines/baseline.json +127 -0
  1041. package/tests/benchmarks/core/dependencyResolver.bench.ts +128 -0
  1042. package/tests/benchmarks/core/planParser.bench.ts +114 -0
  1043. package/tests/benchmarks/core/topologicalSort.bench.ts +102 -0
  1044. package/tests/benchmarks/index.ts +36 -0
  1045. package/tests/benchmarks/io/fileOperations.bench.ts +132 -0
  1046. package/tests/benchmarks/io/gitOperations.bench.ts +99 -0
  1047. package/tests/benchmarks/utils/graphGenerator.ts +201 -0
  1048. package/tests/benchmarks/utils/reporter.ts +231 -0
  1049. package/tests/benchmarks/workflows/endToEnd.bench.ts +132 -0
  1050. package/tests/bootstrap.test.ts +319 -0
  1051. package/tests/budget-tracker.spec.ts +279 -0
  1052. package/tests/bulkOps.spec.ts +166 -0
  1053. package/tests/bulletproof-determinism.test.ts +223 -0
  1054. package/tests/canonicalJson.test.ts +130 -0
  1055. package/tests/checkRunConverter.spec.ts +357 -0
  1056. package/tests/cli/commands/gate/test.spec.ts +564 -0
  1057. package/tests/cli/emit-frames-flag.spec.ts +117 -0
  1058. package/tests/cli/exitHandler.spec.ts +314 -0
  1059. package/tests/cli/flags.spec.ts +223 -0
  1060. package/tests/cli/formatters.spec.ts +513 -0
  1061. package/tests/cli/output.spec.ts +221 -0
  1062. package/tests/cli-autopilot.spec.ts +170 -0
  1063. package/tests/cli-budget-guards.spec.ts +210 -0
  1064. package/tests/cli-color-control.spec.ts +334 -0
  1065. package/tests/cli-deliverables-generator.spec.ts +185 -0
  1066. package/tests/cli-determinism.spec.ts +496 -0
  1067. package/tests/cli-init-enterprise.spec.ts +294 -0
  1068. package/tests/cli-init-json.spec.ts +154 -0
  1069. package/tests/cli-init-local.spec.ts +159 -0
  1070. package/tests/cli-json-envelope.spec.ts +140 -0
  1071. package/tests/cli-json.spec.ts +408 -0
  1072. package/tests/cli-orchestrate-plan-batch.spec.ts +329 -0
  1073. package/tests/cli-orchestrate.spec.ts +231 -0
  1074. package/tests/cli-plan-generation.spec.ts +367 -0
  1075. package/tests/cli-plan-review.spec.ts +300 -0
  1076. package/tests/cli-progress.spec.ts +193 -0
  1077. package/tests/cli-ux-enhancements.spec.ts +213 -0
  1078. package/tests/cliJsonPurity.spec.ts +437 -0
  1079. package/tests/cliSuggestDeps.spec.ts +360 -0
  1080. package/tests/cluster-gates-rollback.spec.ts +353 -0
  1081. package/tests/command-validator-integration.spec.ts +305 -0
  1082. package/tests/command-validator.spec.ts +380 -0
  1083. package/tests/commands/autopilot.spec.ts +124 -0
  1084. package/tests/commands/config-validate.spec.ts +301 -0
  1085. package/tests/commands/config.spec.ts +311 -0
  1086. package/tests/commands/create-project.spec.ts +90 -0
  1087. package/tests/commands/doctor.spec.ts +57 -0
  1088. package/tests/commands/execute.spec.ts +293 -0
  1089. package/tests/commands/gateAttest.spec.ts +172 -0
  1090. package/tests/commands/gateImport.spec.ts +176 -0
  1091. package/tests/commands/gateReport.spec.ts +130 -0
  1092. package/tests/commands/guards.spec.ts +114 -0
  1093. package/tests/commands/idea.spec.ts +177 -0
  1094. package/tests/commands/merge.spec.ts +166 -0
  1095. package/tests/commands/plan.spec.ts +123 -0
  1096. package/tests/commands/query.spec.ts +294 -0
  1097. package/tests/commands/report.spec.ts +54 -0
  1098. package/tests/commands/retry.spec.ts +300 -0
  1099. package/tests/commands/schema.spec.ts +136 -0
  1100. package/tests/commands/validation.spec.ts +229 -0
  1101. package/tests/completion.spec.ts +133 -0
  1102. package/tests/config-inspect.spec.ts +202 -0
  1103. package/tests/conflictClustering-e2e.spec.ts +278 -0
  1104. package/tests/conflictClustering.spec.ts +550 -0
  1105. package/tests/conflictGraph.spec.ts +126 -0
  1106. package/tests/conflictPredictor.spec.ts +238 -0
  1107. package/tests/deliverables-generator.spec.ts +329 -0
  1108. package/tests/deliverables.spec.ts +381 -0
  1109. package/tests/dependencyParser-github.spec.ts +244 -0
  1110. package/tests/dependencyParser.spec.ts +386 -0
  1111. package/tests/dependencyScoring.spec.ts +668 -0
  1112. package/tests/deterministic-applicable.test.ts +156 -0
  1113. package/tests/deterministic-build.test.ts +172 -0
  1114. package/tests/deterministic-simple.test.ts +32 -0
  1115. package/tests/discover-suggest-integration.spec.ts +340 -0
  1116. package/tests/dogfood-merge-weave-script.spec.ts +150 -0
  1117. package/tests/e2e/planner.spec.ts +596 -0
  1118. package/tests/e2e-comprehensive.test.ts +500 -0
  1119. package/tests/e2e-determinism.test.ts +293 -0
  1120. package/tests/e2e-synthetic-6pr-weave.spec.ts +329 -0
  1121. package/tests/enterprise-init.spec.ts +350 -0
  1122. package/tests/envUtils.spec.ts +267 -0
  1123. package/tests/error-handling.test.ts +104 -0
  1124. package/tests/error-recovery.spec.ts +451 -0
  1125. package/tests/execution-plan-v1.test.ts +257 -0
  1126. package/tests/executionState-loadGateResults.spec.ts +267 -0
  1127. package/tests/executionState.test.ts +169 -0
  1128. package/tests/executors/README.md +100 -0
  1129. package/tests/executors/frameContract-integration.spec.ts +324 -0
  1130. package/tests/executors/frameContract.spec.ts +531 -0
  1131. package/tests/executors/guardrailEnforcement.spec.ts +424 -0
  1132. package/tests/executors/lifecycle.spec.ts +313 -0
  1133. package/tests/executors/toolBudget.spec.ts +473 -0
  1134. package/tests/feature-spec-v0.test.ts +145 -0
  1135. package/tests/fileAnalysis.spec.ts +946 -0
  1136. package/tests/fingerprint.spec.ts +100 -0
  1137. package/tests/fixtures/README.md +380 -0
  1138. package/tests/fixtures/deliverables/batch-example-plan.json +62 -0
  1139. package/tests/fixtures/executors/README.md +57 -0
  1140. package/tests/fixtures/executors/index.ts +9 -0
  1141. package/tests/fixtures/executors/mock-executor.ts +204 -0
  1142. package/tests/fixtures/executors/registry.ts +51 -0
  1143. package/tests/fixtures/executors/types.ts +95 -0
  1144. package/tests/fixtures/fixtures.spec.ts +307 -0
  1145. package/tests/fixtures/gates/configs.ts +234 -0
  1146. package/tests/fixtures/gates/results.ts +234 -0
  1147. package/tests/fixtures/harvest-bundle-fixture.json +87 -0
  1148. package/tests/fixtures/index.ts +219 -0
  1149. package/tests/fixtures/invalid/plans.ts +178 -0
  1150. package/tests/fixtures/jest/all-passing.json +71 -0
  1151. package/tests/fixtures/jest/snapshot-failures.json +66 -0
  1152. package/tests/fixtures/jest/some-failing.json +100 -0
  1153. package/tests/fixtures/jest/with-location.json +84 -0
  1154. package/tests/fixtures/junit/cdata-messages.xml +29 -0
  1155. package/tests/fixtures/junit/multiple-suites.xml +30 -0
  1156. package/tests/fixtures/junit/single-suite.xml +17 -0
  1157. package/tests/fixtures/junit/with-errors.xml +19 -0
  1158. package/tests/fixtures/junit/with-skipped.xml +18 -0
  1159. package/tests/fixtures/npm-audit.json +32 -0
  1160. package/tests/fixtures/plan.bad-schema.json +5 -0
  1161. package/tests/fixtures/plan.bad-unknown-dep.json +10 -0
  1162. package/tests/fixtures/plan.ci-gates.json +36 -0
  1163. package/tests/fixtures/plan.complex-cycle.json +22 -0
  1164. package/tests/fixtures/plan.cycle.json +14 -0
  1165. package/tests/fixtures/plan.deep-chain.json +95 -0
  1166. package/tests/fixtures/plan.dogfood-execute.json +36 -0
  1167. package/tests/fixtures/plan.gates.json +30 -0
  1168. package/tests/fixtures/plan.integration-pyramid.json +56 -0
  1169. package/tests/fixtures/plan.orphans.json +22 -0
  1170. package/tests/fixtures/plan.parallel.json +30 -0
  1171. package/tests/fixtures/plan.tiny.json +18 -0
  1172. package/tests/fixtures/plan.wide-parallel.json +75 -0
  1173. package/tests/fixtures/plan.with-failures.json +26 -0
  1174. package/tests/fixtures/plan.with-vuln.json +25 -0
  1175. package/tests/fixtures/planner/cross-module.json +101 -0
  1176. package/tests/fixtures/planner/cycle-error.json +56 -0
  1177. package/tests/fixtures/planner/diamond-pattern.json +74 -0
  1178. package/tests/fixtures/planner/empty-repo.json +9 -0
  1179. package/tests/fixtures/planner/file-overlap-heavy.json +110 -0
  1180. package/tests/fixtures/planner/invalid-pr.json +25 -0
  1181. package/tests/fixtures/planner/merge-conflicts.json +42 -0
  1182. package/tests/fixtures/planner/mixed-deps.json +101 -0
  1183. package/tests/fixtures/planner/self-dependency.json +24 -0
  1184. package/tests/fixtures/planner/simple-stack.json +79 -0
  1185. package/tests/fixtures/planner/single-pr.json +25 -0
  1186. package/tests/fixtures/planner/stale-pr.json +40 -0
  1187. package/tests/fixtures/plans/complex.ts +201 -0
  1188. package/tests/fixtures/plans/diamond.ts +115 -0
  1189. package/tests/fixtures/plans/linear.ts +74 -0
  1190. package/tests/fixtures/plans/simple.ts +61 -0
  1191. package/tests/fixtures/prs/basic.ts +175 -0
  1192. package/tests/fixtures/prs/withDeps.ts +197 -0
  1193. package/tests/fixtures/scan-results-clean.sarif +15 -0
  1194. package/tests/fixtures/scan-results.sarif +74 -0
  1195. package/tests/fixtures/scenarios/mergeWorkflows.ts +300 -0
  1196. package/tests/fixtures/scenarios/syntheticWeave.ts +351 -0
  1197. package/tests/fixtures/snapshot/package.json +5 -0
  1198. package/tests/fixtures/snapshot/sample.ts +21 -0
  1199. package/tests/fixtures/utils/cleanup.ts +81 -0
  1200. package/tests/fixtures/utils/mockGitHub.ts +219 -0
  1201. package/tests/fixtures/utils/tempDir.ts +109 -0
  1202. package/tests/fixtures/verification/expected-verification.json +16 -0
  1203. package/tests/fixtures/verification/receipt.json +31 -0
  1204. package/tests/fixtures/verification/snapshot.json +44 -0
  1205. package/tests/fixtures/vitest/all-passing.json +67 -0
  1206. package/tests/fixtures/vitest/complex-nested-suites.json +98 -0
  1207. package/tests/fixtures/vitest/some-failing.json +98 -0
  1208. package/tests/fixtures/vitest/with-coverage.json +97 -0
  1209. package/tests/fixtures-usage-examples.spec.ts +304 -0
  1210. package/tests/flakeReport.spec.ts +267 -0
  1211. package/tests/frames/ci-gate-integration.spec.ts +331 -0
  1212. package/tests/frames/controller.spec.ts +165 -0
  1213. package/tests/frames/emitter.spec.ts +371 -0
  1214. package/tests/frames/idempotency.spec.ts +177 -0
  1215. package/tests/frames/storage.spec.ts +346 -0
  1216. package/tests/frames/types.spec.ts +249 -0
  1217. package/tests/frames/v2-schema-integration.spec.ts +435 -0
  1218. package/tests/gate-working-directory.spec.ts +204 -0
  1219. package/tests/gateMapping.spec.ts +161 -0
  1220. package/tests/gateReportIntegration.spec.ts +175 -0
  1221. package/tests/gateReportValidation.spec.ts +452 -0
  1222. package/tests/gates/test/adapters/jest-json.spec.ts +372 -0
  1223. package/tests/gates/test/adapters/junit-xml.spec.ts +421 -0
  1224. package/tests/gates/test/adapters/registry.spec.ts +376 -0
  1225. package/tests/gates/test/adapters/vitest-json.spec.ts +455 -0
  1226. package/tests/gates/test/enrichment/failureId.spec.ts +131 -0
  1227. package/tests/gates/test/enrichment/nextActions.spec.ts +365 -0
  1228. package/tests/gates/test/enrichment/rerunTemplates.spec.ts +187 -0
  1229. package/tests/gates/test/enrichment/signature.spec.ts +163 -0
  1230. package/tests/gates/test/enrichment/stackParser.spec.ts +203 -0
  1231. package/tests/gates/turncost-integration.spec.ts +221 -0
  1232. package/tests/gates/validation-integration.spec.ts +147 -0
  1233. package/tests/gates/validator.spec.ts +200 -0
  1234. package/tests/gates.test.ts +255 -0
  1235. package/tests/gatesWithPolicy.hostilityTimeoutAdjustment.spec.ts +156 -0
  1236. package/tests/git-operations-receipts.spec.ts +121 -0
  1237. package/tests/git-operations.test.ts +152 -0
  1238. package/tests/git-runtime.spec.ts +175 -0
  1239. package/tests/github-api.labels.spec.ts +21 -0
  1240. package/tests/github-api.test.ts +85 -0
  1241. package/tests/github-context-diet.spec.ts +441 -0
  1242. package/tests/github-diff-hunks.spec.ts +387 -0
  1243. package/tests/github-integration.spec.ts +774 -0
  1244. package/tests/github-minimal-context.spec.ts +338 -0
  1245. package/tests/github-symbol-map.spec.ts +414 -0
  1246. package/tests/githubClient.spec.ts +123 -0
  1247. package/tests/governance/mcpStatus.spec.ts +276 -0
  1248. package/tests/governance/timeoutAdjustment.spec.ts +149 -0
  1249. package/tests/governance/turnCostSummary.spec.ts +188 -0
  1250. package/tests/governance-retention.spec.ts +151 -0
  1251. package/tests/governance-wrapper-delegation.spec.ts +148 -0
  1252. package/tests/guardrails.spec.ts +860 -0
  1253. package/tests/hash.test.ts +83 -0
  1254. package/tests/helpers/cli.ts +23 -0
  1255. package/tests/helpers/getStd.ts +1 -0
  1256. package/tests/helpers/makeGate.ts +19 -0
  1257. package/tests/helpers/plannerTestHelpers.ts +314 -0
  1258. package/tests/hooks/events.spec.ts +518 -0
  1259. package/tests/hostility/checks.spec.ts +295 -0
  1260. package/tests/hostility/integration.spec.ts +123 -0
  1261. package/tests/hostility/score.spec.ts +175 -0
  1262. package/tests/init.spec.ts +270 -0
  1263. package/tests/integration/hipaa-encryption.spec.ts +148 -0
  1264. package/tests/integration/lex-smoke-test.spec.ts +328 -0
  1265. package/tests/integration-e2e.test.ts +244 -0
  1266. package/tests/integration-matrix.test.ts +409 -0
  1267. package/tests/interPRConflicts.spec.ts +254 -0
  1268. package/tests/interactive-plan-history.spec.ts +255 -0
  1269. package/tests/interactive-plan-review.spec.ts +287 -0
  1270. package/tests/issue-analyzer.spec.ts +593 -0
  1271. package/tests/lexsona-integration.spec.ts +311 -0
  1272. package/tests/localOverlay.spec.ts +203 -0
  1273. package/tests/lockHash.spec.ts +167 -0
  1274. package/tests/mcp-auth-errors.spec.ts +190 -0
  1275. package/tests/mcp-contracts.spec.ts +290 -0
  1276. package/tests/mcp-gates-external-plan.spec.ts +146 -0
  1277. package/tests/mcp-granular-tools.spec.ts +208 -0
  1278. package/tests/mcp-runstore-integration.spec.ts +334 -0
  1279. package/tests/mcp-scope-integration.spec.ts +318 -0
  1280. package/tests/mcp-task-handoff.spec.ts +320 -0
  1281. package/tests/mcp-workflow-guide.spec.ts +53 -0
  1282. package/tests/mcp.test.ts +151 -0
  1283. package/tests/merge-conflict-detection.spec.ts +260 -0
  1284. package/tests/mergeEligibility.test.ts +201 -0
  1285. package/tests/mergeLockHash.spec.ts +158 -0
  1286. package/tests/mergeOrder-with-fixtures.spec.ts +215 -0
  1287. package/tests/mergeOrder.test.ts +108 -0
  1288. package/tests/mergeTreeSimulator.spec.ts +145 -0
  1289. package/tests/metrics/export.spec.ts +446 -0
  1290. package/tests/metrics/turncost.spec.ts +309 -0
  1291. package/tests/metrics-template.spec.ts +137 -0
  1292. package/tests/migrateProfile.spec.ts +254 -0
  1293. package/tests/mis.spec.ts +202 -0
  1294. package/tests/monitoring-audit.spec.ts +181 -0
  1295. package/tests/monitoring-cache.spec.ts +331 -0
  1296. package/tests/monitoring-error-recovery.spec.ts +236 -0
  1297. package/tests/monitoring-errors.spec.ts +193 -0
  1298. package/tests/monitoring-fileLogger.spec.ts +319 -0
  1299. package/tests/monitoring-health.spec.ts +152 -0
  1300. package/tests/monitoring-lock.spec.ts +308 -0
  1301. package/tests/monitoring-logger.spec.ts +157 -0
  1302. package/tests/monitoring-metrics.spec.ts +158 -0
  1303. package/tests/monitoring-profiler.spec.ts +197 -0
  1304. package/tests/orchestration-determinism.spec.ts +204 -0
  1305. package/tests/parseRemote.spec.ts +25 -0
  1306. package/tests/pathResolver.spec.ts +122 -0
  1307. package/tests/paths.spec.ts +68 -0
  1308. package/tests/performance.spec.ts +322 -0
  1309. package/tests/pipeline-determinism.spec.ts +597 -0
  1310. package/tests/plan-tier-integration.spec.ts +184 -0
  1311. package/tests/precedence-resolution.spec.ts +682 -0
  1312. package/tests/preflightConflicts.spec.ts +205 -0
  1313. package/tests/procedures/keystone-policy.spec.ts +296 -0
  1314. package/tests/procedures/loader.spec.ts +585 -0
  1315. package/tests/procedures/pr-review.spec.ts +321 -0
  1316. package/tests/profileResolver.spec.ts +375 -0
  1317. package/tests/progress-indicators.spec.ts +139 -0
  1318. package/tests/promptsResolver.spec.ts +443 -0
  1319. package/tests/public-api.spec.ts +272 -0
  1320. package/tests/query.spec.ts +170 -0
  1321. package/tests/receipts.spec.ts +463 -0
  1322. package/tests/release-prepare.spec.ts +268 -0
  1323. package/tests/report.test.ts +335 -0
  1324. package/tests/resolutionGuidance.spec.ts +160 -0
  1325. package/tests/rotate-secrets-example.spec.ts +198 -0
  1326. package/tests/rulesResolver.spec.ts +232 -0
  1327. package/tests/runGit.spec.ts +229 -0
  1328. package/tests/runner-lifecycle-integration.spec.ts +283 -0
  1329. package/tests/runs/artifacts.spec.ts +367 -0
  1330. package/tests/runs/decisions.spec.ts +495 -0
  1331. package/tests/runs/enforcement.spec.ts +555 -0
  1332. package/tests/runs/failures.spec.ts +554 -0
  1333. package/tests/runs/manager-runstore-integration.spec.ts +455 -0
  1334. package/tests/runs/manager.spec.ts +678 -0
  1335. package/tests/runs-manager.spec.ts +485 -0
  1336. package/tests/safety-acceptance.spec.ts +278 -0
  1337. package/tests/safety-enhanced.spec.ts +329 -0
  1338. package/tests/safety-framework.spec.ts +427 -0
  1339. package/tests/safety-guards-integration.spec.ts +213 -0
  1340. package/tests/safety-integration.spec.ts +278 -0
  1341. package/tests/sarif-parser.spec.ts +148 -0
  1342. package/tests/schema.test.ts +88 -0
  1343. package/tests/schemas/behavior-rule.spec.ts +366 -0
  1344. package/tests/schemas/executorManifest.spec.ts +441 -0
  1345. package/tests/schemas/persona-integration.spec.ts +62 -0
  1346. package/tests/schemas/persona.spec.ts +172 -0
  1347. package/tests/schemas/project.spec.ts +247 -0
  1348. package/tests/schemas/run-store.spec.ts +553 -0
  1349. package/tests/schemas/runCentric.spec.ts +463 -0
  1350. package/tests/schemas/vacuumReadyPrompt.spec.ts +515 -0
  1351. package/tests/scope-github-auto-detection.spec.ts +200 -0
  1352. package/tests/scopeValidator.spec.ts +497 -0
  1353. package/tests/security-authentication.spec.ts +42 -0
  1354. package/tests/security-authorization.spec.ts +350 -0
  1355. package/tests/security-cli.spec.ts +264 -0
  1356. package/tests/security-compliance.spec.ts +334 -0
  1357. package/tests/security-policy.spec.ts +295 -0
  1358. package/tests/security-scanning.spec.ts +349 -0
  1359. package/tests/security-secrets.spec.ts +401 -0
  1360. package/tests/store/create-run-store.spec.ts +185 -0
  1361. package/tests/store/inmemory/run-store.spec.ts +533 -0
  1362. package/tests/store/sqlite/run-store.spec.ts +849 -0
  1363. package/tests/telemetry/frames.spec.ts +120 -0
  1364. package/tests/tiers.spec.ts +466 -0
  1365. package/tests/token-usage.spec.ts +309 -0
  1366. package/tests/toolchain-manifest.spec.ts +145 -0
  1367. package/tests/unified-budget.spec.ts +713 -0
  1368. package/tests/unit/cache/issue-cache.spec.ts +131 -0
  1369. package/tests/unit/fanout/analyzer-integration.spec.ts +398 -0
  1370. package/tests/unit/fanout/analyzer.spec.ts +605 -0
  1371. package/tests/unit/fanout/github-adapter.spec.ts +203 -0
  1372. package/tests/unit/fanout/harvest.spec.ts +93 -0
  1373. package/tests/unit/fanout/monitor.spec.ts +297 -0
  1374. package/tests/unit/fanout/types.spec.ts +308 -0
  1375. package/tests/unit/github/batch-ops.spec.ts +179 -0
  1376. package/tests/unit/learning/counter-example.spec.ts +168 -0
  1377. package/tests/unit/learning/storage.spec.ts +154 -0
  1378. package/tests/unit/preview/constraints.spec.ts +429 -0
  1379. package/tests/unit/runs/attribution.spec.ts +204 -0
  1380. package/tests/unit/schemas/task-contract.spec.ts +483 -0
  1381. package/tests/unit/snapshot/builder.spec.ts +389 -0
  1382. package/tests/unit/verification/engine-verifier.spec.ts +279 -0
  1383. package/tests/unit/weave/authority-evaluator.spec.ts +404 -0
  1384. package/tests/unit/weave/authority-schema.spec.ts +199 -0
  1385. package/tests/unit/weave/auto-undraft-integration.spec.ts +349 -0
  1386. package/tests/unit/weave/copilot-completion.spec.ts +182 -0
  1387. package/tests/unit/weave/d1-executor.spec.ts +269 -0
  1388. package/tests/unit/weave/d2-executor.spec.ts +334 -0
  1389. package/tests/unit/weave/fanout-generator.spec.ts +365 -0
  1390. package/tests/unit/weave/fanout-matcher.spec.ts +320 -0
  1391. package/tests/unit/weave/fanout-schema.spec.ts +221 -0
  1392. package/tests/unit/weave/mergeWeaveSequential.spec.ts +268 -0
  1393. package/tests/unit/weave/metrics-calculator.spec.ts +212 -0
  1394. package/tests/unit/weave/metrics-logger.spec.ts +233 -0
  1395. package/tests/unit/weave/metrics-schema.spec.ts +383 -0
  1396. package/tests/unit/weave/multi-repo-plan.spec.ts +221 -0
  1397. package/tests/unit/weave/planner.spec.ts +227 -0
  1398. package/tests/unit/weave/post-merge-checks.spec.ts +342 -0
  1399. package/tests/unit/weave/recovery.spec.ts +306 -0
  1400. package/tests/unit/weave/testfix/applier.spec.ts +364 -0
  1401. package/tests/unit/weave/testfix/e2e.spec.ts +273 -0
  1402. package/tests/unit/weave/testfix/integration.spec.ts +128 -0
  1403. package/tests/unit/weave/testfix/matcher.spec.ts +321 -0
  1404. package/tests/unit/weave/testfix/schema.spec.ts +298 -0
  1405. package/tests/utils/fingerprint.spec.ts +251 -0
  1406. package/tests/utils/paths.spec.ts +284 -0
  1407. package/tests/utils/tokens.spec.ts +210 -0
  1408. package/tests/utils/validation.spec.ts +215 -0
  1409. package/tests/utils-validation.spec.ts +80 -0
  1410. package/tests/validate-manifests.spec.ts +231 -0
  1411. package/tests/validation.spec.ts +501 -0
  1412. package/tests/vuln-gate.spec.ts +341 -0
  1413. package/tests/weave/adr007-integration.spec.ts +309 -0
  1414. package/tests/weave/checkpoint/cli-integration.spec.ts +118 -0
  1415. package/tests/weave/checkpoint/storage.spec.ts +302 -0
  1416. package/tests/weave/checkpoint/utils.spec.ts +223 -0
  1417. package/tests/weave/frameHelper.spec.ts +423 -0
  1418. package/tests/weave/gateFailureHandler.spec.ts +249 -0
  1419. package/tests/weave/lockFile.spec.ts +387 -0
  1420. package/tests/weave/mergeHelpers.spec.ts +173 -0
  1421. package/tests/weave/receiptHelper.spec.ts +261 -0
  1422. package/tests/weave/stateMachine.spec.ts +436 -0
  1423. package/tests/weave-contract.test.ts +517 -0
  1424. package/tests/weave-e2e.spec.ts +279 -0
  1425. package/tests/weaveLock.spec.ts +136 -0
  1426. package/tests/workflow-state-machine.spec.ts +274 -0
  1427. package/tests/write-protection.spec.ts +213 -0
  1428. package/tsconfig.json +18 -0
  1429. package/tsup.config.ts +12 -0
  1430. package/vitest.benchmark.config.ts +17 -0
  1431. package/vitest.config.ts +28 -0
  1432. package/vitest.git.config.ts +12 -0
  1433. package/vitest.slow-cli.config.ts +28 -0
@@ -0,0 +1,3587 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * MCP server adapter for lexrunner
5
+ * Exposes read-only tools for plan creation, gate execution, and merge operations
6
+ */
7
+
8
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
9
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
10
+ import {
11
+ CallToolRequestSchema,
12
+ ErrorCode,
13
+ ListToolsRequestSchema,
14
+ McpError,
15
+ } from "@modelcontextprotocol/sdk/types.js";
16
+ import { z } from "zod";
17
+
18
+ import { loadInputs, detectGitHubMode } from "../core/inputs.js";
19
+ import { generatePlan } from "../core/plan.js";
20
+ import { generateSnapshot, generateGitHubSnapshot } from "../core/snapshot.js";
21
+ import { canonicalJSONStringify } from "../util/canonicalJson.js";
22
+ import { executeGatesWithPolicy } from "../gates.js";
23
+ import { ExecutionState } from "../executionState.js";
24
+ import { MergeEligibilityEvaluator } from "../mergeEligibility.js";
25
+ import { computeMergeOrder, CycleError, UnknownDependencyError } from "../mergeOrder.js";
26
+ import { loadPlan, validatePlan } from "../schema.js";
27
+ import { initLocalOverlay } from "../config/localOverlay.js";
28
+ import { healthChecker } from "../monitoring/health.js";
29
+ import { generatePlanFromGitHub } from "../core/githubPlan.js";
30
+ import { generateMultiRepoPlan } from "../core/multiRepoPlan.js";
31
+ import { createGitHubClient } from "../github/index.js";
32
+ import { createGitHubAPI, GitHubAPI, GitHubAPIError } from "../github/api.js";
33
+ import { createGitOperations } from "../git/operations.js";
34
+ import {
35
+ bootstrapWorkspace,
36
+ detectProjectType,
37
+ getEnvironmentSuggestions,
38
+ } from "../core/bootstrap.js";
39
+ import {
40
+ getMCPEnvironment,
41
+ PlanCreateArgs,
42
+ GatesRunArgs,
43
+ MergeApplyArgs,
44
+ InitLocalArgs,
45
+ ProfileResolveArgs,
46
+ PlanCreateResult,
47
+ GatesRunResult,
48
+ MergeApplyResult,
49
+ InitLocalResult,
50
+ ProfileResolveResult,
51
+ WorkflowGuideArgs,
52
+ PrListArgs,
53
+ PrListResult,
54
+ PlanValidateArgs,
55
+ PlanValidateResult,
56
+ PlanAnalyzeArgs,
57
+ PlanAnalyzeResult,
58
+ CreateTaskSnapshotArgs,
59
+ SubmitTaskReceiptArgs,
60
+ GetTaskStatusArgs,
61
+ ListPendingTasksArgs,
62
+ CreateTaskSnapshotResult,
63
+ SubmitTaskReceiptResult,
64
+ GetTaskStatusResult,
65
+ ListPendingTasksResult,
66
+ FanoutHarvestArgs,
67
+ FanoutAnalyzeArgs,
68
+ FanoutHarvestResult,
69
+ FanoutAnalyzeResult,
70
+ } from "./types.js";
71
+ import {
72
+ resolveProfile,
73
+ validateWriteOperation,
74
+ WriteProtectionError,
75
+ } from "../config/profileResolver.js";
76
+ import { getCIMutationPolicy, validateCIEnvironment } from "../util/envUtils.js";
77
+
78
+ // Governance metrics imports
79
+ import { getGlobalMetricsCollector, METRIC_DEFINITIONS } from "../metrics/export.js";
80
+
81
+ // AXError imports for structured error responses
82
+ import {
83
+ type AXError,
84
+ mcpToolError,
85
+ planNotFoundError,
86
+ writeProtectionError,
87
+ githubApiError,
88
+ toAXError,
89
+ ErrorCodes,
90
+ cycleDetectedError,
91
+ unknownDependencyError,
92
+ AXErrorException,
93
+ isAXErrorException,
94
+ type CycleDetectedContext,
95
+ type UnknownDependencyContext,
96
+ } from "../errors/index.js";
97
+
98
+ import * as fs from "fs";
99
+ import * as path from "path";
100
+
101
+ // Hostility scoring imports
102
+ import { runEnvironmentQualityCheck } from "../hostility/index.js";
103
+
104
+ // Governance integration imports
105
+ import { buildGovernanceStatus, governanceStatusToJSON } from "../governance/index.js";
106
+
107
+ // Tier metrics imports
108
+ import { suggestTiersForPlan, calculateTierMetrics } from "../tiers/index.js";
109
+
110
+ // Senior Dev executor imports
111
+ import {
112
+ prepareReviewContext,
113
+ recallSeniorDevContext,
114
+ captureSeniorDevFrame,
115
+ EXECUTOR_MODES,
116
+ } from "../executors/seniorDev/index.js";
117
+ import type {
118
+ PrepareContextInput,
119
+ RecallContextInput,
120
+ CaptureFrameInput,
121
+ RecallQueryType,
122
+ Severity,
123
+ } from "../executors/seniorDev/index.js";
124
+
125
+ // Run manager imports
126
+ import {
127
+ createRunManager,
128
+ StartRunInput,
129
+ StartRunInputSchema,
130
+ GetStatusInput,
131
+ GetStatusInputSchema,
132
+ RunNotFoundError,
133
+ SubmitDecisionInput,
134
+ SubmitDecisionInputSchema,
135
+ submitDecision,
136
+ } from "../runs/index.js";
137
+
138
+ // RunStore imports
139
+ import { createRunStore, type RunStore, type ListRunsOptions } from "../store/index.js";
140
+ import { ulid } from "ulid";
141
+ import * as crypto from "crypto";
142
+
143
+ // Workflow guidance imports
144
+ import { createWorkflowGuide, type WorkflowPhase } from "./workflow/state-machine.js";
145
+ import type { WorkflowGuide } from "./types/guided-response.js";
146
+
147
+ // Task Snapshot Contract imports (ADR-007)
148
+ import { SnapshotBuilder } from "../snapshot/index.js";
149
+ import { EngineVerifier } from "../verification/index.js";
150
+ import { parseTaskReceipt, TaskSnapshot_v1, TaskReceipt_v1 } from "../schemas/task-contract.js";
151
+
152
+ // =============================================================================
153
+ // AXError MCP Helper
154
+ // =============================================================================
155
+
156
+ /**
157
+ * Create an McpError with AXError-structured content in the message.
158
+ *
159
+ * Per AX-CONTRACT.md v0.1, Guarantee 2.3: All MCP tool failures should
160
+ * return structured errors that agents can parse for recovery actions.
161
+ *
162
+ * The error message is JSON-serialized AXError for machine readability,
163
+ * while remaining compatible with MCP's error format.
164
+ */
165
+ function throwMcpAXError(mcpErrorCode: ErrorCode, axError: AXError): never {
166
+ // Serialize the AXError as JSON in the message for structured parsing
167
+ const structuredMessage = JSON.stringify(axError);
168
+ throw new McpError(mcpErrorCode, structuredMessage);
169
+ }
170
+
171
+ /**
172
+ * Create an McpError from a caught error, converting to AXError format.
173
+ *
174
+ * @param mcpErrorCode - The MCP error code to use (e.g., ErrorCode.InternalError)
175
+ * @param tool - The MCP tool name
176
+ * @param error - The caught error
177
+ * @param operation - Optional operation description
178
+ * @param axErrorCode - Optional AXError code (defaults to INTERNAL_ERROR)
179
+ */
180
+ function throwMcpToolError(
181
+ mcpErrorCode: ErrorCode,
182
+ tool: string,
183
+ error: unknown,
184
+ operation?: string,
185
+ axErrorCode: string = ErrorCodes.INTERNAL_ERROR
186
+ ): never {
187
+ const message = error instanceof Error ? error.message : String(error);
188
+ const axError = mcpToolError(axErrorCode, `${tool} failed: ${message}`, {
189
+ tool,
190
+ operation,
191
+ });
192
+ throwMcpAXError(mcpErrorCode, axError);
193
+ }
194
+
195
+ /**
196
+ * Options for creating the MCP server.
197
+ */
198
+ export interface McpServerOptions {
199
+ /**
200
+ * RunStore instance for persisting run lifecycle data.
201
+ * If not provided, a default SqliteRunStore will be created.
202
+ */
203
+ runStore?: RunStore;
204
+ }
205
+
206
+ /**
207
+ * Input schema for lexrunner.listRuns tool
208
+ */
209
+ const ListRunsInputSchema = z.object({
210
+ limit: z.number().int().positive().optional(),
211
+ offset: z.number().int().nonnegative().optional(),
212
+ state: z.enum(["pending", "running", "completed", "failed", "aborted"]).optional(),
213
+ });
214
+ type ListRunsInput = z.infer<typeof ListRunsInputSchema>;
215
+
216
+ /**
217
+ * Create and configure the MCP server
218
+ */
219
+ function createServer(options?: McpServerOptions): Server {
220
+ // Initialize RunStore (use provided or create default)
221
+ const runStore = options?.runStore ?? createRunStore();
222
+ const server = new Server(
223
+ {
224
+ name: "lexrunner",
225
+ version: "0.1.0",
226
+ },
227
+ {
228
+ capabilities: {
229
+ tools: {},
230
+ },
231
+ }
232
+ );
233
+
234
+ // List available tools
235
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
236
+ return {
237
+ tools: [
238
+ {
239
+ name: "plan_create",
240
+ description:
241
+ "Create a plan from configuration files or auto-discover from GitHub PRs. Requires GITHUB_TOKEN environment variable when using fromGithub mode.",
242
+ inputSchema: {
243
+ type: "object",
244
+ properties: {
245
+ json: {
246
+ type: "boolean",
247
+ description: "Output plan as JSON to stdout",
248
+ default: false,
249
+ },
250
+ outDir: {
251
+ type: "string",
252
+ description: "Output directory for plan artifacts",
253
+ },
254
+ fromGithub: {
255
+ type: "boolean",
256
+ description: "Auto-discover PRs from GitHub API",
257
+ default: false,
258
+ },
259
+ query: {
260
+ type: "string",
261
+ description: "GitHub search query (e.g., 'is:open label:stack:*')",
262
+ },
263
+ labels: {
264
+ type: "array",
265
+ description: "Filter PRs by labels",
266
+ items: {
267
+ type: "string",
268
+ },
269
+ },
270
+ includeDrafts: {
271
+ type: "boolean",
272
+ description: "Include draft PRs in the plan",
273
+ default: true,
274
+ },
275
+ excludePRs: {
276
+ type: "array",
277
+ description: "Exclude specific PRs by number",
278
+ items: {
279
+ type: "number",
280
+ },
281
+ },
282
+ githubToken: {
283
+ type: "string",
284
+ description: "GitHub API token (or use GITHUB_TOKEN env var)",
285
+ },
286
+ owner: {
287
+ type: "string",
288
+ description: "GitHub repository owner (auto-detected from git remote)",
289
+ },
290
+ repo: {
291
+ type: "string",
292
+ description: "GitHub repository name (auto-detected from git remote)",
293
+ },
294
+ repos: {
295
+ type: "array",
296
+ description:
297
+ "Multi-repo mode: array of repositories to discover PRs from. Overrides owner/repo if provided.",
298
+ items: {
299
+ type: "object",
300
+ properties: {
301
+ owner: { type: "string", description: "Repository owner" },
302
+ repo: { type: "string", description: "Repository name" },
303
+ priority: {
304
+ type: "number",
305
+ description: "Priority for merge ordering (default: 1, lower = earlier)",
306
+ },
307
+ },
308
+ required: ["owner", "repo"],
309
+ },
310
+ },
311
+ requiredGates: {
312
+ type: "array",
313
+ description: "List of required gates (default: lint,typecheck,test)",
314
+ items: {
315
+ type: "string",
316
+ },
317
+ },
318
+ maxWorkers: {
319
+ type: "number",
320
+ description: "Maximum parallel workers for execution (default: 2)",
321
+ },
322
+ target: {
323
+ type: "string",
324
+ description: "Target branch for merging PRs (default: repo default branch)",
325
+ },
326
+ },
327
+ },
328
+ },
329
+ {
330
+ name: "pr_list",
331
+ description:
332
+ "List pull requests from GitHub without creating a plan. Useful for discovering PRs before plan generation.",
333
+ inputSchema: {
334
+ type: "object",
335
+ properties: {
336
+ owner: {
337
+ type: "string",
338
+ description:
339
+ "GitHub repository owner (auto-detected from git remote if not provided)",
340
+ },
341
+ repo: {
342
+ type: "string",
343
+ description:
344
+ "GitHub repository name (auto-detected from git remote if not provided)",
345
+ },
346
+ query: {
347
+ type: "string",
348
+ description: "GitHub search query (e.g., 'is:open label:stack:*')",
349
+ },
350
+ labels: {
351
+ type: "array",
352
+ description: "Filter PRs by labels",
353
+ items: {
354
+ type: "string",
355
+ },
356
+ },
357
+ includeDrafts: {
358
+ type: "boolean",
359
+ description: "Include draft PRs in results",
360
+ default: true,
361
+ },
362
+ excludePRs: {
363
+ type: "array",
364
+ description: "Exclude specific PRs by number",
365
+ items: {
366
+ type: "number",
367
+ },
368
+ },
369
+ githubToken: {
370
+ type: "string",
371
+ description: "GitHub API token (or use GITHUB_TOKEN env var)",
372
+ },
373
+ state: {
374
+ type: "string",
375
+ description: "PR state filter (default: open)",
376
+ enum: ["open", "closed", "all"],
377
+ default: "open",
378
+ },
379
+ },
380
+ },
381
+ },
382
+ {
383
+ name: "plan_validate",
384
+ description:
385
+ "Validate a plan.json file without executing it. Checks schema compliance and logical consistency.",
386
+ inputSchema: {
387
+ type: "object",
388
+ properties: {
389
+ planFile: {
390
+ type: "string",
391
+ description: "Path to plan.json file (default: <profile>/runner/plan.json)",
392
+ },
393
+ planContent: {
394
+ type: "string",
395
+ description: "JSON string of plan content to validate (alternative to planFile)",
396
+ },
397
+ },
398
+ },
399
+ },
400
+ {
401
+ name: "plan_analyze",
402
+ description:
403
+ "Analyze a plan for potential conflicts and dependency issues. Performs dry-run dependency resolution and conflict detection.",
404
+ inputSchema: {
405
+ type: "object",
406
+ properties: {
407
+ planFile: {
408
+ type: "string",
409
+ description: "Path to plan.json file (default: <profile>/runner/plan.json)",
410
+ },
411
+ },
412
+ },
413
+ },
414
+ {
415
+ name: "gates_run",
416
+ description: "Execute gates for plan items",
417
+ inputSchema: {
418
+ type: "object",
419
+ properties: {
420
+ planFile: {
421
+ type: "string",
422
+ description:
423
+ "Path to external plan.json file (optional, uses internal state if not provided)",
424
+ },
425
+ onlyItem: {
426
+ type: "string",
427
+ description: "Run gates for specific item only",
428
+ },
429
+ onlyGate: {
430
+ type: "string",
431
+ description: "Run specific gate only",
432
+ },
433
+ outDir: {
434
+ type: "string",
435
+ description: "Output directory for gate results",
436
+ },
437
+ },
438
+ },
439
+ },
440
+ {
441
+ name: "merge_apply",
442
+ description: "Apply merge operations (requires ALLOW_MUTATIONS=true)",
443
+ inputSchema: {
444
+ type: "object",
445
+ properties: {
446
+ dryRun: {
447
+ type: "boolean",
448
+ description: "Simulate merge without making changes",
449
+ default: true,
450
+ },
451
+ },
452
+ },
453
+ },
454
+ {
455
+ name: "local_init",
456
+ description:
457
+ "Initialize local overlay directory with auto-detected project configuration",
458
+ inputSchema: {
459
+ type: "object",
460
+ properties: {
461
+ force: {
462
+ type: "boolean",
463
+ description: "Force recreation even if local overlay exists",
464
+ default: false,
465
+ },
466
+ },
467
+ },
468
+ },
469
+ {
470
+ name: "profile_resolve",
471
+ description:
472
+ "Resolve profile directory using precedence chain (--profile-dir → LEX_PR_PROFILE_DIR → .smartergpt.local/ → .smartergpt/)",
473
+ inputSchema: {
474
+ type: "object",
475
+ properties: {
476
+ profileDir: {
477
+ type: "string",
478
+ description: "Optional profile directory override",
479
+ },
480
+ },
481
+ },
482
+ },
483
+ {
484
+ name: "health",
485
+ description: "Get health status of the system with optional metrics",
486
+ inputSchema: {
487
+ type: "object",
488
+ properties: {
489
+ includeMetrics: {
490
+ type: "boolean",
491
+ description: "Include detailed metrics in response",
492
+ default: false,
493
+ },
494
+ },
495
+ },
496
+ },
497
+ // ─────────────────────────────────────────────────────────────────
498
+ // Senior Dev Executor Tools
499
+ // ─────────────────────────────────────────────────────────────────
500
+ {
501
+ name: "executor_prepare_context",
502
+ description:
503
+ "Phase 1: Gather deterministic artifacts for code review (lint, typecheck, tests, diff, PR metadata)",
504
+ inputSchema: {
505
+ type: "object",
506
+ properties: {
507
+ pr_number: {
508
+ type: "string",
509
+ description: "PR number to prepare context for",
510
+ },
511
+ base_branch: {
512
+ type: "string",
513
+ description: "Base branch for diff (default: main)",
514
+ default: "main",
515
+ },
516
+ output_dir: {
517
+ type: "string",
518
+ description: "Output directory for artifacts (default: /tmp/senior-dev-review-...)",
519
+ },
520
+ skip_tests: {
521
+ type: "boolean",
522
+ description: "Skip running tests",
523
+ default: false,
524
+ },
525
+ skip_lint: {
526
+ type: "boolean",
527
+ description: "Skip running lint",
528
+ default: false,
529
+ },
530
+ skip_typecheck: {
531
+ type: "boolean",
532
+ description: "Skip running typecheck",
533
+ default: false,
534
+ },
535
+ },
536
+ required: ["pr_number"],
537
+ },
538
+ },
539
+ {
540
+ name: "executor_recall_context",
541
+ description:
542
+ "Phase 1: Recall relevant Frames from Lex memory (module reviews, developer history, patterns). " +
543
+ "This tool delegates to the Lex CLI (`lex recall`) to query the Lex memory system. " +
544
+ "For direct access to Lex memory, use the Lex MCP server's `mcp_lex_frame_recall` tool instead. " +
545
+ "This executor-specific tool provides Senior Dev workflow integration.",
546
+ inputSchema: {
547
+ type: "object",
548
+ properties: {
549
+ query_type: {
550
+ type: "string",
551
+ enum: ["module", "developer", "pattern", "pr"],
552
+ description: "Type of query: module, developer, pattern, or pr",
553
+ },
554
+ query: {
555
+ type: "string",
556
+ description:
557
+ "Query value (required for module, developer, pr; optional for pattern)",
558
+ },
559
+ limit: {
560
+ type: "number",
561
+ description: "Maximum frames to return (default: 10)",
562
+ default: 10,
563
+ },
564
+ },
565
+ required: ["query_type"],
566
+ },
567
+ },
568
+ {
569
+ name: "executor_capture_frame",
570
+ description: "Phase 4: Capture review session as a Frame in Lex memory (the receipt)",
571
+ inputSchema: {
572
+ type: "object",
573
+ properties: {
574
+ pr_number: {
575
+ type: "string",
576
+ description: "PR number being reviewed",
577
+ },
578
+ module: {
579
+ type: "string",
580
+ description: "Primary module (must match lexmap.policy.json)",
581
+ },
582
+ summary: {
583
+ type: "string",
584
+ description: "One-line summary of review findings",
585
+ },
586
+ next_action: {
587
+ type: "string",
588
+ description: "Follow-up action required",
589
+ },
590
+ developer: {
591
+ type: "string",
592
+ description: "Developer name for tracking (default: unknown)",
593
+ default: "unknown",
594
+ },
595
+ severity: {
596
+ type: "string",
597
+ enum: ["blocker", "must-fix", "should-fix", "nit", "praise", "review"],
598
+ description: "Highest severity level (default: review)",
599
+ default: "review",
600
+ },
601
+ jira: {
602
+ type: "string",
603
+ description: "Jira ticket ID if applicable",
604
+ },
605
+ blockers: {
606
+ type: "array",
607
+ items: { type: "string" },
608
+ description: "List of blockers",
609
+ },
610
+ },
611
+ required: ["pr_number", "module", "summary", "next_action"],
612
+ },
613
+ },
614
+ {
615
+ name: "executor_modes",
616
+ description:
617
+ "List available executor modes (triage, deep_review, pattern_mining, mentorship)",
618
+ inputSchema: {
619
+ type: "object",
620
+ properties: {},
621
+ },
622
+ },
623
+ // ─────────────────────────────────────────────────────────────────
624
+ // LexRunner Run Management Tools
625
+ // ─────────────────────────────────────────────────────────────────
626
+ {
627
+ name: "start_run",
628
+ description: "Start a new LexRunner procedure run and return a runId",
629
+ inputSchema: {
630
+ type: "object",
631
+ properties: {
632
+ mode: {
633
+ type: "string",
634
+ description: "Persona mode (e.g., 'senior-dev', 'eager-pm')",
635
+ },
636
+ procedure: {
637
+ type: "string",
638
+ description: "Procedure identifier (e.g., 'merge-weave-main', 'pr-review')",
639
+ },
640
+ repo: {
641
+ type: "string",
642
+ description: "Repository in 'owner/repo' format",
643
+ },
644
+ task: {
645
+ type: "string",
646
+ description: "Human-readable task description",
647
+ },
648
+ params: {
649
+ type: "object",
650
+ description: "Procedure-specific parameters",
651
+ },
652
+ },
653
+ required: ["mode", "procedure", "repo"],
654
+ },
655
+ },
656
+ {
657
+ name: "get_status",
658
+ description: "Get current run state, summary, and next available actions",
659
+ inputSchema: {
660
+ type: "object",
661
+ properties: {
662
+ runId: {
663
+ type: "string",
664
+ description: "Unique run identifier",
665
+ },
666
+ },
667
+ required: ["runId"],
668
+ },
669
+ },
670
+ {
671
+ name: "list_artifacts",
672
+ description: "List runs from the store with optional filtering",
673
+ inputSchema: {
674
+ type: "object",
675
+ properties: {
676
+ limit: {
677
+ type: "number",
678
+ description: "Maximum number of runs to return",
679
+ },
680
+ offset: {
681
+ type: "number",
682
+ description: "Number of runs to skip (for pagination)",
683
+ },
684
+ state: {
685
+ type: "string",
686
+ enum: ["pending", "running", "completed", "failed", "aborted"],
687
+ description: "Filter by run state",
688
+ },
689
+ },
690
+ },
691
+ },
692
+ {
693
+ name: "run_decision",
694
+ description: "Submit an LLM decision for a pending action in a run",
695
+ inputSchema: {
696
+ type: "object",
697
+ properties: {
698
+ runId: {
699
+ type: "string",
700
+ description: "Unique run identifier",
701
+ },
702
+ action: {
703
+ type: "string",
704
+ description: "Action to submit (must match a nextOptions[x].action)",
705
+ },
706
+ response: {
707
+ description: "Response data (validated against nextOptions[x].responseSchema)",
708
+ },
709
+ rationale: {
710
+ type: "string",
711
+ description: "Optional rationale for audit trail",
712
+ },
713
+ },
714
+ required: ["runId", "action", "response"],
715
+ },
716
+ },
717
+ // ─────────────────────────────────────────────────────────────────
718
+ // MCP/CLI Parity Tools (AX-004)
719
+ // ─────────────────────────────────────────────────────────────────
720
+ {
721
+ name: "discover",
722
+ description:
723
+ "Discover open pull requests from GitHub with optional dependency suggestions. Requires GITHUB_TOKEN environment variable.",
724
+ inputSchema: {
725
+ type: "object",
726
+ properties: {
727
+ owner: {
728
+ type: "string",
729
+ description: "GitHub repository owner",
730
+ },
731
+ repo: {
732
+ type: "string",
733
+ description: "GitHub repository name",
734
+ },
735
+ state: {
736
+ type: "string",
737
+ enum: ["open", "closed", "all"],
738
+ description: "PR state filter (default: open)",
739
+ default: "open",
740
+ },
741
+ suggest: {
742
+ type: "boolean",
743
+ description: "Generate dependency suggestions using heuristics",
744
+ default: false,
745
+ },
746
+ },
747
+ },
748
+ },
749
+ {
750
+ name: "weave_status",
751
+ description: "Show current execution status and merge eligibility for a plan",
752
+ inputSchema: {
753
+ type: "object",
754
+ properties: {
755
+ planFile: {
756
+ type: "string",
757
+ description: "Path to plan.json file (default: plan.json)",
758
+ default: "plan.json",
759
+ },
760
+ },
761
+ },
762
+ },
763
+ {
764
+ name: "doctor",
765
+ description:
766
+ "Run environment and configuration sanity checks with optional hostility scoring",
767
+ inputSchema: {
768
+ type: "object",
769
+ properties: {
770
+ environmentQuality: {
771
+ type: "boolean",
772
+ description: "Include environmental hostility scoring in the check",
773
+ default: false,
774
+ },
775
+ },
776
+ },
777
+ },
778
+ {
779
+ name: "merge_order",
780
+ description: "Compute dependency levels and merge order using Kahn's algorithm",
781
+ inputSchema: {
782
+ type: "object",
783
+ properties: {
784
+ planFile: {
785
+ type: "string",
786
+ description: "Path to plan.json file (default: plan.json)",
787
+ default: "plan.json",
788
+ },
789
+ },
790
+ },
791
+ },
792
+ {
793
+ name: "config_show",
794
+ description: "Display configuration with precedence chain and provenance",
795
+ inputSchema: {
796
+ type: "object",
797
+ properties: {
798
+ key: {
799
+ type: "string",
800
+ description: "Show specific configuration key",
801
+ },
802
+ },
803
+ },
804
+ },
805
+ // ─────────────────────────────────────────────────────────────────
806
+ // Workflow Guidance Tools (LPR-037)
807
+ // ─────────────────────────────────────────────────────────────────
808
+ {
809
+ name: "workflow_guide",
810
+ description:
811
+ "Get context-aware workflow guidance for the current phase. " +
812
+ "Provides next steps, common issues, and recommendations.",
813
+ inputSchema: {
814
+ type: "object",
815
+ properties: {
816
+ phase: {
817
+ type: "string",
818
+ enum: [
819
+ "initial",
820
+ "post-plan-creation",
821
+ "post-gates-run",
822
+ "pre-merge",
823
+ "post-merge",
824
+ "error-recovery",
825
+ ],
826
+ description: "Current workflow phase to get guidance for",
827
+ },
828
+ },
829
+ required: ["phase"],
830
+ },
831
+ },
832
+ // ─────────────────────────────────────────────────────────────────
833
+ // Governance Metrics Tools (Wave 3)
834
+ // ─────────────────────────────────────────────────────────────────
835
+ {
836
+ name: "metrics",
837
+ description: "Get current governance metrics snapshot for observability dashboards",
838
+ inputSchema: {
839
+ type: "object",
840
+ properties: {
841
+ filter: {
842
+ type: "string",
843
+ description: "Filter metrics by name pattern (e.g., 'turn_cost', 'tier')",
844
+ },
845
+ format: {
846
+ type: "string",
847
+ enum: ["json", "prometheus"],
848
+ description: "Output format (default: json)",
849
+ default: "json",
850
+ },
851
+ },
852
+ },
853
+ },
854
+ // ─────────────────────────────────────────────────────────────────
855
+ // Task Handoff Tools (ADR-007)
856
+ // ─────────────────────────────────────────────────────────────────
857
+ {
858
+ name: "create_task_snapshot",
859
+ description:
860
+ "Create a task snapshot for agent handoff (ADR-007). Prepares work for external agent with failure info, target files, and verification command.",
861
+ inputSchema: {
862
+ type: "object",
863
+ properties: {
864
+ taskId: {
865
+ type: "string",
866
+ description: "Optional task ID (auto-generated if not provided)",
867
+ },
868
+ procedure: {
869
+ type: "string",
870
+ description: "Procedure identifier (e.g., 'post-merge-fix', 'fanout-issue')",
871
+ },
872
+ determinism: {
873
+ type: "string",
874
+ enum: ["D1", "D2", "D3"],
875
+ description: "Determinism level (default: D1)",
876
+ default: "D1",
877
+ },
878
+ failureMessage: {
879
+ type: "string",
880
+ description: "Short error description",
881
+ },
882
+ failureFileRel: {
883
+ type: "string",
884
+ description: "Repo-relative path to failed file",
885
+ },
886
+ failureLine: {
887
+ type: "number",
888
+ description: "Line number if available",
889
+ },
890
+ runnerOutputSnip: {
891
+ type: "string",
892
+ description: "Actual test runner output snippet",
893
+ },
894
+ failureExcerpt: {
895
+ type: "string",
896
+ description: "Code context around failure",
897
+ },
898
+ targetFiles: {
899
+ type: "array",
900
+ items: { type: "string" },
901
+ description: "Repo-relative paths of files to modify",
902
+ },
903
+ verificationCmd: {
904
+ type: "string",
905
+ description: "Command to run for verification",
906
+ },
907
+ expectedExitCode: {
908
+ type: "number",
909
+ description: "Expected exit code (default: 0)",
910
+ default: 0,
911
+ },
912
+ repoRoot: {
913
+ type: "string",
914
+ description: "Absolute path to repo root (auto-detected if not provided)",
915
+ },
916
+ repoId: {
917
+ type: "string",
918
+ description:
919
+ "Repository identifier in owner/repo format (auto-detected if not provided)",
920
+ },
921
+ commitSha: {
922
+ type: "string",
923
+ description: "Git commit SHA (auto-detected if not provided)",
924
+ },
925
+ },
926
+ required: [
927
+ "procedure",
928
+ "failureMessage",
929
+ "failureFileRel",
930
+ "runnerOutputSnip",
931
+ "targetFiles",
932
+ "verificationCmd",
933
+ ],
934
+ },
935
+ },
936
+ {
937
+ name: "submit_task_receipt",
938
+ description:
939
+ "Submit a task receipt after agent completes work (ADR-007). Returns acknowledgment and engine verification status.",
940
+ inputSchema: {
941
+ type: "object",
942
+ properties: {
943
+ receipt: {
944
+ type: "object",
945
+ description: "TaskReceipt_v1 JSON object",
946
+ },
947
+ },
948
+ required: ["receipt"],
949
+ },
950
+ },
951
+ {
952
+ name: "get_task_status",
953
+ description:
954
+ "Get current task state (ADR-007). Returns snapshot, receipt, and verification info.",
955
+ inputSchema: {
956
+ type: "object",
957
+ properties: {
958
+ taskId: {
959
+ type: "string",
960
+ description: "Unique task identifier",
961
+ },
962
+ },
963
+ required: ["taskId"],
964
+ },
965
+ },
966
+ {
967
+ name: "list_pending_tasks",
968
+ description: "List pending task snapshots (ADR-007). Used by PM agent to see work queue.",
969
+ inputSchema: {
970
+ type: "object",
971
+ properties: {
972
+ procedure: {
973
+ type: "string",
974
+ description: "Filter by procedure identifier",
975
+ },
976
+ determinism: {
977
+ type: "string",
978
+ enum: ["D1", "D2", "D3"],
979
+ description: "Filter by determinism level",
980
+ },
981
+ limit: {
982
+ type: "number",
983
+ description: "Maximum tasks to return",
984
+ },
985
+ },
986
+ },
987
+ },
988
+ // ─────────────────────────────────────────────────────────────────
989
+ // Fanout AX Tools — D0/D1 Pipeline (Epic #654 Layer 2)
990
+ // ─────────────────────────────────────────────────────────────────
991
+ {
992
+ name: "fanout_harvest",
993
+ description:
994
+ "D0: Harvest external state from GitHub into a deterministic, replayable HarvestBundle. " +
995
+ "Fetches PRs, issues, CI status, review status, and pins all SHAs at fetch time. " +
996
+ "Requires GITHUB_TOKEN environment variable.",
997
+ inputSchema: {
998
+ type: "object",
999
+ properties: {
1000
+ owner: {
1001
+ type: "string",
1002
+ description:
1003
+ "GitHub repository owner (auto-detected from git remote if not provided)",
1004
+ },
1005
+ repo: {
1006
+ type: "string",
1007
+ description:
1008
+ "GitHub repository name (auto-detected from git remote if not provided)",
1009
+ },
1010
+ state: {
1011
+ type: "string",
1012
+ enum: ["open", "closed", "all"],
1013
+ description: "PR state filter (default: open)",
1014
+ default: "open",
1015
+ },
1016
+ includeIssues: {
1017
+ type: "boolean",
1018
+ description: "Include issues in harvest (default: false)",
1019
+ default: false,
1020
+ },
1021
+ maxBody: {
1022
+ type: "number",
1023
+ description: "Max body length before truncation (default: 4096)",
1024
+ default: 4096,
1025
+ },
1026
+ githubToken: {
1027
+ type: "string",
1028
+ description: "GitHub API token (or use GITHUB_TOKEN env var)",
1029
+ },
1030
+ },
1031
+ },
1032
+ },
1033
+ {
1034
+ name: "fanout_analyze",
1035
+ description:
1036
+ "D1: Analyze a HarvestBundle into a deterministic AnalysisPool with evidence IDs. " +
1037
+ "Pure computation with no side effects. Same input → identical output. " +
1038
+ "Extracts entities, relations, conflicts, and blockers.",
1039
+ inputSchema: {
1040
+ type: "object",
1041
+ properties: {
1042
+ harvestBundle: {
1043
+ type: "object",
1044
+ description: "HarvestBundle JSON object from fanout_harvest (preferred)",
1045
+ },
1046
+ fromFile: {
1047
+ type: "string",
1048
+ description:
1049
+ "Path to harvest bundle JSON file (alternative to harvestBundle object)",
1050
+ },
1051
+ },
1052
+ },
1053
+ },
1054
+ ],
1055
+ };
1056
+ });
1057
+
1058
+ // Handle tool calls
1059
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1060
+ const { name, arguments: args } = request.params;
1061
+
1062
+ switch (name) {
1063
+ // Plan tools
1064
+ case "plan_create":
1065
+ return await handlePlanCreate(args as PlanCreateArgs);
1066
+
1067
+ case "pr_list":
1068
+ return await handlePrList(args as PrListArgs);
1069
+
1070
+ case "plan_validate":
1071
+ return await handlePlanValidate(args as PlanValidateArgs);
1072
+
1073
+ case "plan_analyze":
1074
+ return await handlePlanAnalyze(args as PlanAnalyzeArgs);
1075
+
1076
+ // Gate tools
1077
+ case "gates_run":
1078
+ return await handleGatesRun(args as GatesRunArgs);
1079
+
1080
+ // Weave tools
1081
+ case "merge_apply":
1082
+ return await handleMergeApply(args as MergeApplyArgs);
1083
+
1084
+ case "discover":
1085
+ return await handleDiscover(
1086
+ args as {
1087
+ owner?: string;
1088
+ repo?: string;
1089
+ state?: string;
1090
+ suggest?: boolean;
1091
+ }
1092
+ );
1093
+
1094
+ case "weave_status":
1095
+ return await handleStatus(args as { planFile?: string });
1096
+
1097
+ case "merge_order":
1098
+ return await handleMergeOrder(args as { planFile?: string });
1099
+
1100
+ // Workspace tools
1101
+ case "local_init":
1102
+ return await handleLocalInit(args as InitLocalArgs);
1103
+
1104
+ case "profile_resolve":
1105
+ return await handleProfileResolve(args as ProfileResolveArgs);
1106
+
1107
+ case "doctor":
1108
+ return await handleDoctor(args as { environmentQuality?: boolean });
1109
+
1110
+ // Core tools
1111
+ case "health":
1112
+ return await handleHealth(args as { includeMetrics?: boolean });
1113
+
1114
+ case "config_show":
1115
+ return await handleConfigShow(args as { key?: string });
1116
+
1117
+ case "workflow_guide":
1118
+ return await handleWorkflowGuide(args as WorkflowGuideArgs);
1119
+
1120
+ case "metrics":
1121
+ return await handleMetrics(args as { filter?: string; format?: string });
1122
+
1123
+ // Executor tools (Senior Dev)
1124
+ case "executor_prepare_context":
1125
+ return await handleSeniorDevPrepareContext(args as unknown as PrepareContextInput);
1126
+
1127
+ case "executor_recall_context":
1128
+ return await handleSeniorDevRecallContext(args as unknown as RecallContextInput);
1129
+
1130
+ case "executor_capture_frame":
1131
+ return await handleSeniorDevCaptureFrame(args as unknown as CaptureFrameInput);
1132
+
1133
+ case "executor_modes":
1134
+ return await handleSeniorDevModes();
1135
+
1136
+ // Run management tools
1137
+ case "start_run":
1138
+ return await handleStartRun(args as unknown as StartRunInput, runStore);
1139
+
1140
+ case "get_status":
1141
+ return await handleGetStatus(args as unknown as GetStatusInput, runStore);
1142
+
1143
+ case "list_artifacts":
1144
+ return await handleListRuns(args as unknown as ListRunsInput, runStore);
1145
+
1146
+ case "run_decision":
1147
+ return await handleSubmitDecision(args as unknown as SubmitDecisionInput);
1148
+
1149
+ // Task Handoff tools (ADR-007)
1150
+ case "create_task_snapshot":
1151
+ return await handleCreateTaskSnapshot(args as unknown as CreateTaskSnapshotArgs);
1152
+
1153
+ case "submit_task_receipt":
1154
+ return await handleSubmitTaskReceipt(args as unknown as SubmitTaskReceiptArgs);
1155
+
1156
+ case "get_task_status":
1157
+ return await handleGetTaskStatus(args as unknown as GetTaskStatusArgs);
1158
+
1159
+ case "list_pending_tasks":
1160
+ return await handleListPendingTasks(args as unknown as ListPendingTasksArgs);
1161
+
1162
+ // Fanout AX tools (Epic #654 Layer 2)
1163
+ case "fanout_harvest":
1164
+ return await handleFanoutHarvest(args as unknown as FanoutHarvestArgs);
1165
+
1166
+ case "fanout_analyze":
1167
+ return await handleFanoutAnalyze(args as unknown as FanoutAnalyzeArgs);
1168
+
1169
+ default:
1170
+ throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
1171
+ }
1172
+ });
1173
+
1174
+ return server;
1175
+ }
1176
+
1177
+ /**
1178
+ * Check if GitHub token is available and throw helpful error if not
1179
+ */
1180
+ function ensureGitHubToken(providedToken?: string): void {
1181
+ const token = providedToken || process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
1182
+
1183
+ if (!token) {
1184
+ const axError = githubApiError({
1185
+ status: 401,
1186
+ message:
1187
+ "GitHub authentication required. Set GITHUB_TOKEN environment variable.\n" +
1188
+ "\n" +
1189
+ "To fix:\n" +
1190
+ " export GITHUB_TOKEN=ghp_...\n" +
1191
+ "\n" +
1192
+ "See: https://github.com/Guffawaffle/lexrunner#authentication",
1193
+ });
1194
+ throwMcpAXError(ErrorCode.InvalidRequest, axError);
1195
+ }
1196
+ }
1197
+
1198
+ /**
1199
+ * Handle plan.create tool
1200
+ */
1201
+ async function handlePlanCreate(
1202
+ args: PlanCreateArgs
1203
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
1204
+ try {
1205
+ const env = getMCPEnvironment();
1206
+
1207
+ // Resolve profile and validate write permissions
1208
+ const resolved = resolveProfile(undefined, process.cwd());
1209
+ const profilePath = resolved.path;
1210
+ const role = resolved.manifest.role;
1211
+
1212
+ let plan;
1213
+ let inputs = null;
1214
+ let autoDetectedGitHubMode = false;
1215
+
1216
+ // Auto-detect GitHub mode from scope.yml if fromGithub not explicitly set
1217
+ if (!args.fromGithub) {
1218
+ const detection = detectGitHubMode(profilePath);
1219
+ if (detection.shouldUseGitHub) {
1220
+ autoDetectedGitHubMode = true;
1221
+ // Merge scope.yml filters with args (args take precedence)
1222
+ args.fromGithub = true;
1223
+ if (!args.query && detection.scopeConfig?.query) {
1224
+ args.query = detection.scopeConfig.query;
1225
+ }
1226
+ if (
1227
+ !args.labels &&
1228
+ detection.scopeConfig?.labels &&
1229
+ detection.scopeConfig.labels.length > 0
1230
+ ) {
1231
+ args.labels = detection.scopeConfig.labels;
1232
+ }
1233
+ if (!args.target && detection.scopeConfig?.target) {
1234
+ args.target = detection.scopeConfig.target;
1235
+ }
1236
+
1237
+ console.error("[mcp:plan.create] Auto-detected GitHub mode from scope.yml filters");
1238
+ }
1239
+ }
1240
+
1241
+ if (args.fromGithub) {
1242
+ // Check for GitHub authentication before making API calls
1243
+ ensureGitHubToken(args.githubToken);
1244
+
1245
+ // Parse required gates if provided
1246
+ const requiredGates = args.requiredGates || ["lint", "typecheck", "test"];
1247
+
1248
+ // Parse max workers if provided
1249
+ const maxWorkers = args.maxWorkers || 2;
1250
+
1251
+ // Check for multi-repo mode (issue #677)
1252
+ if (args.repos && args.repos.length > 0) {
1253
+ // Multi-repo mode: discover PRs from multiple repositories
1254
+ console.error(`[mcp:plan.create] Multi-repo mode: ${args.repos.length} repositories`);
1255
+
1256
+ plan = await generateMultiRepoPlan(args.repos, {
1257
+ query: args.query,
1258
+ labels: args.labels,
1259
+ excludePRs: args.excludePRs,
1260
+ includeDrafts: args.includeDrafts,
1261
+ target: args.target,
1262
+ githubToken: args.githubToken,
1263
+ policy: {
1264
+ requiredGates,
1265
+ maxWorkers,
1266
+ },
1267
+ });
1268
+
1269
+ // Log discovery results to stderr
1270
+ const repoList = args.repos.map((r) => `${r.owner}/${r.repo}`).join(", ");
1271
+ const filterInfo = args.labels ? ` labels=${args.labels.join(",")}` : "";
1272
+ console.error(
1273
+ `[mcp:plan.create] repos=[${repoList}]${filterInfo} discovered=${plan.items.length} PRs`
1274
+ );
1275
+
1276
+ if (plan.items.length === 0) {
1277
+ console.error(
1278
+ `[mcp:plan.create] Warning: No PRs found matching criteria. Check filters and repository state.`
1279
+ );
1280
+ } else {
1281
+ const prNames = plan.items.map((item) => item.name).join(", ");
1282
+ console.error(`[mcp:plan.create] PRs included: ${prNames}`);
1283
+ }
1284
+ } else {
1285
+ // Single-repo mode (backward compatible)
1286
+ const client = await createGitHubClient({
1287
+ token: args.githubToken,
1288
+ owner: args.owner,
1289
+ repo: args.repo,
1290
+ });
1291
+
1292
+ // Generate plan from GitHub
1293
+ plan = await generatePlanFromGitHub(client, {
1294
+ query: args.query,
1295
+ labels: args.labels,
1296
+ excludePRs: args.excludePRs,
1297
+ includeDrafts: args.includeDrafts,
1298
+ target: args.target,
1299
+ policy: {
1300
+ requiredGates,
1301
+ maxWorkers,
1302
+ },
1303
+ });
1304
+
1305
+ // Log discovery results to stderr
1306
+ const repoDiag = `${client.getOwner()}/${client.getRepo()}`;
1307
+ const filterInfo = args.labels ? ` labels=${args.labels.join(",")}` : "";
1308
+ const queryInfo = args.query ? ` query="${args.query}"` : "";
1309
+ console.error(
1310
+ `[mcp:plan.create] repo=${repoDiag}${filterInfo}${queryInfo} discovered=${plan.items.length} PRs`
1311
+ );
1312
+
1313
+ if (plan.items.length === 0) {
1314
+ console.error(
1315
+ `[mcp:plan.create] Warning: No PRs found matching criteria. Check filters and repository state.`
1316
+ );
1317
+ } else {
1318
+ const prNumbers = plan.items.map((item) => item.name).join(", ");
1319
+ console.error(`[mcp:plan.create] PRs included: ${prNumbers}`);
1320
+ }
1321
+ }
1322
+ } else {
1323
+ // Traditional mode: load from configuration files
1324
+ inputs = loadInputs(profilePath);
1325
+ plan = generatePlan(inputs);
1326
+ }
1327
+
1328
+ // Determine output directory
1329
+ const outDir = args.outDir || path.join(profilePath, "runner");
1330
+
1331
+ // Validate write operation is allowed
1332
+ validateWriteOperation(profilePath, role, "write plan artifacts");
1333
+
1334
+ // Ensure output directory exists
1335
+ if (!fs.existsSync(outDir)) {
1336
+ fs.mkdirSync(outDir, { recursive: true });
1337
+ }
1338
+
1339
+ // Write plan.json
1340
+ const planPath = path.join(outDir, "plan.json");
1341
+ const planJson = canonicalJSONStringify(plan);
1342
+ fs.writeFileSync(planPath, planJson + "\n");
1343
+
1344
+ // Generate snapshot - use GitHub snapshot for GitHub mode
1345
+ let snapshot: string;
1346
+ if (args.fromGithub) {
1347
+ snapshot = generateGitHubSnapshot(plan);
1348
+ } else {
1349
+ // In traditional mode, inputs is guaranteed to be set
1350
+ if (!inputs) {
1351
+ const axError = mcpToolError(
1352
+ ErrorCodes.INTERNAL_ERROR,
1353
+ "Internal error: inputs not loaded in traditional mode",
1354
+ { tool: "plan.create", operation: "generate snapshot" }
1355
+ );
1356
+ throwMcpAXError(ErrorCode.InternalError, axError);
1357
+ }
1358
+ snapshot = generateSnapshot(plan, inputs);
1359
+ }
1360
+ const snapshotPath = path.join(outDir, "snapshot.md");
1361
+ fs.writeFileSync(snapshotPath, snapshot);
1362
+
1363
+ const result: PlanCreateResult = {
1364
+ plan: plan,
1365
+ outDir: outDir,
1366
+ };
1367
+
1368
+ return {
1369
+ content: [
1370
+ {
1371
+ type: "text",
1372
+ text: JSON.stringify(result, null, 2),
1373
+ },
1374
+ ],
1375
+ };
1376
+ } catch (error) {
1377
+ if (error instanceof WriteProtectionError) {
1378
+ const axError = writeProtectionError(error.message, "plan.create");
1379
+ throwMcpAXError(ErrorCode.InvalidRequest, axError);
1380
+ }
1381
+ throwMcpToolError(ErrorCode.InternalError, "plan.create", error, "create plan");
1382
+ }
1383
+ }
1384
+
1385
+ /**
1386
+ * Handle pr_list tool
1387
+ * Lists pull requests from GitHub without creating a plan
1388
+ */
1389
+ async function handlePrList(
1390
+ args: PrListArgs
1391
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
1392
+ try {
1393
+ // Check for GitHub authentication early
1394
+ ensureGitHubToken(args.githubToken);
1395
+
1396
+ // Create GitHub client
1397
+ const client = await createGitHubClient({
1398
+ token: args.githubToken,
1399
+ owner: args.owner,
1400
+ repo: args.repo,
1401
+ });
1402
+
1403
+ // Validate repository access
1404
+ const repoInfo = await client.validateRepository();
1405
+
1406
+ // Get state parameter (default to "open")
1407
+ const state = args.state || "open";
1408
+
1409
+ // Discover PRs based on query/filters
1410
+ const prs = await client.listOpenPRs({
1411
+ state,
1412
+ labels: args.labels,
1413
+ ...(args.query ? { query: args.query } : {}),
1414
+ });
1415
+
1416
+ // Default behavior: include drafts unless explicitly disabled
1417
+ const includeDrafts = args.includeDrafts === undefined ? true : Boolean(args.includeDrafts);
1418
+ const filteredPRs = includeDrafts ? prs : prs.filter((pr) => !pr.draft);
1419
+
1420
+ // Exclude specific PRs if requested
1421
+ const excludePRs = args.excludePRs || [];
1422
+ const finalPRs =
1423
+ excludePRs.length > 0
1424
+ ? filteredPRs.filter((pr) => !excludePRs.includes(pr.number))
1425
+ : filteredPRs;
1426
+
1427
+ // Transform to result format
1428
+ const result: PrListResult = {
1429
+ pullRequests: finalPRs.map((pr) => ({
1430
+ number: pr.number,
1431
+ title: pr.title,
1432
+ branch: pr.head.ref,
1433
+ author: pr.user.login,
1434
+ labels: pr.labels.map((l) => l.name),
1435
+ sha: pr.head.sha,
1436
+ draft: pr.draft,
1437
+ })),
1438
+ total: prs.length,
1439
+ filtered: finalPRs.length,
1440
+ owner: client.getOwner(),
1441
+ repo: client.getRepo(),
1442
+ };
1443
+
1444
+ // Log discovery results to stderr
1445
+ const repoDiag = `${client.getOwner()}/${client.getRepo()}`;
1446
+ const filterInfo = args.labels ? ` labels=${args.labels.join(",")}` : "";
1447
+ const queryInfo = args.query ? ` query="${args.query}"` : "";
1448
+ console.error(
1449
+ `[mcp:pr_list] repo=${repoDiag}${filterInfo}${queryInfo} found=${result.filtered}/${result.total} PRs`
1450
+ );
1451
+
1452
+ return {
1453
+ content: [
1454
+ {
1455
+ type: "text",
1456
+ text: JSON.stringify(result, null, 2),
1457
+ },
1458
+ ],
1459
+ };
1460
+ } catch (error) {
1461
+ if (error instanceof GitHubAPIError) {
1462
+ const axError = githubApiError({
1463
+ message: error.message,
1464
+ });
1465
+ throwMcpAXError(ErrorCode.InternalError, axError);
1466
+ }
1467
+ throwMcpToolError(ErrorCode.InternalError, "pr_list", error, "list pull requests");
1468
+ }
1469
+ }
1470
+
1471
+ /**
1472
+ * Handle plan_validate tool
1473
+ * Validates a plan.json file for schema compliance and logical consistency
1474
+ */
1475
+ async function handlePlanValidate(
1476
+ args: PlanValidateArgs
1477
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
1478
+ try {
1479
+ let planContent: string;
1480
+ let planPath: string | undefined;
1481
+
1482
+ // Get plan content either from file or direct content
1483
+ if (args.planContent) {
1484
+ planContent = args.planContent;
1485
+ } else {
1486
+ // Resolve plan file path
1487
+ if (args.planFile) {
1488
+ planPath = args.planFile;
1489
+ } else {
1490
+ const resolved = resolveProfile(undefined, process.cwd());
1491
+ planPath = path.join(resolved.path, "runner", "plan.json");
1492
+ }
1493
+
1494
+ // Check if plan file exists
1495
+ if (!fs.existsSync(planPath)) {
1496
+ throwMcpAXError(ErrorCode.InvalidParams, planNotFoundError(planPath));
1497
+ }
1498
+
1499
+ planContent = fs.readFileSync(planPath, "utf-8");
1500
+ }
1501
+
1502
+ // Try to validate the plan
1503
+ const result: PlanValidateResult = {
1504
+ valid: true,
1505
+ warnings: [],
1506
+ };
1507
+
1508
+ try {
1509
+ const plan = loadPlan(planContent);
1510
+
1511
+ // Basic validation passed
1512
+ result.plan = {
1513
+ schemaVersion: plan.schemaVersion,
1514
+ target: plan.target,
1515
+ itemCount: plan.items.length,
1516
+ };
1517
+
1518
+ // Additional logical validations
1519
+ if (plan.items.length === 0) {
1520
+ result.warnings?.push("Plan contains no items");
1521
+ }
1522
+
1523
+ // Check for duplicate item names
1524
+ const names = new Set<string>();
1525
+ const duplicates: string[] = [];
1526
+ for (const item of plan.items) {
1527
+ if (names.has(item.name)) {
1528
+ duplicates.push(item.name);
1529
+ }
1530
+ names.add(item.name);
1531
+ }
1532
+ if (duplicates.length > 0) {
1533
+ result.valid = false;
1534
+ result.errors = result.errors || [];
1535
+ result.errors.push({
1536
+ path: "items",
1537
+ message: `Duplicate item names found: ${duplicates.join(", ")}`,
1538
+ code: "DUPLICATE_NAMES",
1539
+ });
1540
+ }
1541
+
1542
+ console.error(
1543
+ `[mcp:plan_validate] validated plan with ${plan.items.length} items, valid=${result.valid}`
1544
+ );
1545
+ } catch (error) {
1546
+ result.valid = false;
1547
+ result.errors = [];
1548
+
1549
+ if (error instanceof AXErrorException) {
1550
+ result.errors.push({
1551
+ path: "root",
1552
+ message: error.message,
1553
+ code: error.axError.code,
1554
+ });
1555
+ } else if (error instanceof Error) {
1556
+ result.errors.push({
1557
+ path: "root",
1558
+ message: error.message,
1559
+ });
1560
+ }
1561
+
1562
+ console.error(`[mcp:plan_validate] validation failed: ${error}`);
1563
+ }
1564
+
1565
+ return {
1566
+ content: [
1567
+ {
1568
+ type: "text",
1569
+ text: JSON.stringify(result, null, 2),
1570
+ },
1571
+ ],
1572
+ };
1573
+ } catch (error) {
1574
+ throwMcpToolError(ErrorCode.InternalError, "plan_validate", error, "validate plan");
1575
+ }
1576
+ }
1577
+
1578
+ /**
1579
+ * Handle plan_analyze tool
1580
+ * Analyzes a plan for conflicts and dependency issues (dry-run)
1581
+ */
1582
+ async function handlePlanAnalyze(
1583
+ args: PlanAnalyzeArgs
1584
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
1585
+ try {
1586
+ let planPath: string;
1587
+
1588
+ // Resolve plan file path
1589
+ if (args.planFile) {
1590
+ planPath = args.planFile;
1591
+ } else {
1592
+ const resolved = resolveProfile(undefined, process.cwd());
1593
+ planPath = path.join(resolved.path, "runner", "plan.json");
1594
+ }
1595
+
1596
+ // Check if plan file exists
1597
+ if (!fs.existsSync(planPath)) {
1598
+ throwMcpAXError(ErrorCode.InvalidParams, planNotFoundError(planPath));
1599
+ }
1600
+
1601
+ // Load and validate plan
1602
+ const planContent = fs.readFileSync(planPath, "utf-8");
1603
+ const plan = loadPlan(planContent);
1604
+
1605
+ const result: PlanAnalyzeResult = {
1606
+ valid: true,
1607
+ conflicts: [],
1608
+ dependencies: {
1609
+ total: 0,
1610
+ },
1611
+ summary: {
1612
+ totalItems: plan.items.length,
1613
+ maxParallelism: 0,
1614
+ hasIssues: false,
1615
+ },
1616
+ };
1617
+
1618
+ // Count dependencies
1619
+ for (const item of plan.items) {
1620
+ if (item.deps && item.deps.length > 0) {
1621
+ result.dependencies!.total += item.deps.length;
1622
+ }
1623
+ }
1624
+
1625
+ // Try to compute merge order (will detect cycles and unknown deps)
1626
+ try {
1627
+ const levels = computeMergeOrder(plan);
1628
+ result.mergeOrder = levels;
1629
+ const levelSizes = levels.map((l) => l.length);
1630
+ result.summary.maxParallelism = levelSizes.length > 0 ? Math.max(0, ...levelSizes) : 0;
1631
+
1632
+ console.error(
1633
+ `[mcp:plan_analyze] analyzed plan: ${plan.items.length} items, ${levels.length} levels, max parallelism=${result.summary.maxParallelism}`
1634
+ );
1635
+ } catch (error) {
1636
+ result.valid = false;
1637
+ result.summary.hasIssues = true;
1638
+
1639
+ if (error instanceof CycleError) {
1640
+ const cycle = (error.axError.context as unknown as CycleDetectedContext).cycle;
1641
+ result.dependencies!.cycles = [[...cycle]];
1642
+ result.conflicts?.push({
1643
+ type: "cycle",
1644
+ message: `Dependency cycle detected: ${cycle.join(" -> ")}`,
1645
+ items: cycle,
1646
+ });
1647
+ console.error(`[mcp:plan_analyze] cycle detected: ${cycle.join(" -> ")}`);
1648
+ } else if (error instanceof UnknownDependencyError) {
1649
+ const ctx = error.axError.context as unknown as UnknownDependencyContext;
1650
+ result.dependencies!.unknown = [ctx.dependency];
1651
+ result.conflicts?.push({
1652
+ type: "unknown_dependency",
1653
+ message: `Unknown dependency: ${ctx.dependency} referenced by ${ctx.item}`,
1654
+ items: [ctx.item, ctx.dependency],
1655
+ });
1656
+ console.error(`[mcp:plan_analyze] unknown dependency: ${ctx.dependency}`);
1657
+ } else {
1658
+ result.conflicts?.push({
1659
+ type: "analysis_error",
1660
+ message: error instanceof Error ? error.message : String(error),
1661
+ });
1662
+ }
1663
+ }
1664
+
1665
+ return {
1666
+ content: [
1667
+ {
1668
+ type: "text",
1669
+ text: JSON.stringify(result, null, 2),
1670
+ },
1671
+ ],
1672
+ };
1673
+ } catch (error) {
1674
+ throwMcpToolError(ErrorCode.InternalError, "plan_analyze", error, "analyze plan");
1675
+ }
1676
+ }
1677
+
1678
+ /**
1679
+ * Handle gates.run tool
1680
+ */
1681
+ async function handleGatesRun(
1682
+ args: GatesRunArgs
1683
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
1684
+ try {
1685
+ const env = getMCPEnvironment();
1686
+
1687
+ let planPath: string;
1688
+ let outDirBase: string;
1689
+
1690
+ // Use planFile if provided, otherwise fall back to internal state
1691
+ if (args.planFile) {
1692
+ // Validate that the plan file exists
1693
+ if (!fs.existsSync(args.planFile)) {
1694
+ throwMcpAXError(ErrorCode.InvalidParams, planNotFoundError(args.planFile));
1695
+ }
1696
+
1697
+ planPath = args.planFile;
1698
+ // For external plans, use the plan file's directory as the base for output
1699
+ outDirBase = path.dirname(args.planFile);
1700
+ } else {
1701
+ // Resolve profile directory for internal state
1702
+ const resolved = resolveProfile(env.LEX_PR_PROFILE_DIR, process.cwd());
1703
+
1704
+ // Load plan from resolved profile directory
1705
+ planPath = path.join(resolved.path, "runner", "plan.json");
1706
+ if (!fs.existsSync(planPath)) {
1707
+ throwMcpAXError(ErrorCode.InvalidParams, planNotFoundError(planPath));
1708
+ }
1709
+
1710
+ outDirBase = path.join(resolved.path, "runner");
1711
+ }
1712
+
1713
+ let planContent: string;
1714
+ try {
1715
+ planContent = fs.readFileSync(planPath, "utf-8");
1716
+ } catch (error) {
1717
+ const axError = mcpToolError(
1718
+ ErrorCodes.PLAN_NOT_FOUND,
1719
+ `Failed to read plan file ${planPath}`,
1720
+ { tool: "gates.run", operation: "read plan file" }
1721
+ );
1722
+ throwMcpAXError(ErrorCode.InternalError, axError);
1723
+ }
1724
+
1725
+ const plan = loadPlan(planContent);
1726
+
1727
+ // Create execution state
1728
+ const executionState = new ExecutionState(plan);
1729
+
1730
+ // Determine output directory
1731
+ const outDir = args.outDir || path.join(outDirBase, "gates");
1732
+
1733
+ // Execute gates (this modifies executionState in place)
1734
+ await executeGatesWithPolicy(plan, executionState, outDir);
1735
+
1736
+ // Get results from execution state
1737
+ const results = executionState.getResults();
1738
+
1739
+ // Transform results to expected format
1740
+ const items = [];
1741
+ let allGreen = true;
1742
+
1743
+ for (const [itemName, nodeResult] of results) {
1744
+ // Filter by onlyItem if specified
1745
+ if (args.onlyItem && itemName !== args.onlyItem) {
1746
+ continue;
1747
+ }
1748
+
1749
+ // Filter gates by onlyGate if specified
1750
+ const gates =
1751
+ nodeResult.gates
1752
+ ?.filter((gate) => !args.onlyGate || gate.gate === args.onlyGate)
1753
+ .map((gate: any) => ({
1754
+ name: gate.gate,
1755
+ status: gate.status,
1756
+ })) || [];
1757
+
1758
+ const itemResult = {
1759
+ name: itemName,
1760
+ status: nodeResult.status || "unknown",
1761
+ gates: gates,
1762
+ };
1763
+
1764
+ items.push(itemResult);
1765
+
1766
+ if (nodeResult.status !== "pass") {
1767
+ allGreen = false;
1768
+ }
1769
+ }
1770
+
1771
+ const result: GatesRunResult = {
1772
+ items,
1773
+ allGreen,
1774
+ };
1775
+
1776
+ return {
1777
+ content: [
1778
+ {
1779
+ type: "text",
1780
+ text: JSON.stringify(result, null, 2),
1781
+ },
1782
+ ],
1783
+ };
1784
+ } catch (error) {
1785
+ // Check for plan not found specifically
1786
+ const message = error instanceof Error ? error.message : String(error);
1787
+ if (message.includes("Plan file not found") || message.includes("No plan found")) {
1788
+ throwMcpAXError(ErrorCode.InvalidParams, planNotFoundError(args.planFile));
1789
+ }
1790
+ throwMcpToolError(ErrorCode.InternalError, "gates.run", error, "run gates");
1791
+ }
1792
+ }
1793
+
1794
+ /**
1795
+ * Handle merge.apply tool
1796
+ */
1797
+ async function handleMergeApply(
1798
+ args: MergeApplyArgs
1799
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
1800
+ try {
1801
+ const env = getMCPEnvironment();
1802
+
1803
+ // Resolve profile directory first to check role
1804
+ const resolved = resolveProfile(env.LEX_PR_PROFILE_DIR, process.cwd());
1805
+
1806
+ // Validate CI environment if role is 'ci'
1807
+ validateCIEnvironment(resolved.manifest);
1808
+
1809
+ // Get CI-aware mutation policy
1810
+ const allowMutations = getCIMutationPolicy(resolved.manifest);
1811
+
1812
+ // Check if mutations are allowed
1813
+ if (!allowMutations && !args.dryRun) {
1814
+ const result: MergeApplyResult = {
1815
+ allowed: false,
1816
+ message: "Mutations not allowed. Set ALLOW_MUTATIONS=true or use dryRun=true.",
1817
+ };
1818
+
1819
+ return {
1820
+ content: [
1821
+ {
1822
+ type: "text",
1823
+ text: JSON.stringify(result, null, 2),
1824
+ },
1825
+ ],
1826
+ };
1827
+ }
1828
+
1829
+ // Load plan and execution state
1830
+ const planPath = path.join(resolved.path, "runner", "plan.json");
1831
+ if (!fs.existsSync(planPath)) {
1832
+ throwMcpAXError(ErrorCode.InvalidParams, planNotFoundError(planPath));
1833
+ }
1834
+
1835
+ const planContent = fs.readFileSync(planPath, "utf-8");
1836
+ const plan = loadPlan(planContent);
1837
+
1838
+ const executionState = new ExecutionState(plan);
1839
+
1840
+ // Load gate results from directory if available
1841
+ const gateResultsDir = path.join(resolved.path, "gate-results");
1842
+ if (fs.existsSync(gateResultsDir)) {
1843
+ try {
1844
+ const loadedCount = executionState.loadGateResultsFromDirectory(gateResultsDir);
1845
+ console.log(`📊 Loaded ${loadedCount} gate result(s) from ${gateResultsDir}`);
1846
+ } catch (error) {
1847
+ console.warn(
1848
+ `⚠️ Failed to load gate results from ${gateResultsDir}: ${error instanceof Error ? error.message : String(error)}`
1849
+ );
1850
+ }
1851
+ }
1852
+
1853
+ const evaluator = new MergeEligibilityEvaluator(plan, executionState);
1854
+ const decisions = evaluator.evaluateAllNodes();
1855
+
1856
+ const summary = evaluator.getMergeSummary();
1857
+
1858
+ const result: MergeApplyResult = {
1859
+ allowed: allowMutations && !args.dryRun,
1860
+ message: args.dryRun
1861
+ ? `Dry run: ${summary.eligible.length} items eligible, ${summary.failed.length} failed`
1862
+ : allowMutations
1863
+ ? `Ready to merge ${summary.eligible.length} eligible items`
1864
+ : "Mutations disabled. Set ALLOW_MUTATIONS=true to enable merging.",
1865
+ };
1866
+
1867
+ return {
1868
+ content: [
1869
+ {
1870
+ type: "text",
1871
+ text: JSON.stringify(result, null, 2),
1872
+ },
1873
+ ],
1874
+ };
1875
+ } catch (error) {
1876
+ const message = error instanceof Error ? error.message : String(error);
1877
+ if (message.includes("No plan found")) {
1878
+ throwMcpAXError(ErrorCode.InvalidParams, planNotFoundError());
1879
+ }
1880
+ throwMcpToolError(ErrorCode.InternalError, "merge.apply", error, "apply merge");
1881
+ }
1882
+ }
1883
+
1884
+ /**
1885
+ * Handle local.init tool
1886
+ */
1887
+ async function handleLocalInit(
1888
+ args: InitLocalArgs
1889
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
1890
+ try {
1891
+ const force = args.force ?? false;
1892
+ const result = initLocalOverlay(process.cwd(), force);
1893
+
1894
+ const output: InitLocalResult = {
1895
+ created: result.created,
1896
+ path: result.path,
1897
+ config: result.config,
1898
+ copiedFiles: result.copiedFiles,
1899
+ };
1900
+
1901
+ return {
1902
+ content: [
1903
+ {
1904
+ type: "text",
1905
+ text: JSON.stringify(output, null, 2),
1906
+ },
1907
+ ],
1908
+ };
1909
+ } catch (error) {
1910
+ throwMcpToolError(ErrorCode.InternalError, "local.init", error, "initialize local overlay");
1911
+ }
1912
+ }
1913
+
1914
+ /**
1915
+ * Handle profile.resolve tool
1916
+ */
1917
+ async function handleProfileResolve(
1918
+ args: ProfileResolveArgs
1919
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
1920
+ try {
1921
+ const env = getMCPEnvironment();
1922
+
1923
+ // Use profile directory from args, or fall back to env, or use resolveProfile default logic
1924
+ const profileDirOverride = args.profileDir || env.LEX_PR_PROFILE_DIR;
1925
+ const resolved = resolveProfile(profileDirOverride, process.cwd());
1926
+
1927
+ const output: ProfileResolveResult = {
1928
+ path: resolved.path,
1929
+ source: resolved.source,
1930
+ manifest: {
1931
+ role: resolved.manifest.role,
1932
+ name: resolved.manifest.name,
1933
+ version: resolved.manifest.version,
1934
+ },
1935
+ };
1936
+
1937
+ return {
1938
+ content: [
1939
+ {
1940
+ type: "text",
1941
+ text: JSON.stringify(output, null, 2),
1942
+ },
1943
+ ],
1944
+ };
1945
+ } catch (error) {
1946
+ throwMcpToolError(ErrorCode.InternalError, "profile.resolve", error, "resolve profile");
1947
+ }
1948
+ }
1949
+
1950
+ /**
1951
+ * Handle health check
1952
+ */
1953
+ async function handleHealth(args: {
1954
+ includeMetrics?: boolean;
1955
+ }): Promise<{ content: [{ type: "text"; text: string }] }> {
1956
+ const health = healthChecker.getHealth(args.includeMetrics || false);
1957
+
1958
+ return {
1959
+ content: [
1960
+ {
1961
+ type: "text",
1962
+ text: JSON.stringify(health, null, 2),
1963
+ },
1964
+ ],
1965
+ };
1966
+ }
1967
+
1968
+ /**
1969
+ * Main server startup
1970
+ */
1971
+ async function main() {
1972
+ // Create RunStore (will be closed on shutdown)
1973
+ const runStore = createRunStore();
1974
+ const server = createServer({ runStore });
1975
+ const transport = new StdioServerTransport();
1976
+
1977
+ // Connect the server to stdio transport
1978
+ await server.connect(transport);
1979
+
1980
+ // Log to stderr so it doesn't interfere with MCP protocol
1981
+ console.error("MCP server started for lexrunner");
1982
+
1983
+ // Keep the process alive by setting up event handlers
1984
+ // The event loop will keep running while the stdio transport is active
1985
+ process.stdin.resume();
1986
+
1987
+ // Handle graceful shutdown when stdin closes
1988
+ process.stdin.on("end", async () => {
1989
+ console.error("MCP server shutting down");
1990
+ try {
1991
+ await runStore.close();
1992
+ } catch (error) {
1993
+ console.error("Error closing RunStore:", error);
1994
+ }
1995
+ process.exit(0);
1996
+ });
1997
+
1998
+ // Never return - let the event loop handle everything
1999
+ await new Promise<void>(() => {
2000
+ // This promise never resolves, keeping the process alive
2001
+ });
2002
+ }
2003
+
2004
+ // ─────────────────────────────────────────────────────────────────────────────
2005
+ // Senior Dev Executor Handlers
2006
+ // ─────────────────────────────────────────────────────────────────────────────
2007
+
2008
+ /**
2009
+ * Handle senior-dev.prepare-context tool
2010
+ */
2011
+ async function handleSeniorDevPrepareContext(
2012
+ args: PrepareContextInput
2013
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
2014
+ try {
2015
+ const result = await prepareReviewContext(args);
2016
+ return {
2017
+ content: [
2018
+ {
2019
+ type: "text",
2020
+ text: JSON.stringify(result, null, 2),
2021
+ },
2022
+ ],
2023
+ };
2024
+ } catch (error) {
2025
+ throwMcpToolError(
2026
+ ErrorCode.InternalError,
2027
+ "senior-dev.prepare-context",
2028
+ error,
2029
+ "prepare review context"
2030
+ );
2031
+ }
2032
+ }
2033
+
2034
+ /**
2035
+ * Handle senior-dev.recall-context tool
2036
+ */
2037
+ async function handleSeniorDevRecallContext(
2038
+ args: RecallContextInput
2039
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
2040
+ try {
2041
+ const result = await recallSeniorDevContext(args);
2042
+ return {
2043
+ content: [
2044
+ {
2045
+ type: "text",
2046
+ text: JSON.stringify(result, null, 2),
2047
+ },
2048
+ ],
2049
+ };
2050
+ } catch (error) {
2051
+ throwMcpToolError(
2052
+ ErrorCode.InternalError,
2053
+ "senior-dev.recall-context",
2054
+ error,
2055
+ "recall context"
2056
+ );
2057
+ }
2058
+ }
2059
+
2060
+ /**
2061
+ * Handle senior-dev.capture-frame tool
2062
+ */
2063
+ async function handleSeniorDevCaptureFrame(
2064
+ args: CaptureFrameInput
2065
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
2066
+ try {
2067
+ const result = await captureSeniorDevFrame(args);
2068
+ return {
2069
+ content: [
2070
+ {
2071
+ type: "text",
2072
+ text: JSON.stringify(result, null, 2),
2073
+ },
2074
+ ],
2075
+ };
2076
+ } catch (error) {
2077
+ throwMcpToolError(ErrorCode.InternalError, "senior-dev.capture-frame", error, "capture frame");
2078
+ }
2079
+ }
2080
+
2081
+ /**
2082
+ * Handle senior-dev.modes tool
2083
+ */
2084
+ async function handleSeniorDevModes(): Promise<{
2085
+ content: [{ type: "text"; text: string }];
2086
+ }> {
2087
+ return {
2088
+ content: [
2089
+ {
2090
+ type: "text",
2091
+ text: JSON.stringify(EXECUTOR_MODES, null, 2),
2092
+ },
2093
+ ],
2094
+ };
2095
+ }
2096
+
2097
+ // ─────────────────────────────────────────────────────────────────────────────
2098
+ // LexRunner Run Management Handlers
2099
+ // ─────────────────────────────────────────────────────────────────────────────
2100
+
2101
+ /**
2102
+ * Generate a plan hash from run parameters for RunRecord storage.
2103
+ */
2104
+ function generatePlanHash(input: StartRunInput): string {
2105
+ const hashContent = JSON.stringify({
2106
+ mode: input.mode,
2107
+ procedure: input.procedure,
2108
+ repo: input.repo,
2109
+ params: input.params,
2110
+ });
2111
+ return "sha256:" + crypto.createHash("sha256").update(hashContent).digest("hex");
2112
+ }
2113
+
2114
+ /**
2115
+ * Handle lexrunner.startRun tool
2116
+ *
2117
+ * Creates a run record in both the RunStore (for persistence) and RunManager
2118
+ * (for orchestration state).
2119
+ */
2120
+ async function handleStartRun(
2121
+ args: StartRunInput,
2122
+ runStore: RunStore
2123
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
2124
+ try {
2125
+ // Validate input
2126
+ const validated = StartRunInputSchema.parse(args);
2127
+
2128
+ // Create run manager and start the run (for orchestration state)
2129
+ const manager = createRunManager();
2130
+ const result = manager.startRun(validated);
2131
+
2132
+ // Also create a record in the RunStore for persistence
2133
+ const now = new Date().toISOString();
2134
+ await runStore.createRun({
2135
+ runId: result.runId,
2136
+ planHash: generatePlanHash(validated),
2137
+ state: "pending", // RunStore uses its own state machine
2138
+ startedAt: now,
2139
+ metadata: {
2140
+ mode: validated.mode,
2141
+ procedure: validated.procedure,
2142
+ repo: validated.repo,
2143
+ task: validated.task,
2144
+ },
2145
+ });
2146
+
2147
+ return {
2148
+ content: [
2149
+ {
2150
+ type: "text",
2151
+ text: JSON.stringify(result, null, 2),
2152
+ },
2153
+ ],
2154
+ };
2155
+ } catch (error) {
2156
+ if (error instanceof Error && error.name === "ZodError") {
2157
+ const axError = mcpToolError(
2158
+ ErrorCodes.INVALID_INPUT,
2159
+ `Invalid startRun parameters: ${error.message}`,
2160
+ { tool: "lexrunner.startRun", operation: "validate parameters" }
2161
+ );
2162
+ throwMcpAXError(ErrorCode.InvalidParams, axError);
2163
+ }
2164
+ throwMcpToolError(ErrorCode.InternalError, "lexrunner.startRun", error, "start run");
2165
+ }
2166
+ }
2167
+
2168
+ /**
2169
+ * Handle lexrunner.getStatus tool
2170
+ *
2171
+ * Queries run state from RunManager, and also fetches step/receipt data
2172
+ * from RunStore for enhanced status reporting.
2173
+ */
2174
+ async function handleGetStatus(
2175
+ args: GetStatusInput,
2176
+ runStore: RunStore
2177
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
2178
+ try {
2179
+ // Validate input
2180
+ const validated = GetStatusInputSchema.parse(args);
2181
+
2182
+ // Get orchestration status from run manager
2183
+ const manager = createRunManager();
2184
+ const status = manager.getStatus(validated);
2185
+
2186
+ // Fetch additional data from RunStore if available
2187
+ const runRecord = await runStore.getRun(validated.runId);
2188
+ const steps = await runStore.getStepsForRun(validated.runId);
2189
+ const receipts = await runStore.getReceiptsForRun(validated.runId);
2190
+
2191
+ // Enhance status with store data
2192
+ const enhancedStatus = {
2193
+ ...status,
2194
+ store: runRecord
2195
+ ? {
2196
+ runRecord,
2197
+ steps,
2198
+ receipts,
2199
+ }
2200
+ : null,
2201
+ };
2202
+
2203
+ return {
2204
+ content: [
2205
+ {
2206
+ type: "text",
2207
+ text: JSON.stringify(enhancedStatus, null, 2),
2208
+ },
2209
+ ],
2210
+ };
2211
+ } catch (error) {
2212
+ if (error instanceof RunNotFoundError) {
2213
+ const axError = mcpToolError(
2214
+ ErrorCodes.INTERNAL_ERROR,
2215
+ error.message,
2216
+ { tool: "lexrunner.getStatus" },
2217
+ ["Check that runId is valid", "List available runs with 'lexrunner.listRuns'"]
2218
+ );
2219
+ throwMcpAXError(ErrorCode.InvalidParams, axError);
2220
+ }
2221
+ if (error instanceof Error && error.name === "ZodError") {
2222
+ const axError = mcpToolError(
2223
+ ErrorCodes.INVALID_INPUT,
2224
+ `Invalid getStatus parameters: ${error.message}`,
2225
+ {
2226
+ tool: "lexrunner.getStatus",
2227
+ operation: "validate parameters",
2228
+ }
2229
+ );
2230
+ throwMcpAXError(ErrorCode.InvalidParams, axError);
2231
+ }
2232
+ throwMcpToolError(ErrorCode.InternalError, "lexrunner.getStatus", error, "get status");
2233
+ }
2234
+ }
2235
+
2236
+ /**
2237
+ * Handle lexrunner.listRuns tool
2238
+ *
2239
+ * Queries the RunStore for run records with optional filtering and pagination.
2240
+ */
2241
+ async function handleListRuns(
2242
+ args: ListRunsInput,
2243
+ runStore: RunStore
2244
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
2245
+ try {
2246
+ // Validate input
2247
+ const validated = ListRunsInputSchema.parse(args);
2248
+
2249
+ // Query runs from the store
2250
+ const options: ListRunsOptions = {};
2251
+ if (validated.limit !== undefined) {
2252
+ options.limit = validated.limit;
2253
+ }
2254
+ if (validated.offset !== undefined) {
2255
+ options.offset = validated.offset;
2256
+ }
2257
+ if (validated.state !== undefined) {
2258
+ options.state = validated.state;
2259
+ }
2260
+
2261
+ const runs = await runStore.listRuns(options);
2262
+ const count = await runStore.getRunCount(validated.state);
2263
+
2264
+ const result = {
2265
+ runs,
2266
+ total: count,
2267
+ limit: validated.limit,
2268
+ offset: validated.offset ?? 0,
2269
+ };
2270
+
2271
+ return {
2272
+ content: [
2273
+ {
2274
+ type: "text",
2275
+ text: JSON.stringify(result, null, 2),
2276
+ },
2277
+ ],
2278
+ };
2279
+ } catch (error) {
2280
+ if (error instanceof Error && error.name === "ZodError") {
2281
+ const axError = mcpToolError(
2282
+ ErrorCodes.INVALID_INPUT,
2283
+ `Invalid listRuns parameters: ${error.message}`,
2284
+ { tool: "lexrunner.listRuns", operation: "validate parameters" }
2285
+ );
2286
+ throwMcpAXError(ErrorCode.InvalidParams, axError);
2287
+ }
2288
+ throwMcpToolError(ErrorCode.InternalError, "lexrunner.listRuns", error, "list runs");
2289
+ }
2290
+ }
2291
+
2292
+ /**
2293
+ * Handle lexrunner.submitDecision tool
2294
+ *
2295
+ * Validates and submits an LLM decision for a pending action in a run.
2296
+ */
2297
+ async function handleSubmitDecision(
2298
+ args: SubmitDecisionInput
2299
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
2300
+ try {
2301
+ // Validate input
2302
+ const validated = SubmitDecisionInputSchema.parse(args);
2303
+
2304
+ // Submit the decision (uses process.cwd() as baseDir)
2305
+ const result = submitDecision(validated);
2306
+
2307
+ return {
2308
+ content: [
2309
+ {
2310
+ type: "text",
2311
+ text: JSON.stringify(result, null, 2),
2312
+ },
2313
+ ],
2314
+ };
2315
+ } catch (error) {
2316
+ if (error instanceof Error && error.name === "ZodError") {
2317
+ const axError = mcpToolError(
2318
+ ErrorCodes.INVALID_INPUT,
2319
+ `Invalid submitDecision parameters: ${error.message}`,
2320
+ {
2321
+ tool: "lexrunner.submitDecision",
2322
+ operation: "validate parameters",
2323
+ }
2324
+ );
2325
+ throwMcpAXError(ErrorCode.InvalidParams, axError);
2326
+ }
2327
+ throwMcpToolError(
2328
+ ErrorCode.InternalError,
2329
+ "lexrunner.submitDecision",
2330
+ error,
2331
+ "submit decision"
2332
+ );
2333
+ }
2334
+ }
2335
+
2336
+ // ─────────────────────────────────────────────────────────────────────────────
2337
+ // MCP/CLI Parity Handlers (AX-004)
2338
+ // ─────────────────────────────────────────────────────────────────────────────
2339
+
2340
+ /**
2341
+ * Handle discover tool - Discover open pull requests from GitHub
2342
+ */
2343
+ async function handleDiscover(args: {
2344
+ owner?: string;
2345
+ repo?: string;
2346
+ state?: string;
2347
+ suggest?: boolean;
2348
+ }): Promise<{ content: [{ type: "text"; text: string }] }> {
2349
+ try {
2350
+ // Check for GitHub authentication early
2351
+ ensureGitHubToken();
2352
+
2353
+ let githubAPI = await createGitHubAPI();
2354
+
2355
+ // Override with arguments if provided
2356
+ if (args.owner && args.repo) {
2357
+ githubAPI = new GitHubAPI({
2358
+ owner: args.owner,
2359
+ repo: args.repo,
2360
+ token: process.env.GITHUB_TOKEN,
2361
+ });
2362
+ }
2363
+
2364
+ if (!githubAPI) {
2365
+ const axError = githubApiError({
2366
+ message:
2367
+ "Could not detect GitHub repository. Provide owner and repo parameters or run from a git repository with GitHub remote.",
2368
+ });
2369
+ throwMcpAXError(ErrorCode.InvalidRequest, axError);
2370
+ }
2371
+
2372
+ // Check authentication and warn if not authenticated
2373
+ const authStatus = await githubAPI.checkAuth();
2374
+ if (!authStatus.authenticated) {
2375
+ // Log warning to stderr for MCP clients to surface
2376
+ console.error(
2377
+ "[mcp:discover] Warning: GitHub API not authenticated. Private repos will not be accessible.\n" +
2378
+ "To fix: Add GITHUB_TOKEN to your MCP server config env block.\n" +
2379
+ "See: README.mcp.md#github-authentication"
2380
+ );
2381
+ }
2382
+
2383
+ // Fetch pull requests
2384
+ const state = (args.state || "open") as "open" | "closed" | "all";
2385
+ const pullRequests = await githubAPI.discoverPullRequests(state);
2386
+
2387
+ let result: Record<string, unknown>;
2388
+
2389
+ if (args.suggest) {
2390
+ // Generate dependency suggestions using heuristics
2391
+ const { createFileAnalyzer } = await import("../planner/fileAnalysis.js");
2392
+
2393
+ const analyzer = createFileAnalyzer(
2394
+ githubAPI.getOctokit(),
2395
+ githubAPI.config.owner,
2396
+ githubAPI.config.repo
2397
+ );
2398
+ const prs = pullRequests.map((pr: { number: number; sha: string }) => ({
2399
+ number: pr.number,
2400
+ name: `PR-${pr.number}`,
2401
+ sha: pr.sha,
2402
+ }));
2403
+
2404
+ const suggestions = await analyzer.suggestDependenciesWithHeuristics(prs);
2405
+
2406
+ result = {
2407
+ pullRequests,
2408
+ suggestions,
2409
+ total: pullRequests.length,
2410
+ suggestionsCount: suggestions.length,
2411
+ authenticated: authStatus.authenticated,
2412
+ user: authStatus.user,
2413
+ };
2414
+ } else {
2415
+ result = {
2416
+ pullRequests,
2417
+ total: pullRequests.length,
2418
+ authenticated: authStatus.authenticated,
2419
+ user: authStatus.user,
2420
+ };
2421
+ }
2422
+
2423
+ return {
2424
+ content: [
2425
+ {
2426
+ type: "text",
2427
+ text: JSON.stringify(result, null, 2),
2428
+ },
2429
+ ],
2430
+ };
2431
+ } catch (error) {
2432
+ if (error instanceof McpError) {
2433
+ throw error;
2434
+ }
2435
+ // Handle GitHub API errors specifically with status code context
2436
+ if (error instanceof GitHubAPIError) {
2437
+ const axError = githubApiError({
2438
+ status: error.status,
2439
+ message: error.message,
2440
+ });
2441
+ throwMcpAXError(ErrorCode.InternalError, axError);
2442
+ }
2443
+ throwMcpToolError(ErrorCode.InternalError, "discover", error, "discover PRs");
2444
+ }
2445
+ }
2446
+
2447
+ /**
2448
+ * Handle status tool - Show execution status and merge eligibility
2449
+ */
2450
+ async function handleStatus(args: {
2451
+ planFile?: string;
2452
+ }): Promise<{ content: [{ type: "text"; text: string }] }> {
2453
+ try {
2454
+ const planFile = args.planFile || "plan.json";
2455
+
2456
+ if (!fs.existsSync(planFile)) {
2457
+ throwMcpAXError(ErrorCode.InvalidParams, planNotFoundError(planFile));
2458
+ }
2459
+
2460
+ const planContent = fs.readFileSync(planFile, "utf-8");
2461
+ const plan = loadPlan(planContent);
2462
+
2463
+ // Create execution state (for now, show plan structure)
2464
+ const executionState = new ExecutionState(plan);
2465
+ const evaluator = new MergeEligibilityEvaluator(plan, executionState);
2466
+ const mergeSummary = evaluator.getMergeSummary();
2467
+
2468
+ // Calculate tier metrics from plan items
2469
+ const tierAssignments = suggestTiersForPlan(plan.items);
2470
+ const tierMetrics = calculateTierMetrics(tierAssignments);
2471
+
2472
+ // Run environment quality check for hostility score
2473
+ const hostilityScore = runEnvironmentQualityCheck();
2474
+
2475
+ // Build governance status
2476
+ const governanceStatus = buildGovernanceStatus(
2477
+ tierMetrics,
2478
+ undefined, // Turn cost tracked during actual runs
2479
+ hostilityScore
2480
+ );
2481
+
2482
+ const result = {
2483
+ plan: {
2484
+ schemaVersion: plan.schemaVersion,
2485
+ target: plan.target,
2486
+ itemCount: plan.items.length,
2487
+ policy: plan.policy,
2488
+ },
2489
+ mergeSummary,
2490
+ governance: governanceStatusToJSON(governanceStatus),
2491
+ };
2492
+
2493
+ return {
2494
+ content: [
2495
+ {
2496
+ type: "text",
2497
+ text: JSON.stringify(result, null, 2),
2498
+ },
2499
+ ],
2500
+ };
2501
+ } catch (error) {
2502
+ if (error instanceof McpError) {
2503
+ throw error;
2504
+ }
2505
+ throwMcpToolError(ErrorCode.InternalError, "status", error, "get status");
2506
+ }
2507
+ }
2508
+
2509
+ /**
2510
+ * Handle doctor tool - Environment and configuration sanity checks
2511
+ */
2512
+ async function handleDoctor(args: {
2513
+ environmentQuality?: boolean;
2514
+ }): Promise<{ content: [{ type: "text"; text: string }] }> {
2515
+ try {
2516
+ const checks: Record<string, unknown> = {
2517
+ hasErrors: false,
2518
+ issues: [] as string[],
2519
+ suggestions: [] as string[],
2520
+ };
2521
+
2522
+ // Node.js version check
2523
+ try {
2524
+ const nvmrcContent = fs.readFileSync(".nvmrc", "utf-8").trim();
2525
+ const currentVersion = process.version.slice(1);
2526
+ const expectedVersion = nvmrcContent;
2527
+
2528
+ if (currentVersion === expectedVersion) {
2529
+ checks.nodejs = {
2530
+ status: "ok",
2531
+ current: process.version,
2532
+ expected: `v${expectedVersion}`,
2533
+ };
2534
+ } else {
2535
+ checks.nodejs = {
2536
+ status: "mismatch",
2537
+ current: process.version,
2538
+ expected: `v${expectedVersion}`,
2539
+ };
2540
+ checks.hasErrors = true;
2541
+ (checks.issues as string[]).push(
2542
+ `Node.js version mismatch: ${process.version} vs v${expectedVersion}`
2543
+ );
2544
+ }
2545
+ } catch {
2546
+ checks.nodejs = {
2547
+ status: "no_constraint",
2548
+ current: process.version,
2549
+ };
2550
+ (checks.suggestions as string[]).push(
2551
+ "Consider adding .nvmrc file for Node.js version consistency"
2552
+ );
2553
+ }
2554
+
2555
+ // Configuration check
2556
+ const bootstrap = bootstrapWorkspace();
2557
+ checks.configuration = {
2558
+ hasConfiguration: bootstrap.hasConfiguration,
2559
+ missingFiles: bootstrap.missingFiles,
2560
+ suggestions: bootstrap.suggestions,
2561
+ };
2562
+
2563
+ // Project type detection
2564
+ checks.projectType = detectProjectType();
2565
+
2566
+ // Environment suggestions
2567
+ checks.environmentSuggestions = getEnvironmentSuggestions();
2568
+
2569
+ // GitHub integration check
2570
+ try {
2571
+ const githubAPI = await createGitHubAPI();
2572
+ if (githubAPI) {
2573
+ const authStatus = await githubAPI.checkAuth();
2574
+ checks.github = {
2575
+ detected: true,
2576
+ authenticated: authStatus.authenticated,
2577
+ user: authStatus.user,
2578
+ };
2579
+ } else {
2580
+ checks.github = { detected: false };
2581
+ }
2582
+ } catch (error) {
2583
+ checks.github = {
2584
+ detected: false,
2585
+ error: (error as Error).message,
2586
+ };
2587
+ }
2588
+
2589
+ // Git operations check
2590
+ try {
2591
+ const gitOps = createGitOperations();
2592
+ const isClean = await gitOps.isClean();
2593
+ const currentBranch = await gitOps.getCurrentBranch();
2594
+
2595
+ checks.git = {
2596
+ status: "ok",
2597
+ isClean,
2598
+ currentBranch,
2599
+ };
2600
+ } catch (error) {
2601
+ checks.git = {
2602
+ status: "error",
2603
+ error: (error as Error).message,
2604
+ };
2605
+ checks.hasErrors = true;
2606
+ (checks.issues as string[]).push(`Git operations failed: ${(error as Error).message}`);
2607
+ }
2608
+
2609
+ // Environment quality check (hostility scoring) if requested
2610
+ if (args.environmentQuality) {
2611
+ checks.environmentQuality = runEnvironmentQualityCheck();
2612
+ }
2613
+
2614
+ return {
2615
+ content: [
2616
+ {
2617
+ type: "text",
2618
+ text: JSON.stringify(checks, null, 2),
2619
+ },
2620
+ ],
2621
+ };
2622
+ } catch (error) {
2623
+ throwMcpToolError(ErrorCode.InternalError, "doctor", error, "run doctor");
2624
+ }
2625
+ }
2626
+
2627
+ /**
2628
+ * Handle merge-order tool - Compute dependency levels and merge order
2629
+ */
2630
+ async function handleMergeOrder(args: {
2631
+ planFile?: string;
2632
+ }): Promise<{ content: [{ type: "text"; text: string }] }> {
2633
+ try {
2634
+ const planFile = args.planFile || "plan.json";
2635
+
2636
+ if (!fs.existsSync(planFile)) {
2637
+ throwMcpAXError(ErrorCode.InvalidParams, planNotFoundError(planFile));
2638
+ }
2639
+
2640
+ const planContent = fs.readFileSync(planFile, "utf-8");
2641
+ const plan = loadPlan(planContent);
2642
+
2643
+ // Compute merge order using Kahn's algorithm
2644
+ const levels = computeMergeOrder(plan);
2645
+
2646
+ const result = {
2647
+ levels,
2648
+ totalItems: plan.items.length,
2649
+ maxParallelism: Math.max(...levels.map((level) => level.length)),
2650
+ };
2651
+
2652
+ return {
2653
+ content: [
2654
+ {
2655
+ type: "text",
2656
+ text: JSON.stringify(result, null, 2),
2657
+ },
2658
+ ],
2659
+ };
2660
+ } catch (error) {
2661
+ if (error instanceof McpError) {
2662
+ throw error;
2663
+ }
2664
+ // Handle AXErrorException instances (including CycleError, UnknownDependencyError)
2665
+ if (isAXErrorException(error)) {
2666
+ const axError = error.toAXError();
2667
+ throwMcpAXError(ErrorCode.InvalidParams, axError);
2668
+ }
2669
+ throwMcpToolError(ErrorCode.InternalError, "merge-order", error, "compute merge order");
2670
+ }
2671
+ }
2672
+
2673
+ /**
2674
+ * Handle config.show tool - Display configuration with precedence chain
2675
+ */
2676
+ async function handleConfigShow(args: {
2677
+ key?: string;
2678
+ }): Promise<{ content: [{ type: "text"; text: string }] }> {
2679
+ try {
2680
+ // Load configuration with provenance tracking
2681
+ const config = loadInputs();
2682
+
2683
+ const output: Record<string, unknown> = {
2684
+ config: {
2685
+ items: config.items,
2686
+ target: config.target,
2687
+ version: config.version,
2688
+ },
2689
+ provenance: config.provenance || {},
2690
+ sources: config.sources.map((s) => ({
2691
+ exists: s.exists,
2692
+ file: s.file,
2693
+ })),
2694
+ };
2695
+
2696
+ // If specific key requested, extract just that value
2697
+ if (args.key) {
2698
+ const keys = args.key.split(".");
2699
+ let value: unknown = output.config;
2700
+ for (const k of keys) {
2701
+ if (value && typeof value === "object" && k in value) {
2702
+ value = (value as Record<string, unknown>)[k];
2703
+ } else {
2704
+ value = undefined;
2705
+ break;
2706
+ }
2707
+ }
2708
+ return {
2709
+ content: [
2710
+ {
2711
+ type: "text",
2712
+ text: JSON.stringify({ key: args.key, value }, null, 2),
2713
+ },
2714
+ ],
2715
+ };
2716
+ }
2717
+
2718
+ return {
2719
+ content: [
2720
+ {
2721
+ type: "text",
2722
+ text: JSON.stringify(output, null, 2),
2723
+ },
2724
+ ],
2725
+ };
2726
+ } catch (error) {
2727
+ throwMcpToolError(ErrorCode.InternalError, "config.show", error, "show config");
2728
+ }
2729
+ }
2730
+
2731
+ /**
2732
+ * Handle metrics tool - Get governance metrics snapshot
2733
+ */
2734
+ async function handleMetrics(args: {
2735
+ filter?: string;
2736
+ format?: string;
2737
+ }): Promise<{ content: [{ type: "text"; text: string }] }> {
2738
+ try {
2739
+ const collector = getGlobalMetricsCollector();
2740
+
2741
+ // Get snapshot, optionally filtered
2742
+ const snapshot = args.filter
2743
+ ? collector.getMetricsByName(args.filter)
2744
+ : collector.getSnapshot();
2745
+
2746
+ // Format output
2747
+ let output: string;
2748
+ if (args.format === "prometheus") {
2749
+ output = collector.exportPrometheus();
2750
+ } else {
2751
+ output = JSON.stringify(snapshot, null, 2);
2752
+ }
2753
+
2754
+ return {
2755
+ content: [
2756
+ {
2757
+ type: "text",
2758
+ text: output,
2759
+ },
2760
+ ],
2761
+ };
2762
+ } catch (error) {
2763
+ throwMcpToolError(ErrorCode.InternalError, "metrics", error, "get metrics");
2764
+ }
2765
+ }
2766
+
2767
+ /**
2768
+ * Handle workflow.guide tool - Get context-aware workflow guidance
2769
+ */
2770
+ async function handleWorkflowGuide(
2771
+ args: WorkflowGuideArgs
2772
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
2773
+ try {
2774
+ // Validate phase is a valid WorkflowPhase
2775
+ const validPhases: WorkflowPhase[] = [
2776
+ "initial",
2777
+ "post-plan-creation",
2778
+ "post-gates-run",
2779
+ "pre-merge",
2780
+ "post-merge",
2781
+ "error-recovery",
2782
+ ];
2783
+
2784
+ const phase = args.phase as WorkflowPhase;
2785
+ if (!validPhases.includes(phase)) {
2786
+ throw new McpError(
2787
+ ErrorCode.InvalidParams,
2788
+ `Invalid workflow phase: ${args.phase}. Valid phases: ${validPhases.join(", ")}`
2789
+ );
2790
+ }
2791
+
2792
+ // Create workflow guide for the requested phase
2793
+ const guide: WorkflowGuide = createWorkflowGuide(phase);
2794
+
2795
+ return {
2796
+ content: [
2797
+ {
2798
+ type: "text",
2799
+ text: JSON.stringify(guide, null, 2),
2800
+ },
2801
+ ],
2802
+ };
2803
+ } catch (error) {
2804
+ if (error instanceof McpError) {
2805
+ throw error;
2806
+ }
2807
+ throwMcpToolError(ErrorCode.InternalError, "workflow.guide", error, "get workflow guide");
2808
+ }
2809
+ }
2810
+
2811
+ // ─────────────────────────────────────────────────────────────────────────────
2812
+ // Task Handoff Tool Handlers (ADR-007)
2813
+ // ─────────────────────────────────────────────────────────────────────────────
2814
+
2815
+ /**
2816
+ * In-memory task store for MCP session
2817
+ * In production, this should use RunStore or a dedicated task store
2818
+ */
2819
+ const taskStore = new Map<
2820
+ string,
2821
+ {
2822
+ snapshot: TaskSnapshot_v1;
2823
+ receipt?: TaskReceipt_v1;
2824
+ verification?: any;
2825
+ state: "pending" | "in_progress" | "completed" | "verified" | "failed";
2826
+ }
2827
+ >();
2828
+
2829
+ /**
2830
+ * Handle create_task_snapshot tool
2831
+ */
2832
+ async function handleCreateTaskSnapshot(
2833
+ args: CreateTaskSnapshotArgs
2834
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
2835
+ try {
2836
+ // Validate args
2837
+ const validated = CreateTaskSnapshotArgs.parse(args);
2838
+
2839
+ // Auto-detect git info if not provided
2840
+ const gitOps = createGitOperations();
2841
+ const repoRoot = validated.repoRoot || process.cwd();
2842
+ const commitSha = validated.commitSha || (await gitOps.getCurrentHead());
2843
+
2844
+ // Auto-detect repoId if not provided
2845
+ let repoId = validated.repoId;
2846
+ if (!repoId) {
2847
+ try {
2848
+ const githubAPI = await createGitHubAPI();
2849
+ if (githubAPI) {
2850
+ repoId = `${githubAPI.config.owner}/${githubAPI.config.repo}`;
2851
+ } else {
2852
+ repoId = "unknown/unknown";
2853
+ }
2854
+ } catch {
2855
+ repoId = "unknown/unknown";
2856
+ }
2857
+ }
2858
+
2859
+ // Generate task ID if not provided
2860
+ const taskId = validated.taskId || ulid();
2861
+
2862
+ // Build snapshot using SnapshotBuilder
2863
+ const builder = new SnapshotBuilder({
2864
+ repoRoot,
2865
+ repoId,
2866
+ });
2867
+
2868
+ const snapshot = await builder.buildSnapshot({
2869
+ taskId,
2870
+ procedure: validated.procedure,
2871
+ determinism: validated.determinism as "D1" | "D2" | "D3" | undefined,
2872
+ targetFiles: validated.targetFiles,
2873
+ failure: {
2874
+ message: validated.failureMessage,
2875
+ fileRel: validated.failureFileRel,
2876
+ line: validated.failureLine,
2877
+ runnerOutputSnip: validated.runnerOutputSnip,
2878
+ excerpt: validated.failureExcerpt,
2879
+ },
2880
+ commitSha,
2881
+ verificationCmd: validated.verificationCmd,
2882
+ expectedExitCode: validated.expectedExitCode,
2883
+ });
2884
+
2885
+ // Store snapshot in task store
2886
+ taskStore.set(taskId, {
2887
+ snapshot,
2888
+ state: "pending",
2889
+ });
2890
+
2891
+ const result: CreateTaskSnapshotResult = {
2892
+ snapshot,
2893
+ taskId,
2894
+ };
2895
+
2896
+ return {
2897
+ content: [
2898
+ {
2899
+ type: "text",
2900
+ text: JSON.stringify(result, null, 2),
2901
+ },
2902
+ ],
2903
+ };
2904
+ } catch (error) {
2905
+ if (error instanceof Error && error.name === "ZodError") {
2906
+ const axError = mcpToolError(
2907
+ ErrorCodes.INVALID_INPUT,
2908
+ `Invalid create_task_snapshot parameters: ${error.message}`,
2909
+ {
2910
+ tool: "create_task_snapshot",
2911
+ operation: "validate parameters",
2912
+ }
2913
+ );
2914
+ throwMcpAXError(ErrorCode.InvalidParams, axError);
2915
+ }
2916
+ throwMcpToolError(
2917
+ ErrorCode.InternalError,
2918
+ "create_task_snapshot",
2919
+ error,
2920
+ "create task snapshot"
2921
+ );
2922
+ }
2923
+ }
2924
+
2925
+ /**
2926
+ * Handle submit_task_receipt tool
2927
+ */
2928
+ async function handleSubmitTaskReceipt(
2929
+ args: SubmitTaskReceiptArgs
2930
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
2931
+ try {
2932
+ // Validate args
2933
+ const validated = SubmitTaskReceiptArgs.parse(args);
2934
+
2935
+ // Parse and validate receipt
2936
+ const receipt = parseTaskReceipt(validated.receipt);
2937
+
2938
+ // Find corresponding snapshot
2939
+ const taskData = taskStore.get(receipt.task_id);
2940
+ if (!taskData) {
2941
+ const axError = mcpToolError(
2942
+ ErrorCodes.INTERNAL_ERROR,
2943
+ `Task not found: ${receipt.task_id}. Create snapshot first using create_task_snapshot.`,
2944
+ {
2945
+ tool: "submit_task_receipt",
2946
+ details: { taskId: receipt.task_id },
2947
+ }
2948
+ );
2949
+ throwMcpAXError(ErrorCode.InvalidParams, axError);
2950
+ }
2951
+
2952
+ // Update state
2953
+ taskData.state = "in_progress";
2954
+ taskData.receipt = receipt;
2955
+
2956
+ // Run engine verification
2957
+ const verifier = new EngineVerifier();
2958
+ const verificationResult = await verifier.verify({
2959
+ snapshot: taskData.snapshot,
2960
+ receipt,
2961
+ workingDir: taskData.snapshot.repo.root,
2962
+ applyPatch: true,
2963
+ });
2964
+
2965
+ // Update task with verification
2966
+ taskData.verification = verificationResult.verification;
2967
+ taskData.state = verificationResult.verification.verified ? "verified" : "failed";
2968
+
2969
+ const result: SubmitTaskReceiptResult = {
2970
+ acknowledged: true,
2971
+ taskId: receipt.task_id,
2972
+ verification: {
2973
+ verified: verificationResult.verification.verified,
2974
+ trustGap: verificationResult.trustGap,
2975
+ patchApplied: verificationResult.patchApplied,
2976
+ },
2977
+ };
2978
+
2979
+ return {
2980
+ content: [
2981
+ {
2982
+ type: "text",
2983
+ text: JSON.stringify(result, null, 2),
2984
+ },
2985
+ ],
2986
+ };
2987
+ } catch (error) {
2988
+ if (error instanceof Error && error.name === "ZodError") {
2989
+ const axError = mcpToolError(
2990
+ ErrorCodes.INVALID_INPUT,
2991
+ `Invalid submit_task_receipt parameters: ${error.message}`,
2992
+ {
2993
+ tool: "submit_task_receipt",
2994
+ operation: "validate parameters",
2995
+ }
2996
+ );
2997
+ throwMcpAXError(ErrorCode.InvalidParams, axError);
2998
+ }
2999
+ throwMcpToolError(ErrorCode.InternalError, "submit_task_receipt", error, "submit task receipt");
3000
+ }
3001
+ }
3002
+
3003
+ /**
3004
+ * Handle get_task_status tool
3005
+ */
3006
+ async function handleGetTaskStatus(
3007
+ args: GetTaskStatusArgs
3008
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
3009
+ try {
3010
+ // Validate args
3011
+ const validated = GetTaskStatusArgs.parse(args);
3012
+
3013
+ // Find task
3014
+ const taskData = taskStore.get(validated.taskId);
3015
+ if (!taskData) {
3016
+ const axError = mcpToolError(
3017
+ ErrorCodes.INTERNAL_ERROR,
3018
+ `Task not found: ${validated.taskId}`,
3019
+ {
3020
+ tool: "get_task_status",
3021
+ details: { taskId: validated.taskId },
3022
+ }
3023
+ );
3024
+ throwMcpAXError(ErrorCode.InvalidParams, axError);
3025
+ }
3026
+
3027
+ const result: GetTaskStatusResult = {
3028
+ taskId: validated.taskId,
3029
+ state: taskData.state,
3030
+ snapshot: taskData.snapshot,
3031
+ receipt: taskData.receipt,
3032
+ verification: taskData.verification,
3033
+ };
3034
+
3035
+ return {
3036
+ content: [
3037
+ {
3038
+ type: "text",
3039
+ text: JSON.stringify(result, null, 2),
3040
+ },
3041
+ ],
3042
+ };
3043
+ } catch (error) {
3044
+ if (error instanceof Error && error.name === "ZodError") {
3045
+ const axError = mcpToolError(
3046
+ ErrorCodes.INVALID_INPUT,
3047
+ `Invalid get_task_status parameters: ${error.message}`,
3048
+ { tool: "get_task_status", operation: "validate parameters" }
3049
+ );
3050
+ throwMcpAXError(ErrorCode.InvalidParams, axError);
3051
+ }
3052
+ throwMcpToolError(ErrorCode.InternalError, "get_task_status", error, "get task status");
3053
+ }
3054
+ }
3055
+
3056
+ /**
3057
+ * Handle list_pending_tasks tool
3058
+ */
3059
+ async function handleListPendingTasks(
3060
+ args: ListPendingTasksArgs
3061
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
3062
+ try {
3063
+ // Validate args
3064
+ const validated = ListPendingTasksArgs.parse(args);
3065
+
3066
+ // Filter tasks
3067
+ const tasks: ListPendingTasksResult["tasks"] = [];
3068
+ for (const [taskId, taskData] of taskStore.entries()) {
3069
+ // Apply filters
3070
+ if (validated.procedure && taskData.snapshot.procedure !== validated.procedure) {
3071
+ continue;
3072
+ }
3073
+ if (validated.determinism && taskData.snapshot.determinism !== validated.determinism) {
3074
+ continue;
3075
+ }
3076
+
3077
+ tasks.push({
3078
+ taskId,
3079
+ procedure: taskData.snapshot.procedure,
3080
+ determinism: taskData.snapshot.determinism,
3081
+ state: taskData.state,
3082
+ snapshot: taskData.snapshot,
3083
+ });
3084
+
3085
+ // Apply limit
3086
+ if (validated.limit && tasks.length >= validated.limit) {
3087
+ break;
3088
+ }
3089
+ }
3090
+
3091
+ const result: ListPendingTasksResult = {
3092
+ tasks,
3093
+ total: tasks.length,
3094
+ };
3095
+
3096
+ return {
3097
+ content: [
3098
+ {
3099
+ type: "text",
3100
+ text: JSON.stringify(result, null, 2),
3101
+ },
3102
+ ],
3103
+ };
3104
+ } catch (error) {
3105
+ if (error instanceof Error && error.name === "ZodError") {
3106
+ const axError = mcpToolError(
3107
+ ErrorCodes.INVALID_INPUT,
3108
+ `Invalid list_pending_tasks parameters: ${error.message}`,
3109
+ { tool: "list_pending_tasks", operation: "validate parameters" }
3110
+ );
3111
+ throwMcpAXError(ErrorCode.InvalidParams, axError);
3112
+ }
3113
+ throwMcpToolError(ErrorCode.InternalError, "list_pending_tasks", error, "list pending tasks");
3114
+ }
3115
+ }
3116
+
3117
+ // =============================================================================
3118
+ // Fanout AX Handlers (Epic #654 Layer 2)
3119
+ // =============================================================================
3120
+
3121
+ /**
3122
+ * Handle fanout_harvest tool
3123
+ * D0: Harvest external state from GitHub into a deterministic, replayable HarvestBundle
3124
+ */
3125
+ async function handleFanoutHarvest(
3126
+ args: FanoutHarvestArgs
3127
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
3128
+ try {
3129
+ // Validate args
3130
+ const validated = FanoutHarvestArgs.parse(args);
3131
+
3132
+ // Check for GitHub authentication
3133
+ ensureGitHubToken(validated.githubToken);
3134
+
3135
+ // Create GitHub API
3136
+ let githubAPI = await createGitHubAPI();
3137
+
3138
+ // Override with arguments if provided
3139
+ if (validated.owner && validated.repo) {
3140
+ githubAPI = new GitHubAPI({
3141
+ owner: validated.owner,
3142
+ repo: validated.repo,
3143
+ token: validated.githubToken || process.env.GITHUB_TOKEN,
3144
+ });
3145
+ }
3146
+
3147
+ if (!githubAPI) {
3148
+ const axError = githubApiError({
3149
+ message:
3150
+ "Could not detect GitHub repository. Provide owner and repo parameters or run from a git repository with GitHub remote.",
3151
+ });
3152
+ throwMcpAXError(ErrorCode.InvalidRequest, axError);
3153
+ }
3154
+
3155
+ const timestamp = new Date().toISOString();
3156
+ const state = validated.state || "open";
3157
+ const maxBody = validated.maxBody || 4096;
3158
+ const includeIssues = validated.includeIssues ?? false;
3159
+
3160
+ // Compute input digest for replay verification
3161
+ const inputDigest = crypto
3162
+ .createHash("sha256")
3163
+ .update(
3164
+ JSON.stringify({
3165
+ owner: githubAPI.config.owner,
3166
+ repo: githubAPI.config.repo,
3167
+ state,
3168
+ timestamp,
3169
+ })
3170
+ )
3171
+ .digest("hex");
3172
+
3173
+ // Fetch repository info
3174
+ const repoInfo = await githubAPI.getRepository();
3175
+ const defaultBranch = repoInfo.default_branch;
3176
+ const defaultBranchRef = await githubAPI.getRef(`heads/${defaultBranch}`);
3177
+
3178
+ const repository = {
3179
+ owner: githubAPI.config.owner,
3180
+ name: githubAPI.config.repo,
3181
+ defaultBranch,
3182
+ defaultBranchSha: defaultBranchRef.object.sha,
3183
+ };
3184
+
3185
+ // Fetch pull requests
3186
+ const rawPRs = await githubAPI.discoverPullRequests(state);
3187
+ const pullRequests = await Promise.all(
3188
+ rawPRs.map(async (pr: any) => {
3189
+ // Get merge base SHA
3190
+ let mergeBaseSha: string | "unknown" | "unavailable" = "unknown";
3191
+ try {
3192
+ const comparison = await githubAPI.compare(pr.baseBranch, pr.sha);
3193
+ mergeBaseSha = comparison.merge_base_commit?.sha ?? "unavailable";
3194
+ } catch {
3195
+ mergeBaseSha = "unavailable";
3196
+ }
3197
+
3198
+ // Determine CI status
3199
+ let ciStatus: "pass" | "fail" | "pending" | "unknown" | "unavailable" = "unknown";
3200
+ try {
3201
+ const checks = await githubAPI.getCheckRuns(pr.sha);
3202
+ if (checks.total_count === 0) {
3203
+ ciStatus = "pending";
3204
+ } else {
3205
+ const allComplete = checks.check_runs.every((c: any) => c.status === "completed");
3206
+ if (!allComplete) {
3207
+ ciStatus = "pending";
3208
+ } else {
3209
+ const anyFailed = checks.check_runs.some(
3210
+ (c: any) => c.conclusion !== "success" && c.conclusion !== "skipped"
3211
+ );
3212
+ ciStatus = anyFailed ? "fail" : "pass";
3213
+ }
3214
+ }
3215
+ } catch {
3216
+ ciStatus = "unavailable";
3217
+ }
3218
+
3219
+ // Determine review status
3220
+ let reviewStatus:
3221
+ | "approved"
3222
+ | "changes_requested"
3223
+ | "pending"
3224
+ | "none"
3225
+ | "unknown"
3226
+ | "unavailable" = "unknown";
3227
+ try {
3228
+ const reviews = await githubAPI.getReviews(pr.number);
3229
+ const latestByUser = new Map<string, string>();
3230
+ for (const review of reviews) {
3231
+ if (review.state !== "COMMENTED" && review.user?.login) {
3232
+ latestByUser.set(review.user.login, review.state);
3233
+ }
3234
+ }
3235
+ const states = Array.from(latestByUser.values());
3236
+ if (states.includes("CHANGES_REQUESTED")) {
3237
+ reviewStatus = "changes_requested";
3238
+ } else if (states.includes("APPROVED")) {
3239
+ reviewStatus = "approved";
3240
+ } else if (states.length > 0) {
3241
+ reviewStatus = "pending";
3242
+ } else {
3243
+ reviewStatus = "none";
3244
+ }
3245
+ } catch {
3246
+ reviewStatus = "unavailable";
3247
+ }
3248
+
3249
+ // Determine conflict status
3250
+ let conflictStatus: "clean" | "conflicted" | "unknown" | "unavailable" = "unknown";
3251
+ if (pr.mergeable === true) {
3252
+ conflictStatus = "clean";
3253
+ } else if (pr.mergeable === false) {
3254
+ conflictStatus = "conflicted";
3255
+ }
3256
+
3257
+ return {
3258
+ number: pr.number,
3259
+ title: pr.title,
3260
+ state: pr.state,
3261
+ draft: false,
3262
+ headSha: pr.sha,
3263
+ baseSha: "unavailable",
3264
+ mergeBaseSha,
3265
+ author: pr.author,
3266
+ labels: pr.labels,
3267
+ ciStatus,
3268
+ reviewStatus,
3269
+ conflictStatus,
3270
+ updatedAt: pr.updatedAt,
3271
+ body: "",
3272
+ changedFiles: "unknown",
3273
+ additions: "unknown",
3274
+ deletions: "unknown",
3275
+ };
3276
+ })
3277
+ );
3278
+
3279
+ // Fetch issues if requested
3280
+ let issues: Array<object> = [];
3281
+ if (includeIssues) {
3282
+ try {
3283
+ const rawIssues = await githubAPI.listIssues({ state });
3284
+ issues = rawIssues
3285
+ .filter((i: any) => !i.pull_request)
3286
+ .map((i: any) => {
3287
+ let body: string | "truncated" = i.body ?? "";
3288
+ if (body.length > maxBody) {
3289
+ body = "truncated";
3290
+ }
3291
+ return {
3292
+ number: i.number,
3293
+ title: i.title,
3294
+ state: i.state,
3295
+ author: i.user.login,
3296
+ labels: i.labels.map((l: any) => l.name),
3297
+ updatedAt: i.updated_at,
3298
+ body,
3299
+ assignees: i.assignees?.map((a: any) => a.login) ?? [],
3300
+ };
3301
+ });
3302
+ } catch {
3303
+ // Issues not critical - continue without them
3304
+ }
3305
+ }
3306
+
3307
+ const bundle = {
3308
+ repository,
3309
+ pullRequests,
3310
+ issues,
3311
+ harvestedAt: timestamp,
3312
+ };
3313
+
3314
+ const outputDigest = crypto.createHash("sha256").update(JSON.stringify(bundle)).digest("hex");
3315
+
3316
+ const result: FanoutHarvestResult = {
3317
+ schemaVersion: "1.0.0",
3318
+ phase: "D0",
3319
+ timestamp,
3320
+ inputDigest: `sha256:${inputDigest}`,
3321
+ bundle,
3322
+ outputDigest: `sha256:${outputDigest}`,
3323
+ };
3324
+
3325
+ console.error(
3326
+ `[mcp:fanout_harvest] harvested ${pullRequests.length} PRs, ${issues.length} issues from ${repository.owner}/${repository.name}`
3327
+ );
3328
+
3329
+ return {
3330
+ content: [
3331
+ {
3332
+ type: "text",
3333
+ text: JSON.stringify(result, null, 2),
3334
+ },
3335
+ ],
3336
+ };
3337
+ } catch (error) {
3338
+ if (error instanceof Error && error.name === "ZodError") {
3339
+ const axError = mcpToolError(
3340
+ ErrorCodes.INVALID_INPUT,
3341
+ `Invalid fanout_harvest parameters: ${error.message}`,
3342
+ { tool: "fanout_harvest", operation: "validate parameters" }
3343
+ );
3344
+ throwMcpAXError(ErrorCode.InvalidParams, axError);
3345
+ }
3346
+ if (error instanceof GitHubAPIError) {
3347
+ const axError = githubApiError({
3348
+ message: error.message,
3349
+ });
3350
+ throwMcpAXError(ErrorCode.InternalError, axError);
3351
+ }
3352
+ throwMcpToolError(ErrorCode.InternalError, "fanout_harvest", error, "harvest from GitHub");
3353
+ }
3354
+ }
3355
+
3356
+ /**
3357
+ * Handle fanout_analyze tool
3358
+ * D1: Analyze a HarvestBundle into a deterministic AnalysisPool with evidence IDs
3359
+ */
3360
+ async function handleFanoutAnalyze(
3361
+ args: FanoutAnalyzeArgs
3362
+ ): Promise<{ content: [{ type: "text"; text: string }] }> {
3363
+ try {
3364
+ // Validate args
3365
+ const validated = FanoutAnalyzeArgs.parse(args);
3366
+
3367
+ let harvest: any;
3368
+
3369
+ // Get harvest bundle from args or file
3370
+ if (validated.harvestBundle) {
3371
+ harvest = validated.harvestBundle;
3372
+ } else if (validated.fromFile) {
3373
+ if (!fs.existsSync(validated.fromFile)) {
3374
+ const axError = mcpToolError(
3375
+ ErrorCodes.PLAN_NOT_FOUND,
3376
+ `Harvest bundle file not found: ${validated.fromFile}`,
3377
+ { tool: "fanout_analyze", operation: "load harvest bundle" }
3378
+ );
3379
+ throwMcpAXError(ErrorCode.InvalidParams, axError);
3380
+ }
3381
+ const content = fs.readFileSync(validated.fromFile, "utf-8");
3382
+ try {
3383
+ harvest = JSON.parse(content);
3384
+ } catch {
3385
+ const axError = mcpToolError(
3386
+ ErrorCodes.INVALID_INPUT,
3387
+ `Invalid JSON in harvest bundle file: ${validated.fromFile}`,
3388
+ { tool: "fanout_analyze", operation: "parse harvest bundle" }
3389
+ );
3390
+ throwMcpAXError(ErrorCode.InvalidParams, axError);
3391
+ }
3392
+ } else {
3393
+ const axError = mcpToolError(
3394
+ ErrorCodes.INVALID_INPUT,
3395
+ "Either harvestBundle or fromFile must be provided",
3396
+ { tool: "fanout_analyze", operation: "validate input" }
3397
+ );
3398
+ throwMcpAXError(ErrorCode.InvalidParams, axError);
3399
+ }
3400
+
3401
+ // Validate harvest bundle structure
3402
+ if (harvest.phase !== "D0") {
3403
+ const axError = mcpToolError(
3404
+ ErrorCodes.INVALID_INPUT,
3405
+ `Invalid input phase: ${harvest.phase}. Expected: D0 (HarvestBundle)`,
3406
+ { tool: "fanout_analyze", operation: "validate phase" }
3407
+ );
3408
+ throwMcpAXError(ErrorCode.InvalidParams, axError);
3409
+ }
3410
+
3411
+ const timestamp = new Date().toISOString();
3412
+ const inputDigest = harvest.outputDigest;
3413
+
3414
+ // Deterministic analysis
3415
+ const entities: Array<object> = [];
3416
+ const relations: Array<object> = [];
3417
+ const conflicts: Array<object> = [];
3418
+ const blockers: Array<object> = [];
3419
+
3420
+ // Track PRs by number
3421
+ const prByNumber = new Map<number, any>();
3422
+
3423
+ // Process pull requests
3424
+ for (const pr of harvest.bundle.pullRequests) {
3425
+ prByNumber.set(pr.number, pr);
3426
+ const eid = `PR:${pr.number}`;
3427
+
3428
+ // Build facts
3429
+ const facts: Array<object> = [
3430
+ { key: "title", value: pr.title, source: "api", confidence: "known" },
3431
+ { key: "state", value: pr.state, source: "api", confidence: "known" },
3432
+ { key: "author", value: pr.author, source: "api", confidence: "known" },
3433
+ { key: "labels", value: pr.labels, source: "api", confidence: "known" },
3434
+ { key: "head_sha", value: pr.headSha, source: "api", confidence: "known" },
3435
+ { key: "updated_at", value: pr.updatedAt, source: "api", confidence: "known" },
3436
+ ];
3437
+
3438
+ // CI status
3439
+ const ciConfidence = ["unknown", "unavailable"].includes(pr.ciStatus) ? pr.ciStatus : "known";
3440
+ facts.push({ key: "ci_status", value: pr.ciStatus, source: "api", confidence: ciConfidence });
3441
+
3442
+ // Review status
3443
+ const reviewConfidence = ["unknown", "unavailable"].includes(pr.reviewStatus)
3444
+ ? pr.reviewStatus
3445
+ : "known";
3446
+ facts.push({
3447
+ key: "review_status",
3448
+ value: pr.reviewStatus,
3449
+ source: "api",
3450
+ confidence: reviewConfidence,
3451
+ });
3452
+
3453
+ // Conflict status
3454
+ const conflictConfidence = ["unknown", "unavailable"].includes(pr.conflictStatus)
3455
+ ? pr.conflictStatus
3456
+ : "known";
3457
+ facts.push({
3458
+ key: "conflict_status",
3459
+ value: pr.conflictStatus,
3460
+ source: "api",
3461
+ confidence: conflictConfidence,
3462
+ });
3463
+
3464
+ entities.push({
3465
+ eid,
3466
+ type: "pull_request",
3467
+ ref: `#${pr.number}`,
3468
+ facts,
3469
+ });
3470
+
3471
+ // Detect blockers
3472
+ if (pr.ciStatus === "fail") {
3473
+ blockers.push({
3474
+ type: "ci_failed",
3475
+ entity: eid,
3476
+ reason: "CI checks failed",
3477
+ });
3478
+ }
3479
+
3480
+ if (pr.reviewStatus === "changes_requested") {
3481
+ blockers.push({
3482
+ type: "review_rejected",
3483
+ entity: eid,
3484
+ reason: "Changes requested in review",
3485
+ });
3486
+ }
3487
+
3488
+ if (pr.conflictStatus === "conflicted") {
3489
+ conflicts.push({
3490
+ type: "merge_conflict",
3491
+ entities: [eid],
3492
+ resolution: "requires_rebase",
3493
+ });
3494
+ }
3495
+
3496
+ if (pr.draft) {
3497
+ blockers.push({
3498
+ type: "draft",
3499
+ entity: eid,
3500
+ reason: "PR is in draft state",
3501
+ });
3502
+ }
3503
+ }
3504
+
3505
+ // Process issues
3506
+ for (const issue of harvest.bundle.issues) {
3507
+ const eid = `ISSUE:${issue.number}`;
3508
+
3509
+ const facts: Array<object> = [
3510
+ { key: "title", value: issue.title, source: "api", confidence: "known" },
3511
+ { key: "state", value: issue.state, source: "api", confidence: "known" },
3512
+ { key: "author", value: issue.author, source: "api", confidence: "known" },
3513
+ { key: "labels", value: issue.labels, source: "api", confidence: "known" },
3514
+ { key: "updated_at", value: issue.updatedAt, source: "api", confidence: "known" },
3515
+ ];
3516
+
3517
+ entities.push({
3518
+ eid,
3519
+ type: "issue",
3520
+ ref: `#${issue.number}`,
3521
+ facts,
3522
+ });
3523
+ }
3524
+
3525
+ const pool = {
3526
+ entities,
3527
+ relations,
3528
+ conflicts,
3529
+ blockers,
3530
+ };
3531
+
3532
+ const outputDigest = crypto.createHash("sha256").update(JSON.stringify(pool)).digest("hex");
3533
+
3534
+ const result: FanoutAnalyzeResult = {
3535
+ schemaVersion: "1.0.0",
3536
+ phase: "D1",
3537
+ timestamp,
3538
+ inputDigest,
3539
+ pool,
3540
+ outputDigest: `sha256:${outputDigest}`,
3541
+ };
3542
+
3543
+ console.error(
3544
+ `[mcp:fanout_analyze] analyzed ${entities.length} entities, ${relations.length} relations, ${conflicts.length} conflicts, ${blockers.length} blockers`
3545
+ );
3546
+
3547
+ return {
3548
+ content: [
3549
+ {
3550
+ type: "text",
3551
+ text: JSON.stringify(result, null, 2),
3552
+ },
3553
+ ],
3554
+ };
3555
+ } catch (error) {
3556
+ if (error instanceof Error && error.name === "ZodError") {
3557
+ const axError = mcpToolError(
3558
+ ErrorCodes.INVALID_INPUT,
3559
+ `Invalid fanout_analyze parameters: ${error.message}`,
3560
+ { tool: "fanout_analyze", operation: "validate parameters" }
3561
+ );
3562
+ throwMcpAXError(ErrorCode.InvalidParams, axError);
3563
+ }
3564
+ throwMcpToolError(ErrorCode.InternalError, "fanout_analyze", error, "analyze harvest bundle");
3565
+ }
3566
+ }
3567
+
3568
+ // Handle uncaught errors
3569
+ process.on("uncaughtException", (error) => {
3570
+ console.error("Uncaught exception:", error);
3571
+ process.exit(1);
3572
+ });
3573
+
3574
+ process.on("unhandledRejection", (reason, promise) => {
3575
+ console.error("Unhandled rejection at:", promise, "reason:", reason);
3576
+ process.exit(1);
3577
+ });
3578
+
3579
+ // Start the server if run directly (ESM-only)
3580
+ if (import.meta.url === `file://${process.argv[1]}`) {
3581
+ main().catch((error) => {
3582
+ console.error("Failed to start MCP server:", error);
3583
+ process.exit(1);
3584
+ });
3585
+ }
3586
+
3587
+ export { createServer, main };