beth-copilot 1.0.18 → 1.1.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 (291) hide show
  1. package/CHANGELOG.md +41 -28
  2. package/README.md +87 -247
  3. package/bin/cli.js +158 -358
  4. package/dist/__tests__/smoke.test.d.ts +8 -0
  5. package/dist/__tests__/smoke.test.d.ts.map +1 -0
  6. package/dist/__tests__/smoke.test.js +49 -0
  7. package/dist/__tests__/smoke.test.js.map +1 -0
  8. package/dist/cli/commands/beads.e2e.test.d.ts +13 -0
  9. package/dist/cli/commands/beads.e2e.test.d.ts.map +1 -0
  10. package/dist/cli/commands/beads.e2e.test.js +526 -0
  11. package/dist/cli/commands/beads.e2e.test.js.map +1 -0
  12. package/dist/cli/commands/cli-edge-cases.e2e.test.d.ts +32 -0
  13. package/dist/cli/commands/cli-edge-cases.e2e.test.d.ts.map +1 -0
  14. package/dist/cli/commands/cli-edge-cases.e2e.test.js +162 -0
  15. package/dist/cli/commands/cli-edge-cases.e2e.test.js.map +1 -0
  16. package/dist/cli/commands/close.d.ts +89 -0
  17. package/dist/cli/commands/close.d.ts.map +1 -0
  18. package/dist/cli/commands/close.e2e.test.d.ts +27 -0
  19. package/dist/cli/commands/close.e2e.test.d.ts.map +1 -0
  20. package/dist/cli/commands/close.e2e.test.js +252 -0
  21. package/dist/cli/commands/close.e2e.test.js.map +1 -0
  22. package/dist/cli/commands/close.js +309 -0
  23. package/dist/cli/commands/close.js.map +1 -0
  24. package/dist/cli/commands/close.test.d.ts +15 -0
  25. package/dist/cli/commands/close.test.d.ts.map +1 -0
  26. package/dist/cli/commands/close.test.js +634 -0
  27. package/dist/cli/commands/close.test.js.map +1 -0
  28. package/dist/cli/commands/doctor.d.ts +23 -0
  29. package/dist/cli/commands/doctor.d.ts.map +1 -1
  30. package/dist/cli/commands/doctor.js +93 -0
  31. package/dist/cli/commands/doctor.js.map +1 -1
  32. package/dist/cli/commands/doctor.test.js +209 -0
  33. package/dist/cli/commands/doctor.test.js.map +1 -1
  34. package/dist/cli/commands/framework-isolation.test.d.ts +30 -0
  35. package/dist/cli/commands/framework-isolation.test.d.ts.map +1 -0
  36. package/dist/cli/commands/framework-isolation.test.js +119 -0
  37. package/dist/cli/commands/framework-isolation.test.js.map +1 -0
  38. package/dist/cli/commands/help.e2e.test.js +4 -4
  39. package/dist/cli/commands/help.e2e.test.js.map +1 -1
  40. package/dist/cli/commands/init-logic.e2e.test.d.ts +37 -0
  41. package/dist/cli/commands/init-logic.e2e.test.d.ts.map +1 -0
  42. package/dist/cli/commands/init-logic.e2e.test.js +305 -0
  43. package/dist/cli/commands/init-logic.e2e.test.js.map +1 -0
  44. package/dist/cli/commands/land.d.ts +142 -0
  45. package/dist/cli/commands/land.d.ts.map +1 -0
  46. package/dist/cli/commands/land.js +647 -0
  47. package/dist/cli/commands/land.js.map +1 -0
  48. package/dist/cli/commands/land.test.d.ts +20 -0
  49. package/dist/cli/commands/land.test.d.ts.map +1 -0
  50. package/dist/cli/commands/land.test.js +622 -0
  51. package/dist/cli/commands/land.test.js.map +1 -0
  52. package/dist/cli/commands/mcp.e2e.test.js +22 -29
  53. package/dist/cli/commands/mcp.e2e.test.js.map +1 -1
  54. package/dist/cli/commands/pipeline.e2e.test.js +20 -20
  55. package/dist/cli/commands/pipeline.e2e.test.js.map +1 -1
  56. package/dist/cli/commands/pre-push-guard.d.ts +84 -0
  57. package/dist/cli/commands/pre-push-guard.d.ts.map +1 -0
  58. package/dist/cli/commands/pre-push-guard.e2e.test.d.ts +24 -0
  59. package/dist/cli/commands/pre-push-guard.e2e.test.d.ts.map +1 -0
  60. package/dist/cli/commands/pre-push-guard.e2e.test.js +171 -0
  61. package/dist/cli/commands/pre-push-guard.e2e.test.js.map +1 -0
  62. package/dist/cli/commands/pre-push-guard.js +257 -0
  63. package/dist/cli/commands/pre-push-guard.js.map +1 -0
  64. package/dist/cli/commands/pre-push-guard.test.d.ts +15 -0
  65. package/dist/cli/commands/pre-push-guard.test.d.ts.map +1 -0
  66. package/dist/cli/commands/pre-push-guard.test.js +397 -0
  67. package/dist/cli/commands/pre-push-guard.test.js.map +1 -0
  68. package/dist/cli/commands/quickstart-expanded.e2e.test.d.ts +23 -0
  69. package/dist/cli/commands/quickstart-expanded.e2e.test.d.ts.map +1 -0
  70. package/dist/cli/commands/quickstart-expanded.e2e.test.js +179 -0
  71. package/dist/cli/commands/quickstart-expanded.e2e.test.js.map +1 -0
  72. package/dist/cli/commands/quickstart.d.ts.map +1 -1
  73. package/dist/cli/commands/quickstart.js +7 -23
  74. package/dist/cli/commands/quickstart.js.map +1 -1
  75. package/dist/cli/commands/quickstart.test.js +40 -67
  76. package/dist/cli/commands/quickstart.test.js.map +1 -1
  77. package/dist/core/agents/suite.test.js +4 -2
  78. package/dist/core/agents/suite.test.js.map +1 -1
  79. package/dist/core/agents/tools.test.js +5 -1
  80. package/dist/core/agents/tools.test.js.map +1 -1
  81. package/dist/index.d.ts +3 -10
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +5 -10
  84. package/dist/index.js.map +1 -1
  85. package/package.json +15 -9
  86. package/sbom.json +2011 -819
  87. package/templates/.github/agents/beth.agent.md +220 -66
  88. package/templates/.github/agents/developer.agent.md +53 -90
  89. package/templates/.github/agents/product-manager.agent.md +15 -68
  90. package/templates/.github/agents/researcher.agent.md +20 -71
  91. package/templates/.github/agents/security-reviewer.agent.md +29 -81
  92. package/templates/.github/agents/tester.agent.md +40 -69
  93. package/templates/.github/agents/ux-designer.agent.md +20 -74
  94. package/templates/.github/copilot-instructions.md +217 -225
  95. package/templates/AGENTS.md +108 -20
  96. package/templates/mcp.json.example +0 -3
  97. package/dist/cli/commands/client-config.d.ts +0 -31
  98. package/dist/cli/commands/client-config.d.ts.map +0 -1
  99. package/dist/cli/commands/client-config.e2e.test.d.ts +0 -15
  100. package/dist/cli/commands/client-config.e2e.test.d.ts.map +0 -1
  101. package/dist/cli/commands/client-config.e2e.test.js +0 -556
  102. package/dist/cli/commands/client-config.e2e.test.js.map +0 -1
  103. package/dist/cli/commands/client-config.js +0 -73
  104. package/dist/cli/commands/client-config.js.map +0 -1
  105. package/dist/cli/commands/client-config.test.d.ts +0 -6
  106. package/dist/cli/commands/client-config.test.d.ts.map +0 -1
  107. package/dist/cli/commands/client-config.test.js +0 -133
  108. package/dist/cli/commands/client-config.test.js.map +0 -1
  109. package/dist/cli/commands/init-quickstart.e2e.test.d.ts +0 -11
  110. package/dist/cli/commands/init-quickstart.e2e.test.d.ts.map +0 -1
  111. package/dist/cli/commands/init-quickstart.e2e.test.js +0 -221
  112. package/dist/cli/commands/init-quickstart.e2e.test.js.map +0 -1
  113. package/dist/core/context.d.ts +0 -171
  114. package/dist/core/context.d.ts.map +0 -1
  115. package/dist/core/context.js +0 -353
  116. package/dist/core/context.js.map +0 -1
  117. package/dist/core/context.test.d.ts +0 -8
  118. package/dist/core/context.test.d.ts.map +0 -1
  119. package/dist/core/context.test.js +0 -253
  120. package/dist/core/context.test.js.map +0 -1
  121. package/dist/core/handoffs.d.ts +0 -151
  122. package/dist/core/handoffs.d.ts.map +0 -1
  123. package/dist/core/handoffs.js +0 -220
  124. package/dist/core/handoffs.js.map +0 -1
  125. package/dist/core/handoffs.test.d.ts +0 -8
  126. package/dist/core/handoffs.test.d.ts.map +0 -1
  127. package/dist/core/handoffs.test.js +0 -231
  128. package/dist/core/handoffs.test.js.map +0 -1
  129. package/dist/core/orchestrator.d.ts +0 -246
  130. package/dist/core/orchestrator.d.ts.map +0 -1
  131. package/dist/core/orchestrator.js +0 -514
  132. package/dist/core/orchestrator.js.map +0 -1
  133. package/dist/core/orchestrator.test.d.ts +0 -8
  134. package/dist/core/orchestrator.test.d.ts.map +0 -1
  135. package/dist/core/orchestrator.test.js +0 -517
  136. package/dist/core/orchestrator.test.js.map +0 -1
  137. package/dist/core/router.d.ts +0 -102
  138. package/dist/core/router.d.ts.map +0 -1
  139. package/dist/core/router.js +0 -178
  140. package/dist/core/router.js.map +0 -1
  141. package/dist/core/router.test.d.ts +0 -8
  142. package/dist/core/router.test.d.ts.map +0 -1
  143. package/dist/core/router.test.js +0 -215
  144. package/dist/core/router.test.js.map +0 -1
  145. package/dist/init.test.js +0 -288
  146. package/dist/providers/azure.d.ts +0 -147
  147. package/dist/providers/azure.d.ts.map +0 -1
  148. package/dist/providers/azure.js +0 -491
  149. package/dist/providers/azure.js.map +0 -1
  150. package/dist/providers/azure.test.d.ts +0 -11
  151. package/dist/providers/azure.test.d.ts.map +0 -1
  152. package/dist/providers/azure.test.js +0 -330
  153. package/dist/providers/azure.test.js.map +0 -1
  154. package/dist/providers/config.d.ts +0 -87
  155. package/dist/providers/config.d.ts.map +0 -1
  156. package/dist/providers/config.js +0 -193
  157. package/dist/providers/config.js.map +0 -1
  158. package/dist/providers/config.test.d.ts +0 -7
  159. package/dist/providers/config.test.d.ts.map +0 -1
  160. package/dist/providers/config.test.js +0 -370
  161. package/dist/providers/config.test.js.map +0 -1
  162. package/dist/providers/index.d.ts +0 -18
  163. package/dist/providers/index.d.ts.map +0 -1
  164. package/dist/providers/index.js +0 -14
  165. package/dist/providers/index.js.map +0 -1
  166. package/dist/providers/interface.d.ts +0 -191
  167. package/dist/providers/interface.d.ts.map +0 -1
  168. package/dist/providers/interface.js +0 -94
  169. package/dist/providers/interface.js.map +0 -1
  170. package/dist/providers/retry.d.ts +0 -128
  171. package/dist/providers/retry.d.ts.map +0 -1
  172. package/dist/providers/retry.js +0 -205
  173. package/dist/providers/retry.js.map +0 -1
  174. package/dist/providers/retry.test.d.ts +0 -7
  175. package/dist/providers/retry.test.d.ts.map +0 -1
  176. package/dist/providers/retry.test.js +0 -439
  177. package/dist/providers/retry.test.js.map +0 -1
  178. package/dist/providers/streaming.d.ts +0 -157
  179. package/dist/providers/streaming.d.ts.map +0 -1
  180. package/dist/providers/streaming.js +0 -233
  181. package/dist/providers/streaming.js.map +0 -1
  182. package/dist/providers/streaming.test.d.ts +0 -7
  183. package/dist/providers/streaming.test.d.ts.map +0 -1
  184. package/dist/providers/streaming.test.js +0 -372
  185. package/dist/providers/streaming.test.js.map +0 -1
  186. package/dist/providers/types.d.ts +0 -209
  187. package/dist/providers/types.d.ts.map +0 -1
  188. package/dist/providers/types.js +0 -53
  189. package/dist/providers/types.js.map +0 -1
  190. package/dist/providers/types.test.d.ts +0 -7
  191. package/dist/providers/types.test.d.ts.map +0 -1
  192. package/dist/providers/types.test.js +0 -141
  193. package/dist/providers/types.test.js.map +0 -1
  194. package/dist/tools/cli/beads.d.ts +0 -27
  195. package/dist/tools/cli/beads.d.ts.map +0 -1
  196. package/dist/tools/cli/beads.js +0 -172
  197. package/dist/tools/cli/beads.js.map +0 -1
  198. package/dist/tools/cli/beads.test.d.ts +0 -8
  199. package/dist/tools/cli/beads.test.d.ts.map +0 -1
  200. package/dist/tools/cli/beads.test.js +0 -264
  201. package/dist/tools/cli/beads.test.js.map +0 -1
  202. package/dist/tools/cli/editFile.d.ts +0 -17
  203. package/dist/tools/cli/editFile.d.ts.map +0 -1
  204. package/dist/tools/cli/editFile.js +0 -125
  205. package/dist/tools/cli/editFile.js.map +0 -1
  206. package/dist/tools/cli/editFile.test.d.ts +0 -8
  207. package/dist/tools/cli/editFile.test.d.ts.map +0 -1
  208. package/dist/tools/cli/editFile.test.js +0 -177
  209. package/dist/tools/cli/editFile.test.js.map +0 -1
  210. package/dist/tools/cli/readFile.d.ts +0 -25
  211. package/dist/tools/cli/readFile.d.ts.map +0 -1
  212. package/dist/tools/cli/readFile.js +0 -118
  213. package/dist/tools/cli/readFile.js.map +0 -1
  214. package/dist/tools/cli/readFile.test.d.ts +0 -8
  215. package/dist/tools/cli/readFile.test.d.ts.map +0 -1
  216. package/dist/tools/cli/readFile.test.js +0 -194
  217. package/dist/tools/cli/readFile.test.js.map +0 -1
  218. package/dist/tools/cli/search.d.ts +0 -16
  219. package/dist/tools/cli/search.d.ts.map +0 -1
  220. package/dist/tools/cli/search.js +0 -261
  221. package/dist/tools/cli/search.js.map +0 -1
  222. package/dist/tools/cli/search.test.d.ts +0 -8
  223. package/dist/tools/cli/search.test.d.ts.map +0 -1
  224. package/dist/tools/cli/search.test.js +0 -172
  225. package/dist/tools/cli/search.test.js.map +0 -1
  226. package/dist/tools/cli/subagent.d.ts +0 -43
  227. package/dist/tools/cli/subagent.d.ts.map +0 -1
  228. package/dist/tools/cli/subagent.js +0 -99
  229. package/dist/tools/cli/subagent.js.map +0 -1
  230. package/dist/tools/cli/subagent.test.d.ts +0 -8
  231. package/dist/tools/cli/subagent.test.d.ts.map +0 -1
  232. package/dist/tools/cli/subagent.test.js +0 -190
  233. package/dist/tools/cli/subagent.test.js.map +0 -1
  234. package/dist/tools/cli/terminal.d.ts +0 -19
  235. package/dist/tools/cli/terminal.d.ts.map +0 -1
  236. package/dist/tools/cli/terminal.js +0 -164
  237. package/dist/tools/cli/terminal.js.map +0 -1
  238. package/dist/tools/cli/terminal.test.d.ts +0 -8
  239. package/dist/tools/cli/terminal.test.d.ts.map +0 -1
  240. package/dist/tools/cli/terminal.test.js +0 -161
  241. package/dist/tools/cli/terminal.test.js.map +0 -1
  242. package/dist/tools/index.d.ts +0 -25
  243. package/dist/tools/index.d.ts.map +0 -1
  244. package/dist/tools/index.js +0 -41
  245. package/dist/tools/index.js.map +0 -1
  246. package/dist/tools/interface.d.ts +0 -64
  247. package/dist/tools/interface.d.ts.map +0 -1
  248. package/dist/tools/interface.js +0 -37
  249. package/dist/tools/interface.js.map +0 -1
  250. package/dist/tools/interface.test.d.ts +0 -7
  251. package/dist/tools/interface.test.d.ts.map +0 -1
  252. package/dist/tools/interface.test.js +0 -179
  253. package/dist/tools/interface.test.js.map +0 -1
  254. package/dist/tools/mcp/bridge.d.ts +0 -48
  255. package/dist/tools/mcp/bridge.d.ts.map +0 -1
  256. package/dist/tools/mcp/bridge.js +0 -128
  257. package/dist/tools/mcp/bridge.js.map +0 -1
  258. package/dist/tools/mcp/bridge.test.d.ts +0 -8
  259. package/dist/tools/mcp/bridge.test.d.ts.map +0 -1
  260. package/dist/tools/mcp/bridge.test.js +0 -300
  261. package/dist/tools/mcp/bridge.test.js.map +0 -1
  262. package/dist/tools/mcp/client.d.ts +0 -135
  263. package/dist/tools/mcp/client.d.ts.map +0 -1
  264. package/dist/tools/mcp/client.js +0 -263
  265. package/dist/tools/mcp/client.js.map +0 -1
  266. package/dist/tools/mcp/client.test.d.ts +0 -8
  267. package/dist/tools/mcp/client.test.d.ts.map +0 -1
  268. package/dist/tools/mcp/client.test.js +0 -390
  269. package/dist/tools/mcp/client.test.js.map +0 -1
  270. package/dist/tools/registry.d.ts +0 -82
  271. package/dist/tools/registry.d.ts.map +0 -1
  272. package/dist/tools/registry.js +0 -99
  273. package/dist/tools/registry.js.map +0 -1
  274. package/dist/tools/registry.test.d.ts +0 -7
  275. package/dist/tools/registry.test.d.ts.map +0 -1
  276. package/dist/tools/registry.test.js +0 -199
  277. package/dist/tools/registry.test.js.map +0 -1
  278. package/dist/tools/suite.test.d.ts +0 -11
  279. package/dist/tools/suite.test.d.ts.map +0 -1
  280. package/dist/tools/suite.test.js +0 -119
  281. package/dist/tools/suite.test.js.map +0 -1
  282. package/dist/tools/types.d.ts +0 -75
  283. package/dist/tools/types.d.ts.map +0 -1
  284. package/dist/tools/types.js +0 -30
  285. package/dist/tools/types.js.map +0 -1
  286. package/dist/tools/types.test.d.ts +0 -7
  287. package/dist/tools/types.test.d.ts.map +0 -1
  288. package/dist/tools/types.test.js +0 -178
  289. package/dist/tools/types.test.js.map +0 -1
  290. package/templates/.vscode/mcp.json +0 -20
  291. package/templates/CLAUDE.md +0 -129
package/bin/cli.js CHANGED
@@ -775,6 +775,77 @@ async function runBeadsDoctor() {
775
775
  });
776
776
  }
777
777
 
778
+ const BETH_GUARD_BEGIN = '# --- BEGIN BETH GUARD ---';
779
+ const BETH_GUARD_END = '# --- END BETH GUARD ---';
780
+
781
+ /**
782
+ * Generate the shell script to append to the pre-push hook.
783
+ * Pure shell — no Node dependency at hook time for speed.
784
+ */
785
+ function generateGuardScript() {
786
+ return `
787
+ ${BETH_GUARD_BEGIN}
788
+ # Branch discipline enforcement — installed by beth-copilot
789
+ # Bypass: BETH_SKIP_PUSH_GUARD=1 git push
790
+ if [ "\$BETH_SKIP_PUSH_GUARD" = "1" ]; then
791
+ echo "⚠ Pre-push guard bypassed (BETH_SKIP_PUSH_GUARD=1)" >&2
792
+ else
793
+ _beth_branch=\$(git branch --show-current 2>/dev/null)
794
+
795
+ # Block pushes from protected branches
796
+ case "\$_beth_branch" in
797
+ main|master)
798
+ echo "✗ Pushing from '\$_beth_branch' is blocked. Work on an epic branch." >&2
799
+ echo " Set BETH_SKIP_PUSH_GUARD=1 to bypass." >&2
800
+ exit 1
801
+ ;;
802
+ esac
803
+
804
+ # Warn if not on an epic or release branch
805
+ case "\$_beth_branch" in
806
+ epic/*) ;;
807
+ release/*) ;;
808
+ "")
809
+ echo "⚠ Detached HEAD — no branch name. Proceeding anyway." >&2
810
+ ;;
811
+ *)
812
+ echo "⚠ Branch '\$_beth_branch' doesn't follow the epic/<id> convention." >&2
813
+ ;;
814
+ esac
815
+ fi
816
+ ${BETH_GUARD_END}
817
+ `;
818
+ }
819
+
820
+ /**
821
+ * Install the pre-push guard into .beads/hooks/pre-push.
822
+ * Appends the guard section after the beads integration section.
823
+ * Idempotent — skips if guard is already installed.
824
+ *
825
+ * @param {string} cwd - Project root directory
826
+ */
827
+ function installPrePushGuard(cwd) {
828
+ const hookPath = join(cwd, '.beads', 'hooks', 'pre-push');
829
+
830
+ if (!existsSync(hookPath)) {
831
+ logWarning('Pre-push hook not found (.beads/hooks/pre-push). Skipping guard installation.');
832
+ return;
833
+ }
834
+
835
+ const content = readFileSync(hookPath, 'utf-8');
836
+
837
+ // Already installed?
838
+ if (content.includes(BETH_GUARD_BEGIN)) {
839
+ logSuccess('Pre-push branch guard already installed');
840
+ return;
841
+ }
842
+
843
+ // Append guard after existing content
844
+ const guardScript = generateGuardScript();
845
+ writeFileSync(hookPath, content.trimEnd() + '\n' + guardScript, 'utf-8');
846
+ logSuccess('Installed pre-push branch guard (blocks direct pushes to main)');
847
+ }
848
+
778
849
  function showHelp() {
779
850
  showBethBannerStatic({ showQuickHelp: false });
780
851
  console.log(`${COLORS.bright}Beth${COLORS.reset} - AI Orchestrator for GitHub Copilot
@@ -782,65 +853,43 @@ function showHelp() {
782
853
  ${COLORS.bright}Usage:${COLORS.reset}
783
854
  npx beth-copilot init [options] Initialize Beth in current directory
784
855
  npx beth-copilot doctor Check system health and dependencies
856
+ npx beth-copilot close <id> [opts] Close issue with dependency enforcement
857
+ npx beth-copilot land [opts] Automated session completion (test, commit, push)
858
+ npx beth-copilot pre-push-guard Run branch discipline checks (used by git hook)
785
859
  npx beth-copilot quickstart Run init + doctor + beads setup
786
860
  npx beth-copilot help Show this help message
787
861
 
788
862
  ${COLORS.bright}Options:${COLORS.reset}
789
863
  --force Overwrite existing files
790
864
  --skip-backlog Don't create Backlog.md
791
- --skip-mcp Don't install MCP server configs
865
+ --skip-mcp Don't create mcp.json.example
792
866
  --skip-beads Skip beads check (not recommended)
793
867
  --verbose Show detailed diagnostics on errors
794
- --client <type> Skip interactive prompt. Values:
795
- vscode, copilot-cli, claude-code, all
796
868
 
797
869
  ${COLORS.bright}Examples:${COLORS.reset}
798
- npx beth-copilot init Set up Beth (interactive client selection)
799
- npx beth-copilot init --client vscode VS Code + Copilot only
800
- npx beth-copilot init --client claude-code Claude Code only
801
- npx beth-copilot init --client all All clients
870
+ npx beth-copilot init Set up Beth in current project
802
871
  npx beth-copilot init --force Overwrite existing Beth files
803
872
  npx beth-copilot doctor Verify installation health
804
873
 
805
874
  ${COLORS.bright}What gets installed:${COLORS.reset}
806
- ${COLORS.dim}Shared (all clients):${COLORS.reset}
807
- .github/skills/ Domain knowledge modules
808
- AGENTS.md Workflow documentation
809
- Backlog.md Task tracking file
810
-
811
- ${COLORS.dim}VS Code + GitHub Copilot:${COLORS.reset}
812
- .github/agents/ 7 specialized AI agents
813
- .github/copilot-instructions.md Copilot configuration
814
- .vscode/settings.json Recommended VS Code settings
815
- .vscode/mcp.json MCP servers (beads, shadcn, playwright, deepwiki)
816
-
817
- ${COLORS.dim}GitHub Copilot CLI:${COLORS.reset}
818
- .github/copilot-instructions.md Copilot configuration
819
-
820
- ${COLORS.dim}Claude Code:${COLORS.reset}
821
- CLAUDE.md Claude Code instructions
822
-
823
- ${COLORS.bright}Supported clients:${COLORS.reset}
824
- VS Code with GitHub Copilot Full agent orchestration with MCP
825
- GitHub Copilot CLI Terminal-based with bd CLI
826
- Claude Code CLAUDE.md + bd setup claude hooks
875
+ .github/agents/ 7 specialized AI agents
876
+ .github/skills/ 8 domain knowledge modules
877
+ .github/copilot-instructions.md Copilot configuration
878
+ .vscode/settings.json Recommended VS Code settings
879
+ AGENTS.md Workflow documentation
880
+ Backlog.md Task tracking file
881
+ mcp.json.example Optional MCP server config
882
+
883
+ ${COLORS.bright}After installation:${COLORS.reset}
884
+ 1. Open project in VS Code
885
+ 2. Open Copilot Chat (Ctrl+Alt+I / Cmd+Alt+I)
886
+ 3. Type @Beth to start working
827
887
 
828
888
  ${COLORS.bright}Documentation:${COLORS.reset}
829
889
  https://github.com/stephschofield/beth
830
890
  `);
831
891
  }
832
892
 
833
- /**
834
- * Persist client selection to .github/.beth-client.json
835
- * So quickstart and other commands know which client was configured.
836
- */
837
- function persistClientConfig(cwd, clients) {
838
- const configDir = join(cwd, '.github');
839
- const configPath = join(configDir, '.beth-client.json');
840
- mkdirSync(configDir, { recursive: true });
841
- writeFileSync(configPath, JSON.stringify(clients, null, 2) + '\n');
842
- }
843
-
844
893
  function copyDirRecursive(src, dest, options = {}) {
845
894
  const { force = false, copiedFiles = [] } = options;
846
895
 
@@ -889,149 +938,8 @@ function copyDirRecursive(src, dest, options = {}) {
889
938
  return copiedFiles;
890
939
  }
891
940
 
892
- /**
893
- * Prompt the user to select their AI coding client(s).
894
- * Returns an object with boolean flags for each client.
895
- */
896
- async function promptForClient() {
897
- console.log('');
898
- log('Which AI coding tool are you using?', COLORS.bright);
899
- console.log('');
900
- console.log(` ${COLORS.cyan}[1]${COLORS.reset} VS Code with GitHub Copilot`);
901
- console.log(` ${COLORS.cyan}[2]${COLORS.reset} GitHub Copilot CLI (terminal)`);
902
- console.log(` ${COLORS.cyan}[3]${COLORS.reset} Claude Code`);
903
- console.log(` ${COLORS.cyan}[a]${COLORS.reset} All of the above`);
904
- console.log('');
905
-
906
- const answer = await promptForInput('Enter selection (1/2/3/a, or comma-separated e.g. 1,3):');
907
-
908
- if (!answer || answer.toLowerCase() === 'a') {
909
- return { vscode: true, copilotCli: true, claudeCode: true };
910
- }
911
-
912
- const selections = answer.split(',').map(s => s.trim());
913
- return {
914
- vscode: selections.includes('1'),
915
- copilotCli: selections.includes('2'),
916
- claudeCode: selections.includes('3'),
917
- };
918
- }
919
-
920
- /**
921
- * Parse --client flag value into client selection object.
922
- */
923
- function parseClientFlag(clientArg) {
924
- if (!clientArg || clientArg === 'all') {
925
- return { vscode: true, copilotCli: true, claudeCode: true };
926
- }
927
- return {
928
- vscode: clientArg === 'vscode',
929
- copilotCli: clientArg === 'copilot-cli',
930
- claudeCode: clientArg === 'claude-code',
931
- };
932
- }
933
-
934
- /**
935
- * Install beads-mcp (MCP server) for VS Code integration.
936
- *
937
- * SECURITY NOTE - shell:true usage:
938
- * - Required for cross-platform uv/pip execution
939
- * - Arguments are HARDCODED - no user input is passed to the shell
940
- * - Command injection risk: NONE (no dynamic/user-supplied values)
941
- */
942
- async function installBeadsMcp() {
943
- log('\nInstalling beads-mcp (MCP server for VS Code)...', COLORS.cyan);
944
-
945
- // Try uv first, then pip
946
- const installers = [
947
- { cmd: 'uv', args: ['tool', 'install', 'beads-mcp'], label: 'uv tool install beads-mcp' },
948
- { cmd: 'pip', args: ['install', 'beads-mcp'], label: 'pip install beads-mcp' },
949
- ];
950
-
951
- for (const installer of installers) {
952
- try {
953
- execSync(`${installer.cmd} --version`, { stdio: 'ignore' });
954
- } catch {
955
- logDebug(`${installer.cmd} not found, trying next installer...`);
956
- continue;
957
- }
958
-
959
- logInfo(installer.label);
960
-
961
- // SECURITY: All arguments are hardcoded constants.
962
- return new Promise((resolve) => {
963
- const child = spawn(installer.cmd, installer.args, {
964
- stdio: 'inherit',
965
- shell: true,
966
- });
967
-
968
- child.on('close', (code) => {
969
- if (code === 0) {
970
- logSuccess('beads-mcp installed!');
971
- resolve(true);
972
- } else {
973
- logWarning(`${installer.label} failed.`);
974
- resolve(false);
975
- }
976
- });
977
-
978
- child.on('error', () => {
979
- logWarning(`Failed to run ${installer.cmd}.`);
980
- resolve(false);
981
- });
982
- });
983
- }
984
-
985
- logWarning('Neither uv nor pip found. Install beads-mcp manually:');
986
- logInfo(' uv tool install beads-mcp');
987
- logInfo(' OR: pip install beads-mcp');
988
- return false;
989
- }
990
-
991
- /**
992
- * Run `bd setup claude` to configure Claude Code integration.
993
- *
994
- * SECURITY NOTE - shell:true usage:
995
- * - bdPath is validated via getBeadsPath()
996
- * - Arguments are HARDCODED ('setup', 'claude')
997
- * - Command injection risk: LOW (bdPath validated, no user input in args)
998
- */
999
- async function runBdSetupClaude() {
1000
- log('\nConfiguring beads for Claude Code...', COLORS.cyan);
1001
-
1002
- const bdPath = getBeadsPath();
1003
- if (!bdPath) {
1004
- logWarning('Cannot run bd setup claude: bd not found.');
1005
- logInfo('Run manually after installing beads: bd setup claude');
1006
- return false;
1007
- }
1008
-
1009
- // SECURITY: bdPath is validated, only hardcoded args.
1010
- return new Promise((resolve) => {
1011
- const child = spawn(bdPath, ['setup', 'claude'], {
1012
- stdio: 'inherit',
1013
- shell: true,
1014
- });
1015
-
1016
- child.on('close', (code) => {
1017
- if (code === 0) {
1018
- logSuccess('Claude Code integration configured!');
1019
- resolve(true);
1020
- } else {
1021
- logWarning('bd setup claude failed. Run manually: bd setup claude');
1022
- resolve(false);
1023
- }
1024
- });
1025
-
1026
- child.on('error', () => {
1027
- logWarning('Failed to run bd setup claude. Run manually: bd setup claude');
1028
- resolve(false);
1029
- });
1030
- });
1031
- }
1032
-
1033
941
  async function init(options = {}) {
1034
- const { force = false, skipBacklog = false, skipMcp = false, skipBeads = false, client: clientArg } = options;
942
+ const { force = false, skipBacklog = false, skipMcp = false, skipBeads = false } = options;
1035
943
  const cwd = process.cwd();
1036
944
 
1037
945
  // Check for updates
@@ -1054,27 +962,6 @@ ${COLORS.yellow}╔════════════════════
1054
962
 
1055
963
  log(`${COLORS.yellow}Tip: Run with --verbose for detailed diagnostics if you hit issues.${COLORS.reset}`);
1056
964
 
1057
- // Determine which client(s) to configure
1058
- let clients;
1059
- if (clientArg) {
1060
- clients = parseClientFlag(clientArg);
1061
- } else {
1062
- clients = await promptForClient();
1063
- }
1064
-
1065
- // Validate at least one client selected
1066
- if (!clients.vscode && !clients.copilotCli && !clients.claudeCode) {
1067
- logWarning('No client selected. Defaulting to VS Code with GitHub Copilot.');
1068
- clients.vscode = true;
1069
- }
1070
-
1071
- const selectedNames = [];
1072
- if (clients.vscode) selectedNames.push('VS Code + Copilot');
1073
- if (clients.copilotCli) selectedNames.push('Copilot CLI');
1074
- if (clients.claudeCode) selectedNames.push('Claude Code');
1075
- log(`\nConfiguring for: ${COLORS.cyan}${selectedNames.join(', ')}${COLORS.reset}`);
1076
-
1077
-
1078
965
  // Check if templates exist
1079
966
  if (!existsSync(TEMPLATES_DIR)) {
1080
967
  logError('Templates directory not found. Package may be corrupted.');
@@ -1083,15 +970,13 @@ ${COLORS.yellow}╔════════════════════
1083
970
 
1084
971
  const copiedFiles = [];
1085
972
 
1086
- // === SHARED FILES (all clients) ===
1087
-
1088
- // Copy .github/skills/ (domain knowledge - useful for all clients)
1089
- const skillsSrc = join(TEMPLATES_DIR, '.github', 'skills');
1090
- const skillsDest = join(cwd, '.github', 'skills');
973
+ // Copy .github directory (agents, skills, copilot-instructions.md)
974
+ const githubSrc = join(TEMPLATES_DIR, '.github');
975
+ const githubDest = join(cwd, '.github');
1091
976
 
1092
- if (existsSync(skillsSrc)) {
1093
- log('\nInstalling skills (domain knowledge)...');
1094
- copyDirRecursive(skillsSrc, skillsDest, { force, copiedFiles });
977
+ if (existsSync(githubSrc)) {
978
+ log('\nInstalling agents and skills...');
979
+ copyDirRecursive(githubSrc, githubDest, { force, copiedFiles });
1095
980
  }
1096
981
 
1097
982
  // Copy AGENTS.md
@@ -1122,38 +1007,33 @@ ${COLORS.yellow}╔════════════════════
1122
1007
  }
1123
1008
  }
1124
1009
 
1125
- // === VS CODE + COPILOT FILES ===
1126
- if (clients.vscode) {
1127
- log('\nInstalling VS Code + Copilot configuration...');
1128
-
1129
- // .github/agents/ (agent definitions with frontmatter)
1130
- const agentsSrc = join(TEMPLATES_DIR, '.github', 'agents');
1131
- const agentsDest = join(cwd, '.github', 'agents');
1132
- if (existsSync(agentsSrc)) {
1133
- copyDirRecursive(agentsSrc, agentsDest, { force, copiedFiles });
1134
- }
1010
+ // Copy mcp.json.example (unless skipped)
1011
+ if (!skipMcp) {
1012
+ const mcpSrc = join(TEMPLATES_DIR, 'mcp.json.example');
1013
+ const mcpDest = join(cwd, 'mcp.json.example');
1135
1014
 
1136
- // .github/copilot-instructions.md
1137
- const copilotInstructionsSrc = join(TEMPLATES_DIR, '.github', 'copilot-instructions.md');
1138
- const copilotInstructionsDest = join(cwd, '.github', 'copilot-instructions.md');
1139
- if (existsSync(copilotInstructionsSrc)) {
1140
- if (existsSync(copilotInstructionsDest) && !force) {
1141
- logWarning('Skipped (exists): .github/copilot-instructions.md');
1015
+ if (existsSync(mcpSrc)) {
1016
+ if (existsSync(mcpDest) && !force) {
1017
+ logWarning('Skipped (exists): mcp.json.example');
1142
1018
  } else {
1143
- mkdirSync(join(cwd, '.github'), { recursive: true });
1144
- copyFileSync(copilotInstructionsSrc, copilotInstructionsDest);
1145
- copiedFiles.push('.github/copilot-instructions.md');
1019
+ copyFileSync(mcpSrc, mcpDest);
1020
+ copiedFiles.push('mcp.json.example');
1146
1021
  }
1147
1022
  }
1148
-
1149
- // .vscode/settings.json
1150
- const vscodeDest = join(cwd, '.vscode');
1023
+ }
1024
+
1025
+ // Copy .vscode/settings.json (recommended settings for agent mode)
1026
+ const vscodeSrc = join(TEMPLATES_DIR, '.vscode');
1027
+ const vscodeDest = join(cwd, '.vscode');
1028
+
1029
+ if (existsSync(vscodeSrc)) {
1151
1030
  if (!existsSync(vscodeDest)) {
1152
1031
  mkdirSync(vscodeDest, { recursive: true });
1153
1032
  }
1154
1033
 
1155
- const settingsSrc = join(TEMPLATES_DIR, '.vscode', 'settings.json');
1034
+ const settingsSrc = join(vscodeSrc, 'settings.json');
1156
1035
  const settingsDest = join(vscodeDest, 'settings.json');
1036
+
1157
1037
  if (existsSync(settingsSrc)) {
1158
1038
  if (existsSync(settingsDest) && !force) {
1159
1039
  logWarning('Skipped (exists): .vscode/settings.json');
@@ -1162,61 +1042,8 @@ ${COLORS.yellow}╔════════════════════
1162
1042
  copiedFiles.push('.vscode/settings.json');
1163
1043
  }
1164
1044
  }
1165
-
1166
- // .vscode/mcp.json (beads + shadcn + playwright + deepwiki)
1167
- if (!skipMcp) {
1168
- const mcpJsonSrc = join(TEMPLATES_DIR, '.vscode', 'mcp.json');
1169
- const mcpJsonDest = join(vscodeDest, 'mcp.json');
1170
- if (existsSync(mcpJsonSrc)) {
1171
- if (existsSync(mcpJsonDest) && !force) {
1172
- logWarning('Skipped (exists): .vscode/mcp.json');
1173
- } else {
1174
- copyFileSync(mcpJsonSrc, mcpJsonDest);
1175
- copiedFiles.push('.vscode/mcp.json');
1176
- }
1177
- }
1178
- }
1179
- }
1180
-
1181
- // === COPILOT CLI FILES ===
1182
- if (clients.copilotCli && !clients.vscode) {
1183
- // Only install copilot-instructions.md if VS Code didn't already do it
1184
- log('\nInstalling Copilot CLI configuration...');
1185
-
1186
- const copilotInstructionsSrc = join(TEMPLATES_DIR, '.github', 'copilot-instructions.md');
1187
- const copilotInstructionsDest = join(cwd, '.github', 'copilot-instructions.md');
1188
- if (existsSync(copilotInstructionsSrc)) {
1189
- if (existsSync(copilotInstructionsDest) && !force) {
1190
- logWarning('Skipped (exists): .github/copilot-instructions.md');
1191
- } else {
1192
- mkdirSync(join(cwd, '.github'), { recursive: true });
1193
- copyFileSync(copilotInstructionsSrc, copilotInstructionsDest);
1194
- copiedFiles.push('.github/copilot-instructions.md');
1195
- }
1196
- }
1197
- }
1198
-
1199
- // === CLAUDE CODE FILES ===
1200
- if (clients.claudeCode) {
1201
- log('\nInstalling Claude Code configuration...');
1202
-
1203
- // CLAUDE.md
1204
- const claudeMdSrc = join(TEMPLATES_DIR, 'CLAUDE.md');
1205
- const claudeMdDest = join(cwd, 'CLAUDE.md');
1206
- if (existsSync(claudeMdSrc)) {
1207
- if (existsSync(claudeMdDest) && !force) {
1208
- logWarning('Skipped (exists): CLAUDE.md');
1209
- } else {
1210
- copyFileSync(claudeMdSrc, claudeMdDest);
1211
- copiedFiles.push('CLAUDE.md');
1212
- }
1213
- }
1214
1045
  }
1215
1046
 
1216
- // Persist client selection for quickstart and other commands
1217
- persistClientConfig(cwd, clients);
1218
- copiedFiles.push('.github/.beth-client.json');
1219
-
1220
1047
  // Summary
1221
1048
  console.log('');
1222
1049
  if (copiedFiles.length > 0) {
@@ -1342,27 +1169,9 @@ ${COLORS.yellow}╔════════════════════
1342
1169
  await runBeadsDoctor();
1343
1170
  }
1344
1171
 
1345
- // === CLIENT-SPECIFIC BEADS INTEGRATION ===
1346
- if (!skipBeads && getBeadsPath() && isBeadsInitialized(cwd)) {
1347
- // VS Code: install beads-mcp (MCP server)
1348
- if (clients.vscode) {
1349
- const shouldInstallMcp = await promptYesNo('Install beads-mcp for VS Code MCP integration?');
1350
- if (shouldInstallMcp) {
1351
- await installBeadsMcp();
1352
- } else {
1353
- logInfo('Skipped beads-mcp. Install later with: uv tool install beads-mcp');
1354
- }
1355
- }
1356
-
1357
- // Claude Code: run bd setup claude
1358
- if (clients.claudeCode) {
1359
- const shouldSetupClaude = await promptYesNo('Configure beads for Claude Code? (bd setup claude)');
1360
- if (shouldSetupClaude) {
1361
- await runBdSetupClaude();
1362
- } else {
1363
- logInfo('Skipped Claude Code setup. Run later: bd setup claude');
1364
- }
1365
- }
1172
+ // Install pre-push guard hook
1173
+ if (!skipBeads && isBeadsInitialized(cwd)) {
1174
+ installPrePushGuard(cwd);
1366
1175
  }
1367
1176
 
1368
1177
  // Final verification
@@ -1381,35 +1190,15 @@ ${COLORS.yellow}╔════════════════════
1381
1190
  process.exit(1);
1382
1191
  }
1383
1192
 
1384
- // Next steps (client-specific)
1385
- console.log('');
1386
- log('Next steps:', COLORS.bright);
1387
-
1388
- if (clients.vscode) {
1389
- console.log(`
1390
- ${COLORS.bright}VS Code + Copilot:${COLORS.reset}
1193
+ // Next steps
1194
+ console.log(`
1195
+ ${COLORS.bright}Next steps:${COLORS.reset}
1391
1196
  1. Open this project in VS Code
1392
1197
  2. Open Copilot Chat (${COLORS.cyan}Ctrl+Alt+I${COLORS.reset} / ${COLORS.cyan}Cmd+Alt+I${COLORS.reset})
1393
- 3. Type ${COLORS.cyan}@Beth${COLORS.reset} to start she's your orchestrator`);
1394
- }
1395
-
1396
- if (clients.copilotCli) {
1397
- console.log(`
1398
- ${COLORS.bright}Copilot CLI:${COLORS.reset}
1399
- 1. Run ${COLORS.cyan}copilot${COLORS.reset} in your project directory
1400
- 2. Beth's instructions are in ${COLORS.cyan}.github/copilot-instructions.md${COLORS.reset}
1401
- 3. Use ${COLORS.cyan}bd ready${COLORS.reset} to find work, ${COLORS.cyan}bd create${COLORS.reset} to track tasks`);
1402
- }
1403
-
1404
- if (clients.claudeCode) {
1405
- console.log(`
1406
- ${COLORS.bright}Claude Code:${COLORS.reset}
1407
- 1. Run ${COLORS.cyan}claude${COLORS.reset} in your project directory
1408
- 2. Beth's instructions are in ${COLORS.cyan}CLAUDE.md${COLORS.reset}
1409
- 3. Use ${COLORS.cyan}bd ready${COLORS.reset} to find work, ${COLORS.cyan}bd prime${COLORS.reset} for session context`);
1410
- }
1198
+ 3. Type ${COLORS.cyan}@Beth${COLORS.reset} to start - she's your orchestrator
1199
+
1200
+ ${COLORS.bright}Pro tip:${COLORS.reset} Start every session with ${COLORS.cyan}@Beth${COLORS.reset} and let her route work to the right specialists.
1411
1201
 
1412
- console.log(`
1413
1202
  ${COLORS.bright}Documentation:${COLORS.reset}
1414
1203
  https://github.com/stephschofield/beth
1415
1204
 
@@ -1418,13 +1207,16 @@ ${COLORS.cyan}"They broke my wings and forgot I had claws."${COLORS.reset}
1418
1207
  }
1419
1208
 
1420
1209
  // Input validation constants
1421
- const ALLOWED_COMMANDS = ['init', 'help', '--help', '-h', 'doctor', 'quickstart'];
1422
- const ALLOWED_FLAGS = ['--force', '--skip-backlog', '--skip-mcp', '--skip-beads', '--verbose', '--client'];
1423
- const ALLOWED_CLIENTS = ['vscode', 'copilot-cli', 'claude-code', 'all'];
1210
+ const ALLOWED_COMMANDS = ['init', 'help', '--help', '-h', 'doctor', 'quickstart', 'close', 'pre-push-guard'];
1211
+ const ALLOWED_FLAGS = ['--force', '--skip-backlog', '--skip-mcp', '--skip-beads', '--verbose', '--reason', '-r', '-f', '--skip-tests', '--skip-backup', '--message', '-m', '--dry-run'];
1424
1212
  const MAX_ARG_LENGTH = 50;
1425
1213
 
1426
1214
  // Validate and sanitize input
1427
1215
  function validateArgs(args) {
1216
+ // The 'close' and 'land' commands handle their own arg validation
1217
+ const command = args[0]?.toLowerCase();
1218
+ if (command === 'close' || command === 'land') return;
1219
+
1428
1220
  for (const arg of args) {
1429
1221
  // Prevent excessively long arguments (log injection, DoS)
1430
1222
  if (arg.length > MAX_ARG_LENGTH) {
@@ -1445,40 +1237,26 @@ validateArgs(args);
1445
1237
 
1446
1238
  const command = args[0]?.toLowerCase();
1447
1239
 
1448
- // Parse --client flag value (e.g. --client vscode)
1449
- let clientArg = null;
1450
- const clientFlagIndex = args.indexOf('--client');
1451
- if (clientFlagIndex !== -1 && clientFlagIndex + 1 < args.length) {
1452
- clientArg = args[clientFlagIndex + 1].toLowerCase();
1453
- if (!ALLOWED_CLIENTS.includes(clientArg)) {
1454
- logError(`Invalid client: ${clientArg.slice(0, MAX_ARG_LENGTH)}`);
1455
- console.log(`Valid clients: ${ALLOWED_CLIENTS.join(', ')}`);
1456
- process.exit(1);
1457
- }
1458
- }
1459
-
1460
1240
  const options = {
1461
1241
  force: args.includes('--force'),
1462
1242
  skipBacklog: args.includes('--skip-backlog'),
1463
1243
  skipMcp: args.includes('--skip-mcp'),
1464
1244
  skipBeads: args.includes('--skip-beads'),
1465
1245
  verbose: args.includes('--verbose'),
1466
- client: clientArg,
1467
1246
  };
1468
1247
 
1469
1248
  // Set global verbose flag for logDebug
1470
1249
  globalThis.VERBOSE = options.verbose;
1471
1250
 
1472
1251
  // Validate unknown flags (exclude --help which is handled as a command)
1473
- // Also exclude the value after --client since it's not a flag
1474
- const clientValueIndex = clientFlagIndex !== -1 ? clientFlagIndex + 1 : -1;
1475
- const unknownFlags = args.filter((arg, i) =>
1476
- arg.startsWith('--') && !ALLOWED_FLAGS.includes(arg) && arg !== '--help' && i !== clientValueIndex
1477
- );
1478
- if (unknownFlags.length > 0) {
1479
- logError(`Unknown flag: ${unknownFlags[0].slice(0, MAX_ARG_LENGTH)}`);
1480
- console.log('Run "npx beth-copilot help" for usage information.');
1481
- process.exit(1);
1252
+ // Skip for 'close' and 'land' commands which handle their own arg parsing
1253
+ if (command !== 'close' && command !== 'land') {
1254
+ const unknownFlags = args.filter(arg => arg.startsWith('--') && !ALLOWED_FLAGS.includes(arg) && arg !== '--help');
1255
+ if (unknownFlags.length > 0) {
1256
+ logError(`Unknown flag: ${unknownFlags[0].slice(0, MAX_ARG_LENGTH)}`);
1257
+ console.log('Run "npx beth-copilot help" for usage information.');
1258
+ process.exit(1);
1259
+ }
1482
1260
  }
1483
1261
 
1484
1262
  switch (command) {
@@ -1505,6 +1283,28 @@ switch (command) {
1505
1283
  await quickstart(options);
1506
1284
  }
1507
1285
  break;
1286
+ case 'close':
1287
+ {
1288
+ const { close } = await loadTsCommand('close');
1289
+ // Pass raw args after 'close' — the command handles its own parsing
1290
+ const closeArgs = process.argv.slice(3);
1291
+ await close(closeArgs);
1292
+ }
1293
+ break;
1294
+ case 'land':
1295
+ {
1296
+ const { land } = await loadTsCommand('land');
1297
+ // Pass raw args after 'land' — the command handles its own parsing
1298
+ const landArgs = process.argv.slice(3);
1299
+ await land(landArgs);
1300
+ }
1301
+ break;
1302
+ case 'pre-push-guard':
1303
+ {
1304
+ const { prePushGuard } = await loadTsCommand('pre-push-guard');
1305
+ await prePushGuard();
1306
+ }
1307
+ break;
1508
1308
  case 'help':
1509
1309
  case '--help':
1510
1310
  case '-h':
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Smoke Test — Vitest Infrastructure Verification
3
+ *
4
+ * Proves the new Vitest test infrastructure works correctly
5
+ * alongside the existing node:test-based tests.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=smoke.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smoke.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/smoke.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}