@specforge/cli 0.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 (380) hide show
  1. package/README.md +781 -0
  2. package/bin/specforge +21 -0
  3. package/dist/channel.d.ts +27 -0
  4. package/dist/channel.d.ts.map +1 -0
  5. package/dist/channel.js +22 -0
  6. package/dist/channel.js.map +1 -0
  7. package/dist/cli/commands/configure.d.ts +16 -0
  8. package/dist/cli/commands/configure.d.ts.map +1 -0
  9. package/dist/cli/commands/configure.js +186 -0
  10. package/dist/cli/commands/configure.js.map +1 -0
  11. package/dist/cli/commands/configure.types.d.ts +110 -0
  12. package/dist/cli/commands/configure.types.d.ts.map +1 -0
  13. package/dist/cli/commands/configure.types.js +82 -0
  14. package/dist/cli/commands/configure.types.js.map +1 -0
  15. package/dist/cli/commands/debug/call.d.ts +14 -0
  16. package/dist/cli/commands/debug/call.d.ts.map +1 -0
  17. package/dist/cli/commands/debug/call.js +96 -0
  18. package/dist/cli/commands/debug/call.js.map +1 -0
  19. package/dist/cli/commands/debug/index.d.ts +12 -0
  20. package/dist/cli/commands/debug/index.d.ts.map +1 -0
  21. package/dist/cli/commands/debug/index.js +14 -0
  22. package/dist/cli/commands/debug/index.js.map +1 -0
  23. package/dist/cli/commands/debug/register.d.ts +11 -0
  24. package/dist/cli/commands/debug/register.d.ts.map +1 -0
  25. package/dist/cli/commands/debug/register.js +78 -0
  26. package/dist/cli/commands/debug/register.js.map +1 -0
  27. package/dist/cli/commands/debug/test.d.ts +13 -0
  28. package/dist/cli/commands/debug/test.d.ts.map +1 -0
  29. package/dist/cli/commands/debug/test.js +91 -0
  30. package/dist/cli/commands/debug/test.js.map +1 -0
  31. package/dist/cli/commands/debug/tools.d.ts +13 -0
  32. package/dist/cli/commands/debug/tools.d.ts.map +1 -0
  33. package/dist/cli/commands/debug/tools.js +86 -0
  34. package/dist/cli/commands/debug/tools.js.map +1 -0
  35. package/dist/cli/commands/debug/types.d.ts +119 -0
  36. package/dist/cli/commands/debug/types.d.ts.map +1 -0
  37. package/dist/cli/commands/debug/types.js +36 -0
  38. package/dist/cli/commands/debug/types.js.map +1 -0
  39. package/dist/cli/commands/debug/whoami.d.ts +13 -0
  40. package/dist/cli/commands/debug/whoami.d.ts.map +1 -0
  41. package/dist/cli/commands/debug/whoami.js +131 -0
  42. package/dist/cli/commands/debug/whoami.js.map +1 -0
  43. package/dist/cli/commands/doctor.d.ts +16 -0
  44. package/dist/cli/commands/doctor.d.ts.map +1 -0
  45. package/dist/cli/commands/doctor.js +413 -0
  46. package/dist/cli/commands/doctor.js.map +1 -0
  47. package/dist/cli/commands/doctor.types.d.ts +180 -0
  48. package/dist/cli/commands/doctor.types.d.ts.map +1 -0
  49. package/dist/cli/commands/doctor.types.js +140 -0
  50. package/dist/cli/commands/doctor.types.js.map +1 -0
  51. package/dist/cli/commands/feedback.d.ts +27 -0
  52. package/dist/cli/commands/feedback.d.ts.map +1 -0
  53. package/dist/cli/commands/feedback.js +262 -0
  54. package/dist/cli/commands/feedback.js.map +1 -0
  55. package/dist/cli/commands/feedback.types.d.ts +116 -0
  56. package/dist/cli/commands/feedback.types.d.ts.map +1 -0
  57. package/dist/cli/commands/feedback.types.js +65 -0
  58. package/dist/cli/commands/feedback.types.js.map +1 -0
  59. package/dist/cli/commands/index.d.ts +15 -0
  60. package/dist/cli/commands/index.d.ts.map +1 -0
  61. package/dist/cli/commands/index.js +21 -0
  62. package/dist/cli/commands/index.js.map +1 -0
  63. package/dist/cli/commands/init.d.ts +17 -0
  64. package/dist/cli/commands/init.d.ts.map +1 -0
  65. package/dist/cli/commands/init.js +773 -0
  66. package/dist/cli/commands/init.js.map +1 -0
  67. package/dist/cli/commands/init.types.d.ts +193 -0
  68. package/dist/cli/commands/init.types.d.ts.map +1 -0
  69. package/dist/cli/commands/init.types.js +29 -0
  70. package/dist/cli/commands/init.types.js.map +1 -0
  71. package/dist/cli/commands/invitations.d.ts +31 -0
  72. package/dist/cli/commands/invitations.d.ts.map +1 -0
  73. package/dist/cli/commands/invitations.js +250 -0
  74. package/dist/cli/commands/invitations.js.map +1 -0
  75. package/dist/cli/commands/login.d.ts +40 -0
  76. package/dist/cli/commands/login.d.ts.map +1 -0
  77. package/dist/cli/commands/login.js +139 -0
  78. package/dist/cli/commands/login.js.map +1 -0
  79. package/dist/cli/commands/members.d.ts +55 -0
  80. package/dist/cli/commands/members.d.ts.map +1 -0
  81. package/dist/cli/commands/members.js +296 -0
  82. package/dist/cli/commands/members.js.map +1 -0
  83. package/dist/cli/commands/scaffold/agent-types.d.ts +54 -0
  84. package/dist/cli/commands/scaffold/agent-types.d.ts.map +1 -0
  85. package/dist/cli/commands/scaffold/agent-types.js +22 -0
  86. package/dist/cli/commands/scaffold/agent-types.js.map +1 -0
  87. package/dist/cli/commands/scaffold/display.d.ts +56 -0
  88. package/dist/cli/commands/scaffold/display.d.ts.map +1 -0
  89. package/dist/cli/commands/scaffold/display.js +217 -0
  90. package/dist/cli/commands/scaffold/display.js.map +1 -0
  91. package/dist/cli/commands/scaffold/files.d.ts +99 -0
  92. package/dist/cli/commands/scaffold/files.d.ts.map +1 -0
  93. package/dist/cli/commands/scaffold/files.js +122 -0
  94. package/dist/cli/commands/scaffold/files.js.map +1 -0
  95. package/dist/cli/commands/scaffold/index.d.ts +13 -0
  96. package/dist/cli/commands/scaffold/index.d.ts.map +1 -0
  97. package/dist/cli/commands/scaffold/index.js +12 -0
  98. package/dist/cli/commands/scaffold/index.js.map +1 -0
  99. package/dist/cli/commands/scaffold/register.d.ts +11 -0
  100. package/dist/cli/commands/scaffold/register.d.ts.map +1 -0
  101. package/dist/cli/commands/scaffold/register.js +11 -0
  102. package/dist/cli/commands/scaffold/register.js.map +1 -0
  103. package/dist/cli/commands/scaffold/scaffold.d.ts +11 -0
  104. package/dist/cli/commands/scaffold/scaffold.d.ts.map +1 -0
  105. package/dist/cli/commands/scaffold/scaffold.js +728 -0
  106. package/dist/cli/commands/scaffold/scaffold.js.map +1 -0
  107. package/dist/cli/commands/scaffold/targets.d.ts +60 -0
  108. package/dist/cli/commands/scaffold/targets.d.ts.map +1 -0
  109. package/dist/cli/commands/scaffold/targets.js +251 -0
  110. package/dist/cli/commands/scaffold/targets.js.map +1 -0
  111. package/dist/cli/commands/scaffold/types.d.ts +170 -0
  112. package/dist/cli/commands/scaffold/types.d.ts.map +1 -0
  113. package/dist/cli/commands/scaffold/types.js +12 -0
  114. package/dist/cli/commands/scaffold/types.js.map +1 -0
  115. package/dist/cli/commands/scaffold/utils.d.ts +89 -0
  116. package/dist/cli/commands/scaffold/utils.d.ts.map +1 -0
  117. package/dist/cli/commands/scaffold/utils.js +401 -0
  118. package/dist/cli/commands/scaffold/utils.js.map +1 -0
  119. package/dist/cli/commands/status.d.ts +19 -0
  120. package/dist/cli/commands/status.d.ts.map +1 -0
  121. package/dist/cli/commands/status.js +124 -0
  122. package/dist/cli/commands/status.js.map +1 -0
  123. package/dist/cli/commands/status.types.d.ts +37 -0
  124. package/dist/cli/commands/status.types.d.ts.map +1 -0
  125. package/dist/cli/commands/status.types.js +7 -0
  126. package/dist/cli/commands/status.types.js.map +1 -0
  127. package/dist/cli/commands/switch.d.ts +18 -0
  128. package/dist/cli/commands/switch.d.ts.map +1 -0
  129. package/dist/cli/commands/switch.js +134 -0
  130. package/dist/cli/commands/switch.js.map +1 -0
  131. package/dist/cli/commands/switch.types.d.ts +123 -0
  132. package/dist/cli/commands/switch.types.d.ts.map +1 -0
  133. package/dist/cli/commands/switch.types.js +46 -0
  134. package/dist/cli/commands/switch.types.js.map +1 -0
  135. package/dist/cli/config/agent-teams.types.d.ts +120 -0
  136. package/dist/cli/config/agent-teams.types.d.ts.map +1 -0
  137. package/dist/cli/config/agent-teams.types.js +23 -0
  138. package/dist/cli/config/agent-teams.types.js.map +1 -0
  139. package/dist/cli/config/index.d.ts +13 -0
  140. package/dist/cli/config/index.d.ts.map +1 -0
  141. package/dist/cli/config/index.js +7 -0
  142. package/dist/cli/config/index.js.map +1 -0
  143. package/dist/cli/config/loader.d.ts +114 -0
  144. package/dist/cli/config/loader.d.ts.map +1 -0
  145. package/dist/cli/config/loader.js +198 -0
  146. package/dist/cli/config/loader.js.map +1 -0
  147. package/dist/cli/config/paths.d.ts +107 -0
  148. package/dist/cli/config/paths.d.ts.map +1 -0
  149. package/dist/cli/config/paths.js +79 -0
  150. package/dist/cli/config/paths.js.map +1 -0
  151. package/dist/cli/config/planning-sessions-registry.d.ts +52 -0
  152. package/dist/cli/config/planning-sessions-registry.d.ts.map +1 -0
  153. package/dist/cli/config/planning-sessions-registry.js +46 -0
  154. package/dist/cli/config/planning-sessions-registry.js.map +1 -0
  155. package/dist/cli/config/types.d.ts +186 -0
  156. package/dist/cli/config/types.d.ts.map +1 -0
  157. package/dist/cli/config/types.js +27 -0
  158. package/dist/cli/config/types.js.map +1 -0
  159. package/dist/cli/config/validation.d.ts +62 -0
  160. package/dist/cli/config/validation.d.ts.map +1 -0
  161. package/dist/cli/config/validation.js +133 -0
  162. package/dist/cli/config/validation.js.map +1 -0
  163. package/dist/cli/config/writer.d.ts +153 -0
  164. package/dist/cli/config/writer.d.ts.map +1 -0
  165. package/dist/cli/config/writer.js +168 -0
  166. package/dist/cli/config/writer.js.map +1 -0
  167. package/dist/cli/index.d.ts +30 -0
  168. package/dist/cli/index.d.ts.map +1 -0
  169. package/dist/cli/index.js +142 -0
  170. package/dist/cli/index.js.map +1 -0
  171. package/dist/cli/middleware/auth-guard.d.ts +107 -0
  172. package/dist/cli/middleware/auth-guard.d.ts.map +1 -0
  173. package/dist/cli/middleware/auth-guard.js +97 -0
  174. package/dist/cli/middleware/auth-guard.js.map +1 -0
  175. package/dist/cli/middleware/error-handler.d.ts +133 -0
  176. package/dist/cli/middleware/error-handler.d.ts.map +1 -0
  177. package/dist/cli/middleware/error-handler.js +139 -0
  178. package/dist/cli/middleware/error-handler.js.map +1 -0
  179. package/dist/cli/middleware/index.d.ts +6 -0
  180. package/dist/cli/middleware/index.d.ts.map +1 -0
  181. package/dist/cli/middleware/index.js +3 -0
  182. package/dist/cli/middleware/index.js.map +1 -0
  183. package/dist/cli/templates/agents/content/core/sfag-orchestrator.d.ts +9 -0
  184. package/dist/cli/templates/agents/content/core/sfag-orchestrator.d.ts.map +1 -0
  185. package/dist/cli/templates/agents/content/core/sfag-orchestrator.js +160 -0
  186. package/dist/cli/templates/agents/content/core/sfag-orchestrator.js.map +1 -0
  187. package/dist/cli/templates/agents/content/core/sfag-spec-creator.d.ts +9 -0
  188. package/dist/cli/templates/agents/content/core/sfag-spec-creator.d.ts.map +1 -0
  189. package/dist/cli/templates/agents/content/core/sfag-spec-creator.js +343 -0
  190. package/dist/cli/templates/agents/content/core/sfag-spec-creator.js.map +1 -0
  191. package/dist/cli/templates/agents/content/core/sfag-ticket-implementer.d.ts +9 -0
  192. package/dist/cli/templates/agents/content/core/sfag-ticket-implementer.d.ts.map +1 -0
  193. package/dist/cli/templates/agents/content/core/sfag-ticket-implementer.js +254 -0
  194. package/dist/cli/templates/agents/content/core/sfag-ticket-implementer.js.map +1 -0
  195. package/dist/cli/templates/agents/content/research/sfag-package-researcher.d.ts +8 -0
  196. package/dist/cli/templates/agents/content/research/sfag-package-researcher.d.ts.map +1 -0
  197. package/dist/cli/templates/agents/content/research/sfag-package-researcher.js +128 -0
  198. package/dist/cli/templates/agents/content/research/sfag-package-researcher.js.map +1 -0
  199. package/dist/cli/templates/agents/index.d.ts +23 -0
  200. package/dist/cli/templates/agents/index.d.ts.map +1 -0
  201. package/dist/cli/templates/agents/index.js +29 -0
  202. package/dist/cli/templates/agents/index.js.map +1 -0
  203. package/dist/cli/templates/commands.d.ts +17 -0
  204. package/dist/cli/templates/commands.d.ts.map +1 -0
  205. package/dist/cli/templates/commands.js +78 -0
  206. package/dist/cli/templates/commands.js.map +1 -0
  207. package/dist/cli/templates/content/sf-blockers.d.ts +7 -0
  208. package/dist/cli/templates/content/sf-blockers.d.ts.map +1 -0
  209. package/dist/cli/templates/content/sf-blockers.js +69 -0
  210. package/dist/cli/templates/content/sf-blockers.js.map +1 -0
  211. package/dist/cli/templates/content/sf-commit.d.ts +7 -0
  212. package/dist/cli/templates/content/sf-commit.d.ts.map +1 -0
  213. package/dist/cli/templates/content/sf-commit.js +79 -0
  214. package/dist/cli/templates/content/sf-commit.js.map +1 -0
  215. package/dist/cli/templates/content/sf-context.d.ts +7 -0
  216. package/dist/cli/templates/content/sf-context.d.ts.map +1 -0
  217. package/dist/cli/templates/content/sf-context.js +63 -0
  218. package/dist/cli/templates/content/sf-context.js.map +1 -0
  219. package/dist/cli/templates/content/sf-help.d.ts +7 -0
  220. package/dist/cli/templates/content/sf-help.d.ts.map +1 -0
  221. package/dist/cli/templates/content/sf-help.js +42 -0
  222. package/dist/cli/templates/content/sf-help.js.map +1 -0
  223. package/dist/cli/templates/content/sf-init.d.ts +7 -0
  224. package/dist/cli/templates/content/sf-init.d.ts.map +1 -0
  225. package/dist/cli/templates/content/sf-init.js +62 -0
  226. package/dist/cli/templates/content/sf-init.js.map +1 -0
  227. package/dist/cli/templates/content/sf-reset.d.ts +7 -0
  228. package/dist/cli/templates/content/sf-reset.d.ts.map +1 -0
  229. package/dist/cli/templates/content/sf-reset.js +67 -0
  230. package/dist/cli/templates/content/sf-reset.js.map +1 -0
  231. package/dist/cli/templates/content/sf-search.d.ts +7 -0
  232. package/dist/cli/templates/content/sf-search.d.ts.map +1 -0
  233. package/dist/cli/templates/content/sf-search.js +63 -0
  234. package/dist/cli/templates/content/sf-search.js.map +1 -0
  235. package/dist/cli/templates/content/sf-status.d.ts +7 -0
  236. package/dist/cli/templates/content/sf-status.d.ts.map +1 -0
  237. package/dist/cli/templates/content/sf-status.js +62 -0
  238. package/dist/cli/templates/content/sf-status.js.map +1 -0
  239. package/dist/cli/templates/index.d.ts +8 -0
  240. package/dist/cli/templates/index.d.ts.map +1 -0
  241. package/dist/cli/templates/index.js +17 -0
  242. package/dist/cli/templates/index.js.map +1 -0
  243. package/dist/cli/ui/banner.d.ts +38 -0
  244. package/dist/cli/ui/banner.d.ts.map +1 -0
  245. package/dist/cli/ui/banner.js +89 -0
  246. package/dist/cli/ui/banner.js.map +1 -0
  247. package/dist/cli/ui/colors.d.ts +76 -0
  248. package/dist/cli/ui/colors.d.ts.map +1 -0
  249. package/dist/cli/ui/colors.js +67 -0
  250. package/dist/cli/ui/colors.js.map +1 -0
  251. package/dist/cli/ui/index.d.ts +7 -0
  252. package/dist/cli/ui/index.d.ts.map +1 -0
  253. package/dist/cli/ui/index.js +4 -0
  254. package/dist/cli/ui/index.js.map +1 -0
  255. package/dist/cli/ui/output.d.ts +117 -0
  256. package/dist/cli/ui/output.d.ts.map +1 -0
  257. package/dist/cli/ui/output.js +83 -0
  258. package/dist/cli/ui/output.js.map +1 -0
  259. package/dist/cli/ui/spinner.d.ts +120 -0
  260. package/dist/cli/ui/spinner.d.ts.map +1 -0
  261. package/dist/cli/ui/spinner.js +158 -0
  262. package/dist/cli/ui/spinner.js.map +1 -0
  263. package/dist/cli/ui/time.d.ts +54 -0
  264. package/dist/cli/ui/time.d.ts.map +1 -0
  265. package/dist/cli/ui/time.js +119 -0
  266. package/dist/cli/ui/time.js.map +1 -0
  267. package/dist/client/api-client.d.ts +123 -0
  268. package/dist/client/api-client.d.ts.map +1 -0
  269. package/dist/client/api-client.js +105 -0
  270. package/dist/client/api-client.js.map +1 -0
  271. package/dist/client/cli-client.d.ts +26 -0
  272. package/dist/client/cli-client.d.ts.map +1 -0
  273. package/dist/client/cli-client.js +20 -0
  274. package/dist/client/cli-client.js.map +1 -0
  275. package/dist/config/index.d.ts +78 -0
  276. package/dist/config/index.d.ts.map +1 -0
  277. package/dist/config/index.js +79 -0
  278. package/dist/config/index.js.map +1 -0
  279. package/dist/index.d.ts +16 -0
  280. package/dist/index.d.ts.map +1 -0
  281. package/dist/index.js +73 -0
  282. package/dist/index.js.map +1 -0
  283. package/dist/lib/format.d.ts +126 -0
  284. package/dist/lib/format.d.ts.map +1 -0
  285. package/dist/lib/format.js +71 -0
  286. package/dist/lib/format.js.map +1 -0
  287. package/dist/lib/index.d.ts +11 -0
  288. package/dist/lib/index.d.ts.map +1 -0
  289. package/dist/lib/index.js +45 -0
  290. package/dist/lib/index.js.map +1 -0
  291. package/dist/lib/monorepo-detector.d.ts +31 -0
  292. package/dist/lib/monorepo-detector.d.ts.map +1 -0
  293. package/dist/lib/monorepo-detector.js +188 -0
  294. package/dist/lib/monorepo-detector.js.map +1 -0
  295. package/dist/lib/prompt-generator.d.ts +65 -0
  296. package/dist/lib/prompt-generator.d.ts.map +1 -0
  297. package/dist/lib/prompt-generator.js +162 -0
  298. package/dist/lib/prompt-generator.js.map +1 -0
  299. package/dist/lib/strategy-analyzer.d.ts +59 -0
  300. package/dist/lib/strategy-analyzer.d.ts.map +1 -0
  301. package/dist/lib/strategy-analyzer.js +91 -0
  302. package/dist/lib/strategy-analyzer.js.map +1 -0
  303. package/dist/lib/workflow-definitions.d.ts +41 -0
  304. package/dist/lib/workflow-definitions.d.ts.map +1 -0
  305. package/dist/lib/workflow-definitions.js +497 -0
  306. package/dist/lib/workflow-definitions.js.map +1 -0
  307. package/dist/patterns/index.d.ts +9 -0
  308. package/dist/patterns/index.d.ts.map +1 -0
  309. package/dist/patterns/index.js +21 -0
  310. package/dist/patterns/index.js.map +1 -0
  311. package/dist/patterns/inheritance.d.ts +193 -0
  312. package/dist/patterns/inheritance.d.ts.map +1 -0
  313. package/dist/patterns/inheritance.js +125 -0
  314. package/dist/patterns/inheritance.js.map +1 -0
  315. package/dist/server.d.ts +44 -0
  316. package/dist/server.d.ts.map +1 -0
  317. package/dist/server.js +91 -0
  318. package/dist/server.js.map +1 -0
  319. package/dist/tools/core/context-helper.d.ts +50 -0
  320. package/dist/tools/core/context-helper.d.ts.map +1 -0
  321. package/dist/tools/core/context-helper.js +49 -0
  322. package/dist/tools/core/context-helper.js.map +1 -0
  323. package/dist/tools/core/index.d.ts +2 -0
  324. package/dist/tools/core/index.d.ts.map +1 -0
  325. package/dist/tools/core/index.js +2 -0
  326. package/dist/tools/core/index.js.map +1 -0
  327. package/dist/tools/index.d.ts +58 -0
  328. package/dist/tools/index.d.ts.map +1 -0
  329. package/dist/tools/index.js +1499 -0
  330. package/dist/tools/index.js.map +1 -0
  331. package/dist/transport/__tests__/resolve-endpoint.test.d.ts +6 -0
  332. package/dist/transport/__tests__/resolve-endpoint.test.d.ts.map +1 -0
  333. package/dist/transport/index.d.ts +6 -0
  334. package/dist/transport/index.d.ts.map +1 -0
  335. package/dist/transport/index.js +5 -0
  336. package/dist/transport/index.js.map +1 -0
  337. package/dist/transport/interface.d.ts +25 -0
  338. package/dist/transport/interface.d.ts.map +1 -0
  339. package/dist/transport/interface.js +1 -0
  340. package/dist/transport/interface.js.map +1 -0
  341. package/dist/transport/remote.d.ts +38 -0
  342. package/dist/transport/remote.d.ts.map +1 -0
  343. package/dist/transport/remote.js +107 -0
  344. package/dist/transport/remote.js.map +1 -0
  345. package/dist/transport/resolve-endpoint.d.ts +58 -0
  346. package/dist/transport/resolve-endpoint.d.ts.map +1 -0
  347. package/dist/transport/resolve-endpoint.js +146 -0
  348. package/dist/transport/resolve-endpoint.js.map +1 -0
  349. package/dist/types/index.d.ts +212 -0
  350. package/dist/types/index.d.ts.map +1 -0
  351. package/dist/types/index.js +16 -0
  352. package/dist/types/index.js.map +1 -0
  353. package/dist/validation/index.d.ts +86 -0
  354. package/dist/validation/index.d.ts.map +1 -0
  355. package/dist/validation/index.js +392 -0
  356. package/dist/validation/index.js.map +1 -0
  357. package/dist/validation/ticket-validation.d.ts +162 -0
  358. package/dist/validation/ticket-validation.d.ts.map +1 -0
  359. package/dist/validation/ticket-validation.js +188 -0
  360. package/dist/validation/ticket-validation.js.map +1 -0
  361. package/package.json +69 -0
  362. package/src/cli/templates/agents/content/core/sfag-orchestrator.ts +165 -0
  363. package/src/cli/templates/agents/content/core/sfag-spec-creator.ts +348 -0
  364. package/src/cli/templates/agents/content/core/sfag-ticket-implementer.ts +259 -0
  365. package/src/cli/templates/agents/content/research/sfag-package-researcher.ts +132 -0
  366. package/src/cli/templates/agents/index.ts +47 -0
  367. package/src/cli/templates/commands.ts +90 -0
  368. package/src/cli/templates/content/sf-blockers.ts +71 -0
  369. package/src/cli/templates/content/sf-commit.ts +81 -0
  370. package/src/cli/templates/content/sf-context.ts +65 -0
  371. package/src/cli/templates/content/sf-help.ts +44 -0
  372. package/src/cli/templates/content/sf-init.ts +64 -0
  373. package/src/cli/templates/content/sf-reset.ts +69 -0
  374. package/src/cli/templates/content/sf-search.ts +65 -0
  375. package/src/cli/templates/content/sf-status.ts +64 -0
  376. package/src/cli/templates/index.ts +16 -0
  377. package/src/cli/templates/skills/specforge-conventions.md +114 -0
  378. package/src/cli/templates/skills/specforge-orchestrator.md +409 -0
  379. package/src/cli/templates/skills/specforge-validator.md +128 -0
  380. package/src/cli/templates/skills/specforge-worker.md +412 -0
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Pattern Inheritance Resolver
3
+ *
4
+ * Resolves the complete pattern inheritance chain for tickets:
5
+ * Specification → Epic → Ticket
6
+ *
7
+ * Later values override earlier ones. Arrays are concatenated.
8
+ *
9
+ * @see MCI-030-05-pattern-inheritance-resolver
10
+ */
11
+ import type { SpecificationCodeStandards, ReturnTypes, NamingConventions, EpicSharedPatterns, EpicCommonFiles } from '../types/index.js';
12
+ /**
13
+ * Fully resolved patterns for a ticket
14
+ *
15
+ * Combines patterns from specification, epic, and ticket levels
16
+ * with proper override semantics.
17
+ */
18
+ export interface ResolvedPatterns {
19
+ /** All imports (spec.commonImports + epic.additionalImports) */
20
+ imports: string[];
21
+ /** Merged patterns (spec → epic → ticket, later wins) */
22
+ patterns: Record<string, string>;
23
+ /** Return types from specification */
24
+ returnTypes: ReturnTypes;
25
+ /** Common files from epic */
26
+ commonFiles: EpicCommonFiles;
27
+ /** Naming conventions from specification */
28
+ naming: NamingConventions;
29
+ /** Source information for debugging */
30
+ sources: {
31
+ specificationId: string;
32
+ epicId: string;
33
+ ticketId: string;
34
+ };
35
+ }
36
+ /**
37
+ * Override information for a single pattern key
38
+ */
39
+ export interface PatternOverride {
40
+ /** Pattern key */
41
+ key: string;
42
+ /** Value from specification (if defined) */
43
+ specValue?: string;
44
+ /** Value from epic (if defined) */
45
+ epicValue?: string;
46
+ /** Value from ticket (if defined) */
47
+ ticketValue?: string;
48
+ /** Which level the final value came from */
49
+ resolvedFrom: 'specification' | 'epic' | 'ticket';
50
+ }
51
+ /**
52
+ * Detailed override report for debugging
53
+ */
54
+ export interface PatternOverrideReport {
55
+ /** Final merged patterns */
56
+ final: Record<string, string>;
57
+ /** Details about each override */
58
+ overrides: PatternOverride[];
59
+ }
60
+ /**
61
+ * Input data for pattern resolution
62
+ */
63
+ export interface PatternResolutionInput {
64
+ /** Ticket ID */
65
+ ticketId: string;
66
+ /** Specification data */
67
+ specification: {
68
+ id: string;
69
+ codeStandards?: SpecificationCodeStandards | null;
70
+ commonImports?: string[] | null;
71
+ returnTypes?: ReturnTypes | null;
72
+ };
73
+ /** Epic data */
74
+ epic: {
75
+ id: string;
76
+ sharedPatterns?: EpicSharedPatterns | null;
77
+ additionalImports?: string[] | null;
78
+ commonFiles?: EpicCommonFiles | null;
79
+ };
80
+ /** Ticket data (optional, for override information) */
81
+ ticket?: {
82
+ id: string;
83
+ technicalDetails?: {
84
+ patterns?: Record<string, string>;
85
+ } | null;
86
+ };
87
+ }
88
+ /**
89
+ * Flatten SpecificationCodeStandards to a flat Record
90
+ *
91
+ * Extracts all pattern-related fields from code standards into a
92
+ * flat key-value structure for easy merging.
93
+ *
94
+ * @param standards - Specification code standards object
95
+ * @returns Flat record of pattern key-value pairs
96
+ */
97
+ export declare function flattenCodeStandards(standards: SpecificationCodeStandards | null | undefined): Record<string, string>;
98
+ /**
99
+ * Flatten EpicSharedPatterns to a flat Record
100
+ *
101
+ * Extracts all pattern fields from epic shared patterns into a
102
+ * flat key-value structure for merging.
103
+ *
104
+ * @param patterns - Epic shared patterns object
105
+ * @returns Flat record of pattern key-value pairs
106
+ */
107
+ export declare function flattenSharedPatterns(patterns: EpicSharedPatterns | null | undefined): Record<string, string>;
108
+ /**
109
+ * Resolve inherited patterns for a ticket
110
+ *
111
+ * Merges patterns from the specification → epic → ticket chain.
112
+ * Later values override earlier ones. Arrays are concatenated.
113
+ *
114
+ * @param input - Pattern resolution input with spec, epic, and ticket data
115
+ * @returns Fully resolved patterns
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * const resolved = resolvePatterns({
120
+ * ticketId: 'ticket-123',
121
+ * specification: {
122
+ * id: 'spec-1',
123
+ * codeStandards: { errorHandling: 'Result<T>' },
124
+ * commonImports: ['import { z } from "zod"']
125
+ * },
126
+ * epic: {
127
+ * id: 'epic-1',
128
+ * sharedPatterns: { errorHandling: 'AppError' },
129
+ * additionalImports: ['import { api } from "@/lib/api"']
130
+ * }
131
+ * });
132
+ *
133
+ * // resolved.patterns.errorHandling === 'AppError' (epic overrides spec)
134
+ * // resolved.imports contains both spec and epic imports
135
+ * ```
136
+ */
137
+ export declare function resolvePatterns(input: PatternResolutionInput): ResolvedPatterns;
138
+ /**
139
+ * Get detailed override information for debugging
140
+ *
141
+ * Shows where each pattern value came from in the inheritance chain.
142
+ * Useful for debugging and understanding pattern resolution.
143
+ *
144
+ * @param input - Pattern resolution input
145
+ * @returns Override report with final values and source information
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * const report = getPatternOverrides(input);
150
+ *
151
+ * for (const override of report.overrides) {
152
+ * if (override.resolvedFrom === 'epic') {
153
+ * console.log(`${override.key}: Epic overrides spec`);
154
+ * }
155
+ * }
156
+ * ```
157
+ */
158
+ export declare function getPatternOverrides(input: PatternResolutionInput): PatternOverrideReport;
159
+ /**
160
+ * Resolve patterns with caching for performance
161
+ *
162
+ * Uses an in-memory cache to avoid repeated resolution for the same ticket.
163
+ * Cache entries expire after TTL (default 1 minute).
164
+ *
165
+ * @param input - Pattern resolution input
166
+ * @param ttl - Cache TTL in milliseconds (default: 60000)
167
+ * @returns Resolved patterns (may be cached)
168
+ */
169
+ export declare function resolvePatternsWithCache(input: PatternResolutionInput, ttl?: number): ResolvedPatterns;
170
+ /**
171
+ * Clear cache for a specific ticket
172
+ *
173
+ * Call this after updating a ticket's patterns.
174
+ *
175
+ * @param ticketId - Ticket ID to invalidate
176
+ */
177
+ export declare function invalidatePatternCache(ticketId: string): void;
178
+ /**
179
+ * Clear all pattern caches
180
+ *
181
+ * Call this after updating specification or epic patterns,
182
+ * as these changes affect multiple tickets.
183
+ */
184
+ export declare function invalidateAllPatternCaches(): void;
185
+ /**
186
+ * Get current cache size
187
+ *
188
+ * Useful for monitoring and debugging.
189
+ *
190
+ * @returns Number of cached entries
191
+ */
192
+ export declare function getPatternCacheSize(): number;
193
+ //# sourceMappingURL=inheritance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inheritance.d.ts","sourceRoot":"","sources":["../../src/patterns/inheritance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,125 @@
1
+ function flattenCodeStandards(standards) {
2
+ if (!standards) return {};
3
+ const result = {};
4
+ if (standards.language) result.language = standards.language;
5
+ if (standards.asyncPattern) result.asyncPattern = standards.asyncPattern;
6
+ if (standards.errorHandling) result.errorHandling = standards.errorHandling;
7
+ if (standards.documentation) result.documentation = standards.documentation;
8
+ if (standards.testing) result.testing = standards.testing;
9
+ if (standards.stateManagement) result.stateManagement = standards.stateManagement;
10
+ if (standards.apiPattern) result.apiPattern = standards.apiPattern;
11
+ if (standards.logging) result.logging = standards.logging;
12
+ if (standards.validation) result.validation = standards.validation;
13
+ if (standards.custom) {
14
+ Object.assign(result, standards.custom);
15
+ }
16
+ return result;
17
+ }
18
+ function flattenSharedPatterns(patterns) {
19
+ if (!patterns) return {};
20
+ const result = {};
21
+ if (patterns.errorHandling) result.errorHandling = patterns.errorHandling;
22
+ if (patterns.returnType) result.returnType = patterns.returnType;
23
+ if (patterns.actionPrefix) result.actionPrefix = patterns.actionPrefix;
24
+ if (patterns.stateSlice) result.stateSlice = patterns.stateSlice;
25
+ if (patterns.apiBasePath) result.apiBasePath = patterns.apiBasePath;
26
+ if (patterns.componentFolder) result.componentFolder = patterns.componentFolder;
27
+ if (patterns.hookPattern) result.hookPattern = patterns.hookPattern;
28
+ if (patterns.custom) {
29
+ Object.assign(result, patterns.custom);
30
+ }
31
+ return result;
32
+ }
33
+ function resolvePatterns(input) {
34
+ const { ticketId, specification, epic, ticket } = input;
35
+ const specImports = specification.commonImports ?? [];
36
+ const epicImports = epic.additionalImports ?? [];
37
+ const imports = [.../* @__PURE__ */ new Set([...specImports, ...epicImports])];
38
+ const specPatterns = flattenCodeStandards(specification.codeStandards);
39
+ const epicPatterns = flattenSharedPatterns(epic.sharedPatterns);
40
+ const ticketPatterns = ticket?.technicalDetails?.patterns ?? {};
41
+ const patterns = {
42
+ ...specPatterns,
43
+ ...epicPatterns,
44
+ ...ticketPatterns
45
+ };
46
+ return {
47
+ imports,
48
+ patterns,
49
+ returnTypes: specification.returnTypes ?? {},
50
+ commonFiles: epic.commonFiles ?? {},
51
+ naming: specification.codeStandards?.naming ?? {},
52
+ sources: {
53
+ specificationId: specification.id,
54
+ epicId: epic.id,
55
+ ticketId: ticket?.id ?? ticketId
56
+ }
57
+ };
58
+ }
59
+ function getPatternOverrides(input) {
60
+ const { specification, epic, ticket } = input;
61
+ const specPatterns = flattenCodeStandards(specification.codeStandards);
62
+ const epicPatterns = flattenSharedPatterns(epic.sharedPatterns);
63
+ const ticketPatterns = ticket?.technicalDetails?.patterns ?? {};
64
+ const allKeys = /* @__PURE__ */ new Set([
65
+ ...Object.keys(specPatterns),
66
+ ...Object.keys(epicPatterns),
67
+ ...Object.keys(ticketPatterns)
68
+ ]);
69
+ const overrides = Array.from(allKeys).map((key) => {
70
+ const specValue = specPatterns[key];
71
+ const epicValue = epicPatterns[key];
72
+ const ticketValue = ticketPatterns[key];
73
+ let resolvedFrom;
74
+ if (ticketValue !== void 0) {
75
+ resolvedFrom = "ticket";
76
+ } else if (epicValue !== void 0) {
77
+ resolvedFrom = "epic";
78
+ } else {
79
+ resolvedFrom = "specification";
80
+ }
81
+ return { key, specValue, epicValue, ticketValue, resolvedFrom };
82
+ });
83
+ overrides.sort((a, b) => a.key.localeCompare(b.key));
84
+ const final = {
85
+ ...specPatterns,
86
+ ...epicPatterns,
87
+ ...ticketPatterns
88
+ };
89
+ return { final, overrides };
90
+ }
91
+ const patternCache = /* @__PURE__ */ new Map();
92
+ const DEFAULT_CACHE_TTL = 6e4;
93
+ function resolvePatternsWithCache(input, ttl = DEFAULT_CACHE_TTL) {
94
+ const cacheKey = input.ticketId;
95
+ const cached = patternCache.get(cacheKey);
96
+ if (cached && cached.expiry > Date.now()) {
97
+ return cached.patterns;
98
+ }
99
+ const patterns = resolvePatterns(input);
100
+ patternCache.set(cacheKey, {
101
+ patterns,
102
+ expiry: Date.now() + ttl
103
+ });
104
+ return patterns;
105
+ }
106
+ function invalidatePatternCache(ticketId) {
107
+ patternCache.delete(ticketId);
108
+ }
109
+ function invalidateAllPatternCaches() {
110
+ patternCache.clear();
111
+ }
112
+ function getPatternCacheSize() {
113
+ return patternCache.size;
114
+ }
115
+ export {
116
+ flattenCodeStandards,
117
+ flattenSharedPatterns,
118
+ getPatternCacheSize,
119
+ getPatternOverrides,
120
+ invalidateAllPatternCaches,
121
+ invalidatePatternCache,
122
+ resolvePatterns,
123
+ resolvePatternsWithCache
124
+ };
125
+ //# sourceMappingURL=inheritance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/patterns/inheritance.ts"],"sourcesContent":["/**\n * Pattern Inheritance Resolver\n *\n * Resolves the complete pattern inheritance chain for tickets:\n * Specification → Epic → Ticket\n *\n * Later values override earlier ones. Arrays are concatenated.\n *\n * @see MCI-030-05-pattern-inheritance-resolver\n */\n\nimport type {\n SpecificationCodeStandards,\n ReturnTypes,\n NamingConventions,\n EpicSharedPatterns,\n EpicCommonFiles,\n} from '../types/index.js';\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Fully resolved patterns for a ticket\n *\n * Combines patterns from specification, epic, and ticket levels\n * with proper override semantics.\n */\nexport interface ResolvedPatterns {\n /** All imports (spec.commonImports + epic.additionalImports) */\n imports: string[];\n\n /** Merged patterns (spec → epic → ticket, later wins) */\n patterns: Record<string, string>;\n\n /** Return types from specification */\n returnTypes: ReturnTypes;\n\n /** Common files from epic */\n commonFiles: EpicCommonFiles;\n\n /** Naming conventions from specification */\n naming: NamingConventions;\n\n /** Source information for debugging */\n sources: {\n specificationId: string;\n epicId: string;\n ticketId: string;\n };\n}\n\n/**\n * Override information for a single pattern key\n */\nexport interface PatternOverride {\n /** Pattern key */\n key: string;\n /** Value from specification (if defined) */\n specValue?: string;\n /** Value from epic (if defined) */\n epicValue?: string;\n /** Value from ticket (if defined) */\n ticketValue?: string;\n /** Which level the final value came from */\n resolvedFrom: 'specification' | 'epic' | 'ticket';\n}\n\n/**\n * Detailed override report for debugging\n */\nexport interface PatternOverrideReport {\n /** Final merged patterns */\n final: Record<string, string>;\n /** Details about each override */\n overrides: PatternOverride[];\n}\n\n/**\n * Input data for pattern resolution\n */\nexport interface PatternResolutionInput {\n /** Ticket ID */\n ticketId: string;\n /** Specification data */\n specification: {\n id: string;\n codeStandards?: SpecificationCodeStandards | null;\n commonImports?: string[] | null;\n returnTypes?: ReturnTypes | null;\n };\n /** Epic data */\n epic: {\n id: string;\n sharedPatterns?: EpicSharedPatterns | null;\n additionalImports?: string[] | null;\n commonFiles?: EpicCommonFiles | null;\n };\n /** Ticket data (optional, for override information) */\n ticket?: {\n id: string;\n technicalDetails?: {\n patterns?: Record<string, string>;\n } | null;\n };\n}\n\n// =============================================================================\n// Pattern Flattening Helpers\n// =============================================================================\n\n/**\n * Flatten SpecificationCodeStandards to a flat Record\n *\n * Extracts all pattern-related fields from code standards into a\n * flat key-value structure for easy merging.\n *\n * @param standards - Specification code standards object\n * @returns Flat record of pattern key-value pairs\n */\nexport function flattenCodeStandards(\n standards: SpecificationCodeStandards | null | undefined\n): Record<string, string> {\n if (!standards) return {};\n\n const result: Record<string, string> = {};\n\n // Extract all standard fields\n if (standards.language) result.language = standards.language;\n if (standards.asyncPattern) result.asyncPattern = standards.asyncPattern;\n if (standards.errorHandling) result.errorHandling = standards.errorHandling;\n if (standards.documentation) result.documentation = standards.documentation;\n if (standards.testing) result.testing = standards.testing;\n if (standards.stateManagement) result.stateManagement = standards.stateManagement;\n if (standards.apiPattern) result.apiPattern = standards.apiPattern;\n if (standards.logging) result.logging = standards.logging;\n if (standards.validation) result.validation = standards.validation;\n\n // Include custom standards\n if (standards.custom) {\n Object.assign(result, standards.custom);\n }\n\n return result;\n}\n\n/**\n * Flatten EpicSharedPatterns to a flat Record\n *\n * Extracts all pattern fields from epic shared patterns into a\n * flat key-value structure for merging.\n *\n * @param patterns - Epic shared patterns object\n * @returns Flat record of pattern key-value pairs\n */\nexport function flattenSharedPatterns(\n patterns: EpicSharedPatterns | null | undefined\n): Record<string, string> {\n if (!patterns) return {};\n\n const result: Record<string, string> = {};\n\n // Extract all standard fields\n if (patterns.errorHandling) result.errorHandling = patterns.errorHandling;\n if (patterns.returnType) result.returnType = patterns.returnType;\n if (patterns.actionPrefix) result.actionPrefix = patterns.actionPrefix;\n if (patterns.stateSlice) result.stateSlice = patterns.stateSlice;\n if (patterns.apiBasePath) result.apiBasePath = patterns.apiBasePath;\n if (patterns.componentFolder) result.componentFolder = patterns.componentFolder;\n if (patterns.hookPattern) result.hookPattern = patterns.hookPattern;\n\n // Include custom patterns\n if (patterns.custom) {\n Object.assign(result, patterns.custom);\n }\n\n return result;\n}\n\n// =============================================================================\n// Main Resolution Function\n// =============================================================================\n\n/**\n * Resolve inherited patterns for a ticket\n *\n * Merges patterns from the specification → epic → ticket chain.\n * Later values override earlier ones. Arrays are concatenated.\n *\n * @param input - Pattern resolution input with spec, epic, and ticket data\n * @returns Fully resolved patterns\n *\n * @example\n * ```typescript\n * const resolved = resolvePatterns({\n * ticketId: 'ticket-123',\n * specification: {\n * id: 'spec-1',\n * codeStandards: { errorHandling: 'Result<T>' },\n * commonImports: ['import { z } from \"zod\"']\n * },\n * epic: {\n * id: 'epic-1',\n * sharedPatterns: { errorHandling: 'AppError' },\n * additionalImports: ['import { api } from \"@/lib/api\"']\n * }\n * });\n *\n * // resolved.patterns.errorHandling === 'AppError' (epic overrides spec)\n * // resolved.imports contains both spec and epic imports\n * ```\n */\nexport function resolvePatterns(input: PatternResolutionInput): ResolvedPatterns {\n const { ticketId, specification, epic, ticket } = input;\n\n // Concatenate imports (spec + epic, deduplicated)\n const specImports = specification.commonImports ?? [];\n const epicImports = epic.additionalImports ?? [];\n const imports = [...new Set([...specImports, ...epicImports])];\n\n // Flatten patterns from each level\n const specPatterns = flattenCodeStandards(specification.codeStandards);\n const epicPatterns = flattenSharedPatterns(epic.sharedPatterns);\n const ticketPatterns = ticket?.technicalDetails?.patterns ?? {};\n\n // Merge patterns (later overrides earlier)\n const patterns = {\n ...specPatterns,\n ...epicPatterns,\n ...ticketPatterns,\n };\n\n return {\n imports,\n patterns,\n returnTypes: specification.returnTypes ?? {},\n commonFiles: epic.commonFiles ?? {},\n naming: specification.codeStandards?.naming ?? {},\n sources: {\n specificationId: specification.id,\n epicId: epic.id,\n ticketId: ticket?.id ?? ticketId,\n },\n };\n}\n\n// =============================================================================\n// Override Tracking\n// =============================================================================\n\n/**\n * Get detailed override information for debugging\n *\n * Shows where each pattern value came from in the inheritance chain.\n * Useful for debugging and understanding pattern resolution.\n *\n * @param input - Pattern resolution input\n * @returns Override report with final values and source information\n *\n * @example\n * ```typescript\n * const report = getPatternOverrides(input);\n *\n * for (const override of report.overrides) {\n * if (override.resolvedFrom === 'epic') {\n * console.log(`${override.key}: Epic overrides spec`);\n * }\n * }\n * ```\n */\nexport function getPatternOverrides(input: PatternResolutionInput): PatternOverrideReport {\n const { specification, epic, ticket } = input;\n\n const specPatterns = flattenCodeStandards(specification.codeStandards);\n const epicPatterns = flattenSharedPatterns(epic.sharedPatterns);\n const ticketPatterns = ticket?.technicalDetails?.patterns ?? {};\n\n // Get all unique keys\n const allKeys = new Set([\n ...Object.keys(specPatterns),\n ...Object.keys(epicPatterns),\n ...Object.keys(ticketPatterns),\n ]);\n\n // Build override information for each key\n const overrides: PatternOverride[] = Array.from(allKeys).map((key) => {\n const specValue = specPatterns[key];\n const epicValue = epicPatterns[key];\n const ticketValue = ticketPatterns[key];\n\n // Determine which level the value came from\n let resolvedFrom: 'specification' | 'epic' | 'ticket';\n if (ticketValue !== undefined) {\n resolvedFrom = 'ticket';\n } else if (epicValue !== undefined) {\n resolvedFrom = 'epic';\n } else {\n resolvedFrom = 'specification';\n }\n\n return { key, specValue, epicValue, ticketValue, resolvedFrom };\n });\n\n // Sort by key for consistent output\n overrides.sort((a, b) => a.key.localeCompare(b.key));\n\n // Build final merged patterns\n const final = {\n ...specPatterns,\n ...epicPatterns,\n ...ticketPatterns,\n };\n\n return { final, overrides };\n}\n\n// =============================================================================\n// Caching\n// =============================================================================\n\n/** Cache entry with expiry */\ninterface CacheEntry {\n patterns: ResolvedPatterns;\n expiry: number;\n}\n\n/** Pattern resolution cache */\nconst patternCache = new Map<string, CacheEntry>();\n\n/** Default cache TTL (1 minute) */\nconst DEFAULT_CACHE_TTL = 60000;\n\n/**\n * Resolve patterns with caching for performance\n *\n * Uses an in-memory cache to avoid repeated resolution for the same ticket.\n * Cache entries expire after TTL (default 1 minute).\n *\n * @param input - Pattern resolution input\n * @param ttl - Cache TTL in milliseconds (default: 60000)\n * @returns Resolved patterns (may be cached)\n */\nexport function resolvePatternsWithCache(\n input: PatternResolutionInput,\n ttl: number = DEFAULT_CACHE_TTL\n): ResolvedPatterns {\n const cacheKey = input.ticketId;\n const cached = patternCache.get(cacheKey);\n\n if (cached && cached.expiry > Date.now()) {\n return cached.patterns;\n }\n\n const patterns = resolvePatterns(input);\n\n patternCache.set(cacheKey, {\n patterns,\n expiry: Date.now() + ttl,\n });\n\n return patterns;\n}\n\n/**\n * Clear cache for a specific ticket\n *\n * Call this after updating a ticket's patterns.\n *\n * @param ticketId - Ticket ID to invalidate\n */\nexport function invalidatePatternCache(ticketId: string): void {\n patternCache.delete(ticketId);\n}\n\n/**\n * Clear all pattern caches\n *\n * Call this after updating specification or epic patterns,\n * as these changes affect multiple tickets.\n */\nexport function invalidateAllPatternCaches(): void {\n patternCache.clear();\n}\n\n/**\n * Get current cache size\n *\n * Useful for monitoring and debugging.\n *\n * @returns Number of cached entries\n */\nexport function getPatternCacheSize(): number {\n return patternCache.size;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * SpecForge MCP Server
3
+ *
4
+ * MCP (Model Context Protocol) server implementation using stdio transport.
5
+ * Provides tools for AI agents to interact with SpecForge projects.
6
+ *
7
+ * M9: the boot-time `set_working_context` mechanism was removed — that backend
8
+ * op no longer exists. Project/spec/session identity is injected per-call from
9
+ * `.specforge/config.json` by the tool handlers (M9.6b), and the agent reads
10
+ * the M8 envelope (interpreted in `handleToolCall`), TOON-encoded on the wire.
11
+ */
12
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
13
+ import { ApiClient } from './client/api-client.js';
14
+ import { McpConfig } from './config/index.js';
15
+ import type { OutputFormat } from './cli/config/types.js';
16
+ /**
17
+ * Dispatch a tool call and frame the result for the MCP wire.
18
+ *
19
+ * The wire encoding follows the resolved `mcpOutputFormat` (M9.6c) — TOON by
20
+ * default, JSON when the project/global/env config selects it — on both the
21
+ * success and error paths. Exposed for direct testing without spinning up the
22
+ * full MCP transport.
23
+ */
24
+ export declare function dispatchToolCall(apiClient: ApiClient, toolName: string, args: Record<string, unknown>, debug: boolean, format?: OutputFormat): Promise<{
25
+ content: Array<{
26
+ type: 'text';
27
+ text: string;
28
+ }>;
29
+ isError?: boolean;
30
+ }>;
31
+ /**
32
+ * Create and configure the MCP server
33
+ *
34
+ * @param config - Configuration for the server
35
+ * @returns Configured MCP Server instance
36
+ */
37
+ export declare function createServer(config: McpConfig): Promise<Server>;
38
+ /**
39
+ * Start the MCP server with stdio transport
40
+ *
41
+ * @param server - The MCP server instance
42
+ */
43
+ export declare function startServer(server: Server): Promise<void>;
44
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAMnE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAG9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAY1D;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,OAAO,EACd,MAAM,GAAE,YAAqB,GAC5B,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAgBhF;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CA8CrE;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0B/D"}
package/dist/server.js ADDED
@@ -0,0 +1,91 @@
1
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import {
4
+ CallToolRequestSchema,
5
+ ListToolsRequestSchema
6
+ } from "@modelcontextprotocol/sdk/types.js";
7
+ import { ApiClient } from "./client/api-client.js";
8
+ import { getTools, handleToolCall } from "./tools/index.js";
9
+ import { formatToon } from "./lib/format.js";
10
+ function encodeMcp(value, format) {
11
+ return format === "json" ? JSON.stringify(value, null, 2) : formatToon(value);
12
+ }
13
+ const VERSION = "1.0.0";
14
+ async function dispatchToolCall(apiClient, toolName, args, debug, format = "toon") {
15
+ try {
16
+ const result = await handleToolCall(apiClient, toolName, args, debug);
17
+ return {
18
+ content: [{ type: "text", text: encodeMcp(result, format) }]
19
+ };
20
+ } catch (error) {
21
+ const message = error instanceof Error ? error.message : String(error);
22
+ if (debug) {
23
+ console.error(`[DEBUG] Tool ${toolName} failed:`, message);
24
+ }
25
+ return {
26
+ content: [{ type: "text", text: encodeMcp({ error: message }, format) }],
27
+ isError: true
28
+ };
29
+ }
30
+ }
31
+ async function createServer(config) {
32
+ const apiClient = new ApiClient(config);
33
+ const server = new Server(
34
+ {
35
+ name: "specforge",
36
+ version: VERSION
37
+ },
38
+ {
39
+ capabilities: {
40
+ tools: {}
41
+ }
42
+ }
43
+ );
44
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
45
+ if (config.debug) {
46
+ console.error("[DEBUG] ListTools request received");
47
+ }
48
+ const tools = getTools();
49
+ if (config.debug) {
50
+ console.error(`[DEBUG] Returning ${tools.length} tools`);
51
+ }
52
+ return { tools };
53
+ });
54
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
55
+ const { name, arguments: args } = request.params;
56
+ const argsRecord = args || {};
57
+ if (config.debug) {
58
+ console.error("[DEBUG] CallTool request:", {
59
+ name,
60
+ args: JSON.stringify(args)
61
+ });
62
+ }
63
+ return dispatchToolCall(apiClient, name, argsRecord, config.debug, config.mcpOutputFormat ?? "toon");
64
+ });
65
+ return server;
66
+ }
67
+ async function startServer(server) {
68
+ const transport = new StdioServerTransport();
69
+ const shutdown = async () => {
70
+ console.error("[INFO] Shutting down MCP server...");
71
+ await server.close();
72
+ process.exit(0);
73
+ };
74
+ process.on("SIGINT", shutdown);
75
+ process.on("SIGTERM", shutdown);
76
+ process.on("uncaughtException", (error) => {
77
+ console.error("[ERROR] Uncaught exception:", error);
78
+ process.exit(1);
79
+ });
80
+ process.on("unhandledRejection", (reason) => {
81
+ console.error("[ERROR] Unhandled rejection:", reason);
82
+ process.exit(1);
83
+ });
84
+ await server.connect(transport);
85
+ }
86
+ export {
87
+ createServer,
88
+ dispatchToolCall,
89
+ startServer
90
+ };
91
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server.ts"],"sourcesContent":["/**\n * SpecForge MCP Server\n *\n * MCP (Model Context Protocol) server implementation using stdio transport.\n * Provides tools for AI agents to interact with SpecForge projects.\n *\n * M9: the boot-time `set_working_context` mechanism was removed — that backend\n * op no longer exists. Project/spec/session identity is injected per-call from\n * `.specforge/config.json` by the tool handlers (M9.6b), and the agent reads\n * the M8 envelope (interpreted in `handleToolCall`), TOON-encoded on the wire.\n */\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { ApiClient } from './client/api-client.js';\nimport { McpConfig } from './config/index.js';\nimport { getTools, handleToolCall } from './tools/index.js';\nimport { formatToon } from './lib/format.js';\nimport type { OutputFormat } from './cli/config/types.js';\n\n/** Encode an MCP result for the wire per the resolved `mcpOutputFormat`. */\nfunction encodeMcp(value: unknown, format: OutputFormat): string {\n return format === 'json' ? JSON.stringify(value, null, 2) : formatToon(value);\n}\n\n/**\n * Package version - should match package.json\n */\nconst VERSION = '1.0.0';\n\n/**\n * Dispatch a tool call and frame the result for the MCP wire.\n *\n * The wire encoding follows the resolved `mcpOutputFormat` (M9.6c) — TOON by\n * default, JSON when the project/global/env config selects it — on both the\n * success and error paths. Exposed for direct testing without spinning up the\n * full MCP transport.\n */\nexport async function dispatchToolCall(\n apiClient: ApiClient,\n toolName: string,\n args: Record<string, unknown>,\n debug: boolean,\n format: OutputFormat = 'toon'\n): Promise<{ content: Array<{ type: 'text'; text: string }>; isError?: boolean }> {\n try {\n const result = await handleToolCall(apiClient, toolName, args, debug);\n return {\n content: [{ type: 'text', text: encodeMcp(result, format) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (debug) {\n console.error(`[DEBUG] Tool ${toolName} failed:`, message);\n }\n return {\n content: [{ type: 'text', text: encodeMcp({ error: message }, format) }],\n isError: true,\n };\n }\n}\n\n/**\n * Create and configure the MCP server\n *\n * @param config - Configuration for the server\n * @returns Configured MCP Server instance\n */\nexport async function createServer(config: McpConfig): Promise<Server> {\n const apiClient = new ApiClient(config);\n\n const server = new Server(\n {\n name: 'specforge',\n version: VERSION,\n },\n {\n capabilities: {\n tools: {},\n },\n }\n );\n\n // Handle ListTools requests - return available tools\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n if (config.debug) {\n console.error('[DEBUG] ListTools request received');\n }\n\n const tools = getTools();\n\n if (config.debug) {\n console.error(`[DEBUG] Returning ${tools.length} tools`);\n }\n\n return { tools };\n });\n\n // Handle CallTool requests - execute the requested tool\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n const argsRecord = (args || {}) as Record<string, unknown>;\n\n if (config.debug) {\n console.error('[DEBUG] CallTool request:', {\n name,\n args: JSON.stringify(args),\n });\n }\n\n return dispatchToolCall(apiClient, name, argsRecord, config.debug, config.mcpOutputFormat ?? 'toon');\n });\n\n return server;\n}\n\n/**\n * Start the MCP server with stdio transport\n *\n * @param server - The MCP server instance\n */\nexport async function startServer(server: Server): Promise<void> {\n const transport = new StdioServerTransport();\n\n // Handle graceful shutdown\n const shutdown = async () => {\n console.error('[INFO] Shutting down MCP server...');\n await server.close();\n process.exit(0);\n };\n\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n\n // Handle uncaught errors\n process.on('uncaughtException', (error) => {\n console.error('[ERROR] Uncaught exception:', error);\n process.exit(1);\n });\n\n process.on('unhandledRejection', (reason) => {\n console.error('[ERROR] Unhandled rejection:', reason);\n process.exit(1);\n });\n\n // Connect to transport\n await server.connect(transport);\n}\n"],"mappings":"AAYA,SAAS,cAAc;AACvB,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,iBAAiB;AAE1B,SAAS,UAAU,sBAAsB;AACzC,SAAS,kBAAkB;AAI3B,SAAS,UAAU,OAAgB,QAA8B;AAC/D,SAAO,WAAW,SAAS,KAAK,UAAU,OAAO,MAAM,CAAC,IAAI,WAAW,KAAK;AAC9E;AAKA,MAAM,UAAU;AAUhB,eAAsB,iBACpB,WACA,UACA,MACA,OACA,SAAuB,QACyD;AAChF,MAAI;AACF,UAAM,SAAS,MAAM,eAAe,WAAW,UAAU,MAAM,KAAK;AACpE,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,UAAU,QAAQ,MAAM,EAAE,CAAC;AAAA,IAC7D;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,QAAI,OAAO;AACT,cAAQ,MAAM,gBAAgB,QAAQ,YAAY,OAAO;AAAA,IAC3D;AACA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,EAAE,CAAC;AAAA,MACvE,SAAS;AAAA,IACX;AAAA,EACF;AACF;AAQA,eAAsB,aAAa,QAAoC;AACrE,QAAM,YAAY,IAAI,UAAU,MAAM;AAEtC,QAAM,SAAS,IAAI;AAAA,IACjB;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,cAAc;AAAA,QACZ,OAAO,CAAC;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAGA,SAAO,kBAAkB,wBAAwB,YAAY;AAC3D,QAAI,OAAO,OAAO;AAChB,cAAQ,MAAM,oCAAoC;AAAA,IACpD;AAEA,UAAM,QAAQ,SAAS;AAEvB,QAAI,OAAO,OAAO;AAChB,cAAQ,MAAM,qBAAqB,MAAM,MAAM,QAAQ;AAAA,IACzD;AAEA,WAAO,EAAE,MAAM;AAAA,EACjB,CAAC;AAGD,SAAO,kBAAkB,uBAAuB,OAAO,YAAY;AACjE,UAAM,EAAE,MAAM,WAAW,KAAK,IAAI,QAAQ;AAC1C,UAAM,aAAc,QAAQ,CAAC;AAE7B,QAAI,OAAO,OAAO;AAChB,cAAQ,MAAM,6BAA6B;AAAA,QACzC;AAAA,QACA,MAAM,KAAK,UAAU,IAAI;AAAA,MAC3B,CAAC;AAAA,IACH;AAEA,WAAO,iBAAiB,WAAW,MAAM,YAAY,OAAO,OAAO,OAAO,mBAAmB,MAAM;AAAA,EACrG,CAAC;AAED,SAAO;AACT;AAOA,eAAsB,YAAY,QAA+B;AAC/D,QAAM,YAAY,IAAI,qBAAqB;AAG3C,QAAM,WAAW,YAAY;AAC3B,YAAQ,MAAM,oCAAoC;AAClD,UAAM,OAAO,MAAM;AACnB,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,GAAG,UAAU,QAAQ;AAC7B,UAAQ,GAAG,WAAW,QAAQ;AAG9B,UAAQ,GAAG,qBAAqB,CAAC,UAAU;AACzC,YAAQ,MAAM,+BAA+B,KAAK;AAClD,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAED,UAAQ,GAAG,sBAAsB,CAAC,WAAW;AAC3C,YAAQ,MAAM,gCAAgC,MAAM;AACpD,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAGD,QAAM,OAAO,QAAQ,SAAS;AAChC;","names":[]}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Context Helper
3
+ *
4
+ * Provides utilities for injecting working context from .specforge/config.json
5
+ * into tool arguments. This ensures tools scope to the correct project/specification
6
+ * when not explicitly provided.
7
+ */
8
+ import type { ResolvedAgentTeamsConfig } from '../../cli/config/loader.js';
9
+ import type { ActiveSpecification } from '../../cli/config/agent-teams.types.js';
10
+ type ContextField = 'projectId' | 'specificationId';
11
+ /**
12
+ * Inject missing context fields from .specforge/config.json.
13
+ * Explicit args always take precedence over config values.
14
+ *
15
+ * @param args - Tool arguments that may be missing context fields
16
+ * @param fields - Context fields to inject if missing
17
+ * @returns Args with context fields injected from config
18
+ */
19
+ export declare function injectContext<T extends Record<string, unknown>>(args: T, fields: ContextField[]): T;
20
+ /**
21
+ * Inject context and validate required fields are present.
22
+ * Throws error if required fields cannot be resolved from config.
23
+ *
24
+ * @param args - Tool arguments that may be missing context fields
25
+ * @param requiredFields - Fields that MUST be present after injection
26
+ * @param optionalFields - Fields to inject if available but not require
27
+ * @returns Args with context fields injected
28
+ * @throws Error if required fields cannot be resolved
29
+ */
30
+ export declare function injectContextRequired<T extends Record<string, unknown>>(args: T, requiredFields: ContextField[], optionalFields?: ContextField[]): T;
31
+ /**
32
+ * Get the resolved Agent Teams config from .specforge/config.json.
33
+ *
34
+ * Claude Code Agent Teams only. Not used by MCP tool handlers.
35
+ *
36
+ * Always returns a fully-resolved config with defaults applied (never null).
37
+ * Used by CLI commands like `plan` and `status --teams` to read the user's
38
+ * preferred strategy, team limits, and other settings.
39
+ */
40
+ export declare function getAgentTeamsContext(): ResolvedAgentTeamsConfig;
41
+ /**
42
+ * Get the active specification from .specforge/config.json.
43
+ *
44
+ * Claude Code Agent Teams only. Not used by MCP tool handlers.
45
+ *
46
+ * @returns ActiveSpecification if set, null if no spec is activated
47
+ */
48
+ export declare function getActiveSpecificationContext(): ActiveSpecification | null;
49
+ export {};
50
+ //# sourceMappingURL=context-helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-helper.d.ts","sourceRoot":"","sources":["../../../src/tools/core/context-helper.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAC3E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAEjF,KAAK,YAAY,GAAG,WAAW,GAAG,iBAAiB,CAAC;AAwBpD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7D,IAAI,EAAE,CAAC,EACP,MAAM,EAAE,YAAY,EAAE,GACrB,CAAC,CAaH;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrE,IAAI,EAAE,CAAC,EACP,cAAc,EAAE,YAAY,EAAE,EAC9B,cAAc,GAAE,YAAY,EAAO,GAClC,CAAC,CAWH;AAQD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,IAAI,wBAAwB,CAG/D;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,IAAI,mBAAmB,GAAG,IAAI,CAG1E"}
@@ -0,0 +1,49 @@
1
+ import {
2
+ tryLoadProjectConfig,
3
+ getAgentTeamsConfig as resolveAgentTeamsConfig,
4
+ getActiveSpecification as resolveActiveSpecification
5
+ } from "../../cli/config/loader.js";
6
+ function getLocalContext() {
7
+ const config = tryLoadProjectConfig();
8
+ return {
9
+ projectId: config?.projectId,
10
+ specificationId: config?.specificationId
11
+ };
12
+ }
13
+ function injectContext(args, fields) {
14
+ const missingFields = fields.filter((f) => !args[f]);
15
+ if (missingFields.length === 0) return args;
16
+ const context = getLocalContext();
17
+ const result = { ...args };
18
+ for (const field of missingFields) {
19
+ if (context[field]) {
20
+ result[field] = context[field];
21
+ }
22
+ }
23
+ return result;
24
+ }
25
+ function injectContextRequired(args, requiredFields, optionalFields = []) {
26
+ const result = injectContext(args, [...requiredFields, ...optionalFields]);
27
+ const missing = requiredFields.filter((f) => !result[f]);
28
+ if (missing.length > 0) {
29
+ throw new Error(
30
+ `Missing required context: ${missing.join(", ")}. Provide explicitly or run 'specforge switch' to set working context.`
31
+ );
32
+ }
33
+ return result;
34
+ }
35
+ function getAgentTeamsContext() {
36
+ const config = tryLoadProjectConfig();
37
+ return resolveAgentTeamsConfig(config);
38
+ }
39
+ function getActiveSpecificationContext() {
40
+ const config = tryLoadProjectConfig();
41
+ return resolveActiveSpecification(config);
42
+ }
43
+ export {
44
+ getActiveSpecificationContext,
45
+ getAgentTeamsContext,
46
+ injectContext,
47
+ injectContextRequired
48
+ };
49
+ //# sourceMappingURL=context-helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/tools/core/context-helper.ts"],"sourcesContent":["/**\n * Context Helper\n *\n * Provides utilities for injecting working context from .specforge/config.json\n * into tool arguments. This ensures tools scope to the correct project/specification\n * when not explicitly provided.\n */\n\nimport {\n tryLoadProjectConfig,\n getAgentTeamsConfig as resolveAgentTeamsConfig,\n getActiveSpecification as resolveActiveSpecification,\n} from '../../cli/config/loader.js';\nimport type { ResolvedAgentTeamsConfig } from '../../cli/config/loader.js';\nimport type { ActiveSpecification } from '../../cli/config/agent-teams.types.js';\n\ntype ContextField = 'projectId' | 'specificationId';\n\ninterface LocalContext {\n projectId?: string;\n specificationId?: string;\n}\n\n// ============================================================\n// UNIVERSAL CONTEXT — Used by MCP tool handlers\n// Works with any MCP-connected agent CLI\n// ============================================================\n\n/**\n * Get context from .specforge/config.json file.\n * This is the source of truth for the current project/specification.\n */\nfunction getLocalContext(): LocalContext {\n const config = tryLoadProjectConfig();\n return {\n projectId: config?.projectId,\n specificationId: config?.specificationId,\n };\n}\n\n/**\n * Inject missing context fields from .specforge/config.json.\n * Explicit args always take precedence over config values.\n *\n * @param args - Tool arguments that may be missing context fields\n * @param fields - Context fields to inject if missing\n * @returns Args with context fields injected from config\n */\nexport function injectContext<T extends Record<string, unknown>>(\n args: T,\n fields: ContextField[]\n): T {\n const missingFields = fields.filter(f => !args[f]);\n if (missingFields.length === 0) return args;\n\n const context = getLocalContext();\n const result: Record<string, unknown> = { ...args };\n\n for (const field of missingFields) {\n if (context[field]) {\n result[field] = context[field];\n }\n }\n return result as T;\n}\n\n/**\n * Inject context and validate required fields are present.\n * Throws error if required fields cannot be resolved from config.\n *\n * @param args - Tool arguments that may be missing context fields\n * @param requiredFields - Fields that MUST be present after injection\n * @param optionalFields - Fields to inject if available but not require\n * @returns Args with context fields injected\n * @throws Error if required fields cannot be resolved\n */\nexport function injectContextRequired<T extends Record<string, unknown>>(\n args: T,\n requiredFields: ContextField[],\n optionalFields: ContextField[] = []\n): T {\n const result = injectContext(args, [...requiredFields, ...optionalFields]);\n\n const missing = requiredFields.filter(f => !result[f]);\n if (missing.length > 0) {\n throw new Error(\n `Missing required context: ${missing.join(', ')}. ` +\n `Provide explicitly or run 'specforge switch' to set working context.`\n );\n }\n return result;\n}\n\n// ============================================================\n// AGENT TEAMS CONTEXT — Claude Code specific\n// Used by CLI orchestration layer only (spec-activate, plan, status --teams)\n// NOT used by any MCP tool handler\n// ============================================================\n\n/**\n * Get the resolved Agent Teams config from .specforge/config.json.\n *\n * Claude Code Agent Teams only. Not used by MCP tool handlers.\n *\n * Always returns a fully-resolved config with defaults applied (never null).\n * Used by CLI commands like `plan` and `status --teams` to read the user's\n * preferred strategy, team limits, and other settings.\n */\nexport function getAgentTeamsContext(): ResolvedAgentTeamsConfig {\n const config = tryLoadProjectConfig();\n return resolveAgentTeamsConfig(config);\n}\n\n/**\n * Get the active specification from .specforge/config.json.\n *\n * Claude Code Agent Teams only. Not used by MCP tool handlers.\n *\n * @returns ActiveSpecification if set, null if no spec is activated\n */\nexport function getActiveSpecificationContext(): ActiveSpecification | null {\n const config = tryLoadProjectConfig();\n return resolveActiveSpecification(config);\n}\n"],"mappings":"AAQA;AAAA,EACE;AAAA,EACA,uBAAuB;AAAA,EACvB,0BAA0B;AAAA,OACrB;AAoBP,SAAS,kBAAgC;AACvC,QAAM,SAAS,qBAAqB;AACpC,SAAO;AAAA,IACL,WAAW,QAAQ;AAAA,IACnB,iBAAiB,QAAQ;AAAA,EAC3B;AACF;AAUO,SAAS,cACd,MACA,QACG;AACH,QAAM,gBAAgB,OAAO,OAAO,OAAK,CAAC,KAAK,CAAC,CAAC;AACjD,MAAI,cAAc,WAAW,EAAG,QAAO;AAEvC,QAAM,UAAU,gBAAgB;AAChC,QAAM,SAAkC,EAAE,GAAG,KAAK;AAElD,aAAW,SAAS,eAAe;AACjC,QAAI,QAAQ,KAAK,GAAG;AAClB,aAAO,KAAK,IAAI,QAAQ,KAAK;AAAA,IAC/B;AAAA,EACF;AACA,SAAO;AACT;AAYO,SAAS,sBACd,MACA,gBACA,iBAAiC,CAAC,GAC/B;AACH,QAAM,SAAS,cAAc,MAAM,CAAC,GAAG,gBAAgB,GAAG,cAAc,CAAC;AAEzE,QAAM,UAAU,eAAe,OAAO,OAAK,CAAC,OAAO,CAAC,CAAC;AACrD,MAAI,QAAQ,SAAS,GAAG;AACtB,UAAM,IAAI;AAAA,MACR,6BAA6B,QAAQ,KAAK,IAAI,CAAC;AAAA,IAEjD;AAAA,EACF;AACA,SAAO;AACT;AAiBO,SAAS,uBAAiD;AAC/D,QAAM,SAAS,qBAAqB;AACpC,SAAO,wBAAwB,MAAM;AACvC;AASO,SAAS,gCAA4D;AAC1E,QAAM,SAAS,qBAAqB;AACpC,SAAO,2BAA2B,MAAM;AAC1C;","names":[]}
@@ -0,0 +1,2 @@
1
+ export * from './context-helper.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/core/index.ts"],"names":[],"mappings":"AAEA,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from "./context-helper.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/tools/core/index.ts"],"sourcesContent":["// mcp/src/tools/core/index.ts\n\nexport * from './context-helper.js';\n"],"mappings":"AAEA,cAAc;","names":[]}