@ai-coders/context 0.5.2 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (328) hide show
  1. package/README.md +247 -12
  2. package/dist/generators/agents/agentGenerator.d.ts +3 -0
  3. package/dist/generators/agents/agentGenerator.d.ts.map +1 -1
  4. package/dist/generators/agents/agentGenerator.js +13 -7
  5. package/dist/generators/agents/agentGenerator.js.map +1 -1
  6. package/dist/generators/agents/templates/playbookTemplate.d.ts.map +1 -1
  7. package/dist/generators/agents/templates/playbookTemplate.js +3 -1
  8. package/dist/generators/agents/templates/playbookTemplate.js.map +1 -1
  9. package/dist/generators/documentation/codebaseMapGenerator.d.ts +98 -0
  10. package/dist/generators/documentation/codebaseMapGenerator.d.ts.map +1 -0
  11. package/dist/generators/documentation/codebaseMapGenerator.js +247 -0
  12. package/dist/generators/documentation/codebaseMapGenerator.js.map +1 -0
  13. package/dist/generators/documentation/documentationGenerator.d.ts +2 -0
  14. package/dist/generators/documentation/documentationGenerator.d.ts.map +1 -1
  15. package/dist/generators/documentation/documentationGenerator.js +20 -1
  16. package/dist/generators/documentation/documentationGenerator.js.map +1 -1
  17. package/dist/generators/documentation/index.d.ts +2 -0
  18. package/dist/generators/documentation/index.d.ts.map +1 -1
  19. package/dist/generators/documentation/index.js +3 -1
  20. package/dist/generators/documentation/index.js.map +1 -1
  21. package/dist/generators/documentation/templates/architectureTemplate.d.ts.map +1 -1
  22. package/dist/generators/documentation/templates/architectureTemplate.js +2 -31
  23. package/dist/generators/documentation/templates/architectureTemplate.js.map +1 -1
  24. package/dist/generators/documentation/templates/common.d.ts +4 -1
  25. package/dist/generators/documentation/templates/common.d.ts.map +1 -1
  26. package/dist/generators/documentation/templates/common.js +4 -2
  27. package/dist/generators/documentation/templates/common.js.map +1 -1
  28. package/dist/generators/plans/templates/planTemplate.d.ts.map +1 -1
  29. package/dist/generators/plans/templates/planTemplate.js +46 -2
  30. package/dist/generators/plans/templates/planTemplate.js.map +1 -1
  31. package/dist/generators/skills/index.d.ts +7 -0
  32. package/dist/generators/skills/index.d.ts.map +1 -0
  33. package/dist/generators/skills/index.js +15 -0
  34. package/dist/generators/skills/index.js.map +1 -0
  35. package/dist/generators/skills/skillGenerator.d.ts +53 -0
  36. package/dist/generators/skills/skillGenerator.d.ts.map +1 -0
  37. package/dist/generators/skills/skillGenerator.js +149 -0
  38. package/dist/generators/skills/skillGenerator.js.map +1 -0
  39. package/dist/generators/skills/templates/indexTemplate.d.ts +13 -0
  40. package/dist/generators/skills/templates/indexTemplate.d.ts.map +1 -0
  41. package/dist/generators/skills/templates/indexTemplate.js +102 -0
  42. package/dist/generators/skills/templates/indexTemplate.js.map +1 -0
  43. package/dist/generators/skills/templates/skillTemplate.d.ts +20 -0
  44. package/dist/generators/skills/templates/skillTemplate.d.ts.map +1 -0
  45. package/dist/generators/skills/templates/skillTemplate.js +85 -0
  46. package/dist/generators/skills/templates/skillTemplate.js.map +1 -0
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +1315 -43
  49. package/dist/index.js.map +1 -1
  50. package/dist/services/ai/agentEvents.d.ts +1 -1
  51. package/dist/services/ai/agentEvents.d.ts.map +1 -1
  52. package/dist/services/ai/agents/index.d.ts +2 -0
  53. package/dist/services/ai/agents/index.d.ts.map +1 -1
  54. package/dist/services/ai/agents/index.js +3 -1
  55. package/dist/services/ai/agents/index.js.map +1 -1
  56. package/dist/services/ai/agents/skillAgent.d.ts +49 -0
  57. package/dist/services/ai/agents/skillAgent.d.ts.map +1 -0
  58. package/dist/services/ai/agents/skillAgent.js +179 -0
  59. package/dist/services/ai/agents/skillAgent.js.map +1 -0
  60. package/dist/services/ai/prompts/index.d.ts +1 -1
  61. package/dist/services/ai/prompts/index.d.ts.map +1 -1
  62. package/dist/services/ai/prompts/index.js +2 -1
  63. package/dist/services/ai/prompts/index.js.map +1 -1
  64. package/dist/services/ai/prompts/sharedPrompts.d.ts +4 -0
  65. package/dist/services/ai/prompts/sharedPrompts.d.ts.map +1 -1
  66. package/dist/services/ai/prompts/sharedPrompts.js +33 -0
  67. package/dist/services/ai/prompts/sharedPrompts.js.map +1 -1
  68. package/dist/services/ai/schemas.d.ts +98 -1
  69. package/dist/services/ai/schemas.d.ts.map +1 -1
  70. package/dist/services/ai/schemas.js +61 -3
  71. package/dist/services/ai/schemas.js.map +1 -1
  72. package/dist/services/ai/toolRegistry.d.ts.map +1 -1
  73. package/dist/services/ai/toolRegistry.js +17 -0
  74. package/dist/services/ai/toolRegistry.js.map +1 -1
  75. package/dist/services/ai/tools/fillScaffoldingTool.d.ts +21 -4
  76. package/dist/services/ai/tools/fillScaffoldingTool.d.ts.map +1 -1
  77. package/dist/services/ai/tools/fillScaffoldingTool.js +17 -0
  78. package/dist/services/ai/tools/fillScaffoldingTool.js.map +1 -1
  79. package/dist/services/ai/tools/getCodebaseMapTool.d.ts +17 -0
  80. package/dist/services/ai/tools/getCodebaseMapTool.d.ts.map +1 -0
  81. package/dist/services/ai/tools/getCodebaseMapTool.js +115 -0
  82. package/dist/services/ai/tools/getCodebaseMapTool.js.map +1 -0
  83. package/dist/services/ai/tools/index.d.ts +3 -2
  84. package/dist/services/ai/tools/index.d.ts.map +1 -1
  85. package/dist/services/ai/tools/index.js +12 -3
  86. package/dist/services/ai/tools/index.js.map +1 -1
  87. package/dist/services/ai/tools/initializeContextTool.d.ts +22 -4
  88. package/dist/services/ai/tools/initializeContextTool.d.ts.map +1 -1
  89. package/dist/services/ai/tools/initializeContextTool.js +201 -16
  90. package/dist/services/ai/tools/initializeContextTool.js.map +1 -1
  91. package/dist/services/ai/tools/scaffoldPlanTool.d.ts +11 -0
  92. package/dist/services/ai/tools/scaffoldPlanTool.d.ts.map +1 -1
  93. package/dist/services/ai/tools/scaffoldPlanTool.js +79 -7
  94. package/dist/services/ai/tools/scaffoldPlanTool.js.map +1 -1
  95. package/dist/services/export/exportRulesService.d.ts +62 -0
  96. package/dist/services/export/exportRulesService.d.ts.map +1 -0
  97. package/dist/services/export/exportRulesService.js +242 -0
  98. package/dist/services/export/exportRulesService.js.map +1 -0
  99. package/dist/services/export/index.d.ts +5 -0
  100. package/dist/services/export/index.d.ts.map +1 -0
  101. package/dist/services/export/index.js +10 -0
  102. package/dist/services/export/index.js.map +1 -0
  103. package/dist/services/export/skillExportService.d.ts +64 -0
  104. package/dist/services/export/skillExportService.d.ts.map +1 -0
  105. package/dist/services/export/skillExportService.js +238 -0
  106. package/dist/services/export/skillExportService.js.map +1 -0
  107. package/dist/services/fill/skillFillService.d.ts +50 -0
  108. package/dist/services/fill/skillFillService.d.ts.map +1 -0
  109. package/dist/services/fill/skillFillService.js +254 -0
  110. package/dist/services/fill/skillFillService.js.map +1 -0
  111. package/dist/services/import/agentsDetector.d.ts +12 -0
  112. package/dist/services/import/agentsDetector.d.ts.map +1 -0
  113. package/dist/services/import/agentsDetector.js +183 -0
  114. package/dist/services/import/agentsDetector.js.map +1 -0
  115. package/dist/services/import/importAgentsService.d.ts +14 -0
  116. package/dist/services/import/importAgentsService.d.ts.map +1 -0
  117. package/dist/services/import/importAgentsService.js +195 -0
  118. package/dist/services/import/importAgentsService.js.map +1 -0
  119. package/dist/services/import/importRulesService.d.ts +17 -0
  120. package/dist/services/import/importRulesService.d.ts.map +1 -0
  121. package/dist/services/import/importRulesService.js +222 -0
  122. package/dist/services/import/importRulesService.js.map +1 -0
  123. package/dist/services/import/index.d.ts +7 -0
  124. package/dist/services/import/index.d.ts.map +1 -0
  125. package/dist/services/import/index.js +28 -0
  126. package/dist/services/import/index.js.map +1 -0
  127. package/dist/services/import/presets.d.ts +8 -0
  128. package/dist/services/import/presets.d.ts.map +1 -0
  129. package/dist/services/import/presets.js +176 -0
  130. package/dist/services/import/presets.js.map +1 -0
  131. package/dist/services/import/rulesDetector.d.ts +16 -0
  132. package/dist/services/import/rulesDetector.d.ts.map +1 -0
  133. package/dist/services/import/rulesDetector.js +278 -0
  134. package/dist/services/import/rulesDetector.js.map +1 -0
  135. package/dist/services/import/types.d.ts +72 -0
  136. package/dist/services/import/types.d.ts.map +1 -0
  137. package/dist/services/import/types.js +3 -0
  138. package/dist/services/import/types.js.map +1 -0
  139. package/dist/services/mcp/mcpServer.d.ts +24 -0
  140. package/dist/services/mcp/mcpServer.d.ts.map +1 -1
  141. package/dist/services/mcp/mcpServer.js +1651 -7
  142. package/dist/services/mcp/mcpServer.js.map +1 -1
  143. package/dist/services/quickSync/index.d.ts +3 -0
  144. package/dist/services/quickSync/index.d.ts.map +1 -0
  145. package/dist/services/quickSync/index.js +7 -0
  146. package/dist/services/quickSync/index.js.map +1 -0
  147. package/dist/services/quickSync/quickSyncService.d.ts +72 -0
  148. package/dist/services/quickSync/quickSyncService.d.ts.map +1 -0
  149. package/dist/services/quickSync/quickSyncService.js +268 -0
  150. package/dist/services/quickSync/quickSyncService.js.map +1 -0
  151. package/dist/services/report/index.d.ts +3 -0
  152. package/dist/services/report/index.d.ts.map +1 -0
  153. package/dist/services/report/index.js +6 -0
  154. package/dist/services/report/index.js.map +1 -0
  155. package/dist/services/report/reportService.d.ts +131 -0
  156. package/dist/services/report/reportService.d.ts.map +1 -0
  157. package/dist/services/report/reportService.js +372 -0
  158. package/dist/services/report/reportService.js.map +1 -0
  159. package/dist/services/semantic/contextBuilder.d.ts +8 -1
  160. package/dist/services/semantic/contextBuilder.d.ts.map +1 -1
  161. package/dist/services/semantic/contextBuilder.js +107 -20
  162. package/dist/services/semantic/contextBuilder.js.map +1 -1
  163. package/dist/services/shared/globPatterns.d.ts +48 -0
  164. package/dist/services/shared/globPatterns.d.ts.map +1 -0
  165. package/dist/services/shared/globPatterns.js +110 -0
  166. package/dist/services/shared/globPatterns.js.map +1 -0
  167. package/dist/services/shared/index.d.ts +10 -0
  168. package/dist/services/shared/index.d.ts.map +1 -0
  169. package/dist/services/shared/index.js +46 -0
  170. package/dist/services/shared/index.js.map +1 -0
  171. package/dist/services/shared/pathHelpers.d.ts +71 -0
  172. package/dist/services/shared/pathHelpers.d.ts.map +1 -0
  173. package/dist/services/shared/pathHelpers.js +162 -0
  174. package/dist/services/shared/pathHelpers.js.map +1 -0
  175. package/dist/services/shared/types.d.ts +74 -0
  176. package/dist/services/shared/types.d.ts.map +1 -0
  177. package/dist/services/shared/types.js +44 -0
  178. package/dist/services/shared/types.js.map +1 -0
  179. package/dist/services/shared/uiHelpers.d.ts +70 -0
  180. package/dist/services/shared/uiHelpers.d.ts.map +1 -0
  181. package/dist/services/shared/uiHelpers.js +131 -0
  182. package/dist/services/shared/uiHelpers.js.map +1 -0
  183. package/dist/services/stack/index.d.ts +6 -0
  184. package/dist/services/stack/index.d.ts.map +1 -0
  185. package/dist/services/stack/index.js +25 -0
  186. package/dist/services/stack/index.js.map +1 -0
  187. package/dist/services/stack/projectTypeClassifier.d.ts +59 -0
  188. package/dist/services/stack/projectTypeClassifier.d.ts.map +1 -0
  189. package/dist/services/stack/projectTypeClassifier.js +242 -0
  190. package/dist/services/stack/projectTypeClassifier.js.map +1 -0
  191. package/dist/services/stack/scaffoldFilter.d.ts +75 -0
  192. package/dist/services/stack/scaffoldFilter.d.ts.map +1 -0
  193. package/dist/services/stack/scaffoldFilter.js +222 -0
  194. package/dist/services/stack/scaffoldFilter.js.map +1 -0
  195. package/dist/services/stack/stackDetector.d.ts +43 -0
  196. package/dist/services/stack/stackDetector.d.ts.map +1 -0
  197. package/dist/services/stack/stackDetector.js +406 -0
  198. package/dist/services/stack/stackDetector.js.map +1 -0
  199. package/dist/services/start/index.d.ts +3 -0
  200. package/dist/services/start/index.d.ts.map +1 -0
  201. package/dist/services/start/index.js +6 -0
  202. package/dist/services/start/index.js.map +1 -0
  203. package/dist/services/start/startService.d.ts +64 -0
  204. package/dist/services/start/startService.d.ts.map +1 -0
  205. package/dist/services/start/startService.js +180 -0
  206. package/dist/services/start/startService.js.map +1 -0
  207. package/dist/services/sync/presets.d.ts.map +1 -1
  208. package/dist/services/sync/presets.js +16 -1
  209. package/dist/services/sync/presets.js.map +1 -1
  210. package/dist/services/sync/types.d.ts +1 -1
  211. package/dist/services/sync/types.d.ts.map +1 -1
  212. package/dist/services/workflow/autoAdvance.d.ts +38 -0
  213. package/dist/services/workflow/autoAdvance.d.ts.map +1 -0
  214. package/dist/services/workflow/autoAdvance.js +219 -0
  215. package/dist/services/workflow/autoAdvance.js.map +1 -0
  216. package/dist/services/workflow/index.d.ts +6 -0
  217. package/dist/services/workflow/index.d.ts.map +1 -0
  218. package/dist/services/workflow/index.js +11 -0
  219. package/dist/services/workflow/index.js.map +1 -0
  220. package/dist/services/workflow/workflowService.d.ts +98 -0
  221. package/dist/services/workflow/workflowService.d.ts.map +1 -0
  222. package/dist/services/workflow/workflowService.js +210 -0
  223. package/dist/services/workflow/workflowService.js.map +1 -0
  224. package/dist/utils/cliUI.d.ts +4 -0
  225. package/dist/utils/cliUI.d.ts.map +1 -1
  226. package/dist/utils/cliUI.js +31 -1
  227. package/dist/utils/cliUI.js.map +1 -1
  228. package/dist/utils/i18n.d.ts +202 -0
  229. package/dist/utils/i18n.d.ts.map +1 -1
  230. package/dist/utils/i18n.js +438 -2
  231. package/dist/utils/i18n.js.map +1 -1
  232. package/dist/utils/theme.d.ts +1 -0
  233. package/dist/utils/theme.d.ts.map +1 -1
  234. package/dist/utils/theme.js +1 -0
  235. package/dist/utils/theme.js.map +1 -1
  236. package/dist/workflow/agents/agentRegistry.d.ts +82 -0
  237. package/dist/workflow/agents/agentRegistry.d.ts.map +1 -0
  238. package/dist/workflow/agents/agentRegistry.js +205 -0
  239. package/dist/workflow/agents/agentRegistry.js.map +1 -0
  240. package/dist/workflow/agents/index.d.ts +7 -0
  241. package/dist/workflow/agents/index.d.ts.map +1 -0
  242. package/dist/workflow/agents/index.js +14 -0
  243. package/dist/workflow/agents/index.js.map +1 -0
  244. package/dist/workflow/collaboration.d.ts +110 -0
  245. package/dist/workflow/collaboration.d.ts.map +1 -0
  246. package/dist/workflow/collaboration.js +301 -0
  247. package/dist/workflow/collaboration.js.map +1 -0
  248. package/dist/workflow/index.d.ts +25 -0
  249. package/dist/workflow/index.d.ts.map +1 -0
  250. package/dist/workflow/index.js +124 -0
  251. package/dist/workflow/index.js.map +1 -0
  252. package/dist/workflow/orchestration/agentOrchestrator.d.ts +68 -0
  253. package/dist/workflow/orchestration/agentOrchestrator.d.ts.map +1 -0
  254. package/dist/workflow/orchestration/agentOrchestrator.js +280 -0
  255. package/dist/workflow/orchestration/agentOrchestrator.js.map +1 -0
  256. package/dist/workflow/orchestration/documentLinker.d.ts +100 -0
  257. package/dist/workflow/orchestration/documentLinker.d.ts.map +1 -0
  258. package/dist/workflow/orchestration/documentLinker.js +266 -0
  259. package/dist/workflow/orchestration/documentLinker.js.map +1 -0
  260. package/dist/workflow/orchestration/index.d.ts +9 -0
  261. package/dist/workflow/orchestration/index.d.ts.map +1 -0
  262. package/dist/workflow/orchestration/index.js +25 -0
  263. package/dist/workflow/orchestration/index.js.map +1 -0
  264. package/dist/workflow/orchestrator.d.ts +99 -0
  265. package/dist/workflow/orchestrator.d.ts.map +1 -0
  266. package/dist/workflow/orchestrator.js +217 -0
  267. package/dist/workflow/orchestrator.js.map +1 -0
  268. package/dist/workflow/phases.d.ts +64 -0
  269. package/dist/workflow/phases.d.ts.map +1 -0
  270. package/dist/workflow/phases.js +151 -0
  271. package/dist/workflow/phases.js.map +1 -0
  272. package/dist/workflow/plans/index.d.ts +8 -0
  273. package/dist/workflow/plans/index.d.ts.map +1 -0
  274. package/dist/workflow/plans/index.js +27 -0
  275. package/dist/workflow/plans/index.js.map +1 -0
  276. package/dist/workflow/plans/planLinker.d.ts +119 -0
  277. package/dist/workflow/plans/planLinker.d.ts.map +1 -0
  278. package/dist/workflow/plans/planLinker.js +499 -0
  279. package/dist/workflow/plans/planLinker.js.map +1 -0
  280. package/dist/workflow/plans/types.d.ts +167 -0
  281. package/dist/workflow/plans/types.d.ts.map +1 -0
  282. package/dist/workflow/plans/types.js +25 -0
  283. package/dist/workflow/plans/types.js.map +1 -0
  284. package/dist/workflow/prevcConfig.d.ts +27 -0
  285. package/dist/workflow/prevcConfig.d.ts.map +1 -0
  286. package/dist/workflow/prevcConfig.js +153 -0
  287. package/dist/workflow/prevcConfig.js.map +1 -0
  288. package/dist/workflow/roles.d.ts +44 -0
  289. package/dist/workflow/roles.d.ts.map +1 -0
  290. package/dist/workflow/roles.js +112 -0
  291. package/dist/workflow/roles.js.map +1 -0
  292. package/dist/workflow/scaling.d.ts +44 -0
  293. package/dist/workflow/scaling.d.ts.map +1 -0
  294. package/dist/workflow/scaling.js +224 -0
  295. package/dist/workflow/scaling.js.map +1 -0
  296. package/dist/workflow/skills/frontmatter.d.ts +23 -0
  297. package/dist/workflow/skills/frontmatter.d.ts.map +1 -0
  298. package/dist/workflow/skills/frontmatter.js +100 -0
  299. package/dist/workflow/skills/frontmatter.js.map +1 -0
  300. package/dist/workflow/skills/index.d.ts +10 -0
  301. package/dist/workflow/skills/index.d.ts.map +1 -0
  302. package/dist/workflow/skills/index.js +22 -0
  303. package/dist/workflow/skills/index.js.map +1 -0
  304. package/dist/workflow/skills/skillRegistry.d.ts +60 -0
  305. package/dist/workflow/skills/skillRegistry.d.ts.map +1 -0
  306. package/dist/workflow/skills/skillRegistry.js +257 -0
  307. package/dist/workflow/skills/skillRegistry.js.map +1 -0
  308. package/dist/workflow/skills/skillTemplates.d.ts +16 -0
  309. package/dist/workflow/skills/skillTemplates.d.ts.map +1 -0
  310. package/dist/workflow/skills/skillTemplates.js +610 -0
  311. package/dist/workflow/skills/skillTemplates.js.map +1 -0
  312. package/dist/workflow/skills/types.d.ts +72 -0
  313. package/dist/workflow/skills/types.d.ts.map +1 -0
  314. package/dist/workflow/skills/types.js +48 -0
  315. package/dist/workflow/skills/types.js.map +1 -0
  316. package/dist/workflow/status/statusManager.d.ts +84 -0
  317. package/dist/workflow/status/statusManager.d.ts.map +1 -0
  318. package/dist/workflow/status/statusManager.js +402 -0
  319. package/dist/workflow/status/statusManager.js.map +1 -0
  320. package/dist/workflow/status/templates.d.ts +40 -0
  321. package/dist/workflow/status/templates.d.ts.map +1 -0
  322. package/dist/workflow/status/templates.js +148 -0
  323. package/dist/workflow/status/templates.js.map +1 -0
  324. package/dist/workflow/types.d.ts +178 -0
  325. package/dist/workflow/types.d.ts.map +1 -0
  326. package/dist/workflow/types.js +25 -0
  327. package/dist/workflow/types.js.map +1 -0
  328. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -57,10 +57,18 @@ const initService_1 = require("./services/init/initService");
57
57
  const fillService_1 = require("./services/fill/fillService");
58
58
  const planService_1 = require("./services/plan/planService");
59
59
  const syncService_1 = require("./services/sync/syncService");
60
+ const import_1 = require("./services/import");
60
61
  const serve_1 = require("./services/serve");
61
62
  const mcp_1 = require("./services/mcp");
62
63
  const state_1 = require("./services/state");
63
64
  const update_1 = require("./services/update");
65
+ const workflow_1 = require("./services/workflow");
66
+ const start_1 = require("./services/start");
67
+ const export_1 = require("./services/export");
68
+ const report_1 = require("./services/report");
69
+ const quickSync_1 = require("./services/quickSync");
70
+ const workflow_2 = require("./workflow");
71
+ const providerFactory_1 = require("./services/ai/providerFactory");
64
72
  const prompts_1 = require("./utils/prompts");
65
73
  const version_1 = require("./version");
66
74
  const rawArgs = process.argv.slice(2);
@@ -101,6 +109,16 @@ const syncService = new syncService_1.SyncService({
101
109
  t,
102
110
  version: version_1.VERSION
103
111
  });
112
+ const importRulesService = new import_1.ImportRulesService({
113
+ ui,
114
+ t,
115
+ version: version_1.VERSION
116
+ });
117
+ const importAgentsService = new import_1.ImportAgentsService({
118
+ ui,
119
+ t,
120
+ version: version_1.VERSION
121
+ });
104
122
  const updateService = new update_1.UpdateService({
105
123
  ui,
106
124
  t
@@ -312,6 +330,60 @@ program
312
330
  process.exit(1);
313
331
  }
314
332
  });
333
+ program
334
+ .command('import-rules')
335
+ .description(t('commands.importRules.description'))
336
+ .argument('[repo-path]', 'Repository path to scan', process.cwd())
337
+ .option('-s, --source <paths...>', t('commands.importRules.options.source'))
338
+ .option('-t, --target <dir>', t('commands.importRules.options.target'))
339
+ .option('-f, --format <format>', t('commands.importRules.options.format'), 'markdown')
340
+ .option('--force', t('commands.importRules.options.force'))
341
+ .option('--dry-run', t('commands.importRules.options.dryRun'))
342
+ .option('-v, --verbose', t('commands.importRules.options.verbose'))
343
+ .option('--no-auto-detect', 'Disable auto-detection')
344
+ .action(async (repoPath, options) => {
345
+ try {
346
+ await importRulesService.run({
347
+ source: options.source,
348
+ target: options.target,
349
+ format: options.format,
350
+ force: options.force,
351
+ dryRun: options.dryRun,
352
+ verbose: options.verbose,
353
+ autoDetect: options.autoDetect !== false
354
+ }, repoPath);
355
+ }
356
+ catch (error) {
357
+ ui.displayError(t('errors.import.failed'), error);
358
+ process.exit(1);
359
+ }
360
+ });
361
+ program
362
+ .command('import-agents')
363
+ .description(t('commands.importAgents.description'))
364
+ .argument('[repo-path]', 'Repository path to scan', process.cwd())
365
+ .option('-s, --source <paths...>', t('commands.importAgents.options.source'))
366
+ .option('-t, --target <dir>', t('commands.importAgents.options.target'))
367
+ .option('--force', t('commands.importAgents.options.force'))
368
+ .option('--dry-run', t('commands.importAgents.options.dryRun'))
369
+ .option('-v, --verbose', t('commands.importAgents.options.verbose'))
370
+ .option('--no-auto-detect', 'Disable auto-detection')
371
+ .action(async (repoPath, options) => {
372
+ try {
373
+ await importAgentsService.run({
374
+ source: options.source,
375
+ target: options.target,
376
+ force: options.force,
377
+ dryRun: options.dryRun,
378
+ verbose: options.verbose,
379
+ autoDetect: options.autoDetect !== false
380
+ }, repoPath);
381
+ }
382
+ catch (error) {
383
+ ui.displayError(t('errors.import.failed'), error);
384
+ process.exit(1);
385
+ }
386
+ });
315
387
  program
316
388
  .command('serve')
317
389
  .description('Start passthrough server for external AI agents (stdin/stdout JSON)')
@@ -362,6 +434,441 @@ program
362
434
  process.exit(1);
363
435
  }
364
436
  });
437
+ // Smart Start Command
438
+ program
439
+ .command('start')
440
+ .description(t('commands.start.description'))
441
+ .argument('[feature-name]', t('commands.start.arguments.featureName'))
442
+ .option('-t, --template <template>', t('commands.start.options.template'), 'auto')
443
+ .option('--skip-fill', t('commands.start.options.skipFill'))
444
+ .option('--skip-workflow', t('commands.start.options.skipWorkflow'))
445
+ .option('-k, --api-key <key>', t('commands.fill.options.apiKey'))
446
+ .option('-m, --model <model>', t('commands.fill.options.model'), DEFAULT_MODEL)
447
+ .option('-p, --provider <provider>', t('commands.fill.options.provider'))
448
+ .option('-v, --verbose', t('commands.fill.options.verbose'))
449
+ .action(async (featureName, options) => {
450
+ try {
451
+ const startService = new start_1.StartService({
452
+ ui,
453
+ t,
454
+ version: version_1.VERSION,
455
+ defaultModel: DEFAULT_MODEL,
456
+ });
457
+ const result = await startService.run(process.cwd(), {
458
+ featureName,
459
+ template: options.template,
460
+ skipFill: options.skipFill,
461
+ skipWorkflow: options.skipWorkflow,
462
+ apiKey: options.apiKey,
463
+ model: options.model,
464
+ provider: options.provider,
465
+ verbose: options.verbose,
466
+ });
467
+ // Display summary
468
+ const details = [];
469
+ if (result.initialized)
470
+ details.push('context initialized');
471
+ if (result.filled)
472
+ details.push('docs filled');
473
+ if (result.workflowStarted)
474
+ details.push(`workflow started (${(0, workflow_2.getScaleName)(result.scale)})`);
475
+ if (result.stackDetected?.primaryLanguage) {
476
+ details.push(`stack: ${result.stackDetected.primaryLanguage}`);
477
+ }
478
+ ui.displaySuccess(t('success.start.complete', { details: details.join(', ') }));
479
+ }
480
+ catch (error) {
481
+ ui.displayError(t('errors.cli.executionFailed'), error);
482
+ process.exit(1);
483
+ }
484
+ });
485
+ // Export Rules Command
486
+ program
487
+ .command('export-rules')
488
+ .description(t('commands.export.description'))
489
+ .argument('[repo-path]', 'Repository path', process.cwd())
490
+ .option('-s, --source <dir>', t('commands.export.options.source'), '.context/docs')
491
+ .option('-t, --targets <paths...>', t('commands.export.options.targets'))
492
+ .option('--preset <name>', t('commands.export.options.preset'))
493
+ .option('--force', t('commands.export.options.force'))
494
+ .option('--dry-run', t('commands.export.options.dryRun'))
495
+ .option('-v, --verbose', t('commands.fill.options.verbose'))
496
+ .action(async (repoPath, options) => {
497
+ try {
498
+ const exportService = new export_1.ExportRulesService({
499
+ ui,
500
+ t,
501
+ version: version_1.VERSION,
502
+ });
503
+ await exportService.run(repoPath, {
504
+ source: options.source,
505
+ targets: options.targets,
506
+ preset: options.preset,
507
+ force: options.force,
508
+ dryRun: options.dryRun,
509
+ verbose: options.verbose,
510
+ });
511
+ }
512
+ catch (error) {
513
+ ui.displayError(t('errors.cli.executionFailed'), error);
514
+ process.exit(1);
515
+ }
516
+ });
517
+ // Report Command
518
+ program
519
+ .command('report')
520
+ .description(t('commands.report.description'))
521
+ .argument('[repo-path]', 'Repository path', process.cwd())
522
+ .option('-f, --format <format>', t('commands.report.options.format'), 'console')
523
+ .option('-o, --output <path>', t('commands.report.options.output'))
524
+ .option('--include-stack', t('commands.report.options.includeStack'))
525
+ .option('-v, --verbose', t('commands.fill.options.verbose'))
526
+ .action(async (repoPath, options) => {
527
+ try {
528
+ const reportService = new report_1.ReportService({
529
+ ui,
530
+ t,
531
+ version: version_1.VERSION,
532
+ });
533
+ const report = await reportService.generate(repoPath, {
534
+ format: options.format,
535
+ output: options.output,
536
+ includeStack: options.includeStack,
537
+ verbose: options.verbose,
538
+ });
539
+ await reportService.output(report, options);
540
+ }
541
+ catch (error) {
542
+ ui.displayError(t('errors.cli.executionFailed'), error);
543
+ process.exit(1);
544
+ }
545
+ });
546
+ // Skill Commands
547
+ const skillCommand = program
548
+ .command('skill')
549
+ .description(t('commands.skill.description'));
550
+ skillCommand
551
+ .command('init')
552
+ .description(t('commands.skill.init.description'))
553
+ .argument('[repo-path]', 'Repository path', process.cwd())
554
+ .option('-f, --force', 'Overwrite existing files')
555
+ .option('--skills <skills...>', 'Specific skills to scaffold')
556
+ .action(async (repoPath, options) => {
557
+ try {
558
+ const { createSkillGenerator } = await Promise.resolve().then(() => __importStar(require('./generators/skills')));
559
+ const generator = createSkillGenerator({ repoPath });
560
+ const result = await generator.generate({
561
+ skills: options.skills,
562
+ force: options.force,
563
+ });
564
+ ui.displaySuccess(`Skills initialized in ${result.skillsDir}`);
565
+ ui.displayInfo('Generated', result.generatedSkills.join(', ') || 'none');
566
+ if (result.skippedSkills.length > 0) {
567
+ ui.displayInfo('Skipped (already exist)', result.skippedSkills.join(', '));
568
+ }
569
+ }
570
+ catch (error) {
571
+ ui.displayError('Failed to initialize skills', error);
572
+ process.exit(1);
573
+ }
574
+ });
575
+ skillCommand
576
+ .command('fill')
577
+ .description(t('commands.skill.fill.description'))
578
+ .argument('[repo-path]', 'Repository path', process.cwd())
579
+ .option('-o, --output <dir>', 'Output directory', '.context')
580
+ .option('-f, --force', 'Overwrite existing content')
581
+ .option('--skills <skills...>', 'Specific skills to fill')
582
+ .option('--model <model>', 'LLM model to use')
583
+ .option('--provider <provider>', 'LLM provider (anthropic, openai, google, openrouter)')
584
+ .option('--api-key <key>', 'API key for LLM provider')
585
+ .option('--base-url <url>', 'Base URL for custom LLM endpoint')
586
+ .option('--no-semantic', 'Disable semantic context mode')
587
+ .option('--use-lsp', 'Enable LSP for deeper analysis')
588
+ .option('-v, --verbose', 'Show detailed progress')
589
+ .option('--limit <number>', 'Limit number of skills to fill', parseInt)
590
+ .action(async (repoPath, options) => {
591
+ try {
592
+ const { SkillFillService } = await Promise.resolve().then(() => __importStar(require('./services/fill/skillFillService')));
593
+ const skillFillService = new SkillFillService({
594
+ ui,
595
+ t,
596
+ version: version_1.VERSION,
597
+ defaultModel: DEFAULT_MODEL,
598
+ });
599
+ const result = await skillFillService.run(repoPath, {
600
+ output: options.output,
601
+ skills: options.skills,
602
+ force: options.force,
603
+ model: options.model,
604
+ provider: options.provider,
605
+ apiKey: options.apiKey,
606
+ baseUrl: options.baseUrl,
607
+ semantic: options.semantic,
608
+ useLsp: options.useLsp,
609
+ verbose: options.verbose,
610
+ limit: options.limit,
611
+ });
612
+ if (result.filled.length > 0) {
613
+ ui.displaySuccess(t('success.skill.filled', { count: result.filled.length }));
614
+ }
615
+ }
616
+ catch (error) {
617
+ ui.displayError(t('errors.skill.fillFailed'), error);
618
+ process.exit(1);
619
+ }
620
+ });
621
+ skillCommand
622
+ .command('list')
623
+ .description(t('commands.skill.list.description'))
624
+ .argument('[repo-path]', 'Repository path', process.cwd())
625
+ .option('--json', 'Output as JSON')
626
+ .action(async (repoPath, options) => {
627
+ try {
628
+ const { createSkillRegistry, BUILT_IN_SKILLS } = await Promise.resolve().then(() => __importStar(require('./workflow/skills')));
629
+ const registry = createSkillRegistry(repoPath);
630
+ const discovered = await registry.discoverAll();
631
+ if (options.json) {
632
+ console.log(JSON.stringify({
633
+ builtIn: discovered.builtIn.map(s => s.slug),
634
+ custom: discovered.custom.map(s => s.slug),
635
+ total: discovered.all.length,
636
+ }, null, 2));
637
+ return;
638
+ }
639
+ console.log('\nBuilt-in Skills:');
640
+ for (const skill of discovered.builtIn) {
641
+ const scaffolded = discovered.all.find(s => s.slug === skill.slug && s.path.includes('.context'));
642
+ const status = scaffolded ? '[scaffolded]' : '[available]';
643
+ console.log(` ${skill.slug} ${status}`);
644
+ console.log(` ${skill.metadata.description}`);
645
+ }
646
+ if (discovered.custom.length > 0) {
647
+ console.log('\nCustom Skills:');
648
+ for (const skill of discovered.custom) {
649
+ console.log(` ${skill.slug}`);
650
+ console.log(` ${skill.metadata.description}`);
651
+ }
652
+ }
653
+ console.log(`\nTotal: ${discovered.all.length} skills (${discovered.builtIn.length} built-in, ${discovered.custom.length} custom)`);
654
+ }
655
+ catch (error) {
656
+ ui.displayError('Failed to list skills', error);
657
+ process.exit(1);
658
+ }
659
+ });
660
+ skillCommand
661
+ .command('export')
662
+ .description(t('commands.skill.export.description'))
663
+ .argument('[repo-path]', 'Repository path', process.cwd())
664
+ .option('-p, --preset <preset>', 'Export preset: claude, gemini, codex, all', 'all')
665
+ .option('-f, --force', 'Overwrite existing files')
666
+ .option('--include-builtin', 'Include built-in skills even if not scaffolded')
667
+ .option('--dry-run', 'Preview changes without writing')
668
+ .action(async (repoPath, options) => {
669
+ try {
670
+ const { SkillExportService } = await Promise.resolve().then(() => __importStar(require('./services/export/skillExportService')));
671
+ const exportService = new SkillExportService({
672
+ ui,
673
+ t,
674
+ version: version_1.VERSION,
675
+ });
676
+ const result = await exportService.run(repoPath, {
677
+ preset: options.preset,
678
+ force: options.force,
679
+ includeBuiltIn: options.includeBuiltin,
680
+ dryRun: options.dryRun,
681
+ });
682
+ if (options.dryRun) {
683
+ ui.displayInfo('Dry run', 'No files were written');
684
+ }
685
+ else {
686
+ ui.displaySuccess(`Exported ${result.skillsExported.length} skills to ${result.targets.length} targets`);
687
+ }
688
+ }
689
+ catch (error) {
690
+ ui.displayError('Failed to export skills', error);
691
+ process.exit(1);
692
+ }
693
+ });
694
+ skillCommand
695
+ .command('create <name>')
696
+ .description(t('commands.skill.create.description'))
697
+ .argument('[repo-path]', 'Repository path', process.cwd())
698
+ .option('-d, --description <text>', 'Skill description')
699
+ .option('--phases <phases...>', 'PREVC phases (P, R, E, V, C)')
700
+ .option('-f, --force', 'Overwrite if exists')
701
+ .action(async (name, repoPath, options) => {
702
+ try {
703
+ const { createSkillGenerator } = await Promise.resolve().then(() => __importStar(require('./generators/skills')));
704
+ const generator = createSkillGenerator({ repoPath });
705
+ const skillPath = await generator.generateCustomSkill({
706
+ name,
707
+ description: options.description || `TODO: Describe when to use ${name}`,
708
+ phases: options.phases,
709
+ force: options.force,
710
+ });
711
+ ui.displaySuccess(`Created skill: ${name}`);
712
+ ui.displayInfo('Path', skillPath);
713
+ }
714
+ catch (error) {
715
+ ui.displayError('Failed to create skill', error);
716
+ process.exit(1);
717
+ }
718
+ });
719
+ // PREVC Workflow Commands
720
+ const workflowCommand = program
721
+ .command('workflow')
722
+ .description('PREVC workflow management (Planning, Review, Execution, Validation, Confirmation)');
723
+ // Helper to create workflow service dependencies
724
+ const getWorkflowDeps = () => ({
725
+ ui: {
726
+ displaySuccess: (msg) => ui.displaySuccess(msg),
727
+ displayError: (msg, err) => ui.displayError(msg, err),
728
+ displayInfo: (title, detail) => ui.displayInfo(title, detail || '')
729
+ }
730
+ });
731
+ workflowCommand
732
+ .command('init <name>')
733
+ .description('Initialize a new PREVC workflow')
734
+ .option('-d, --description <text>', 'Project description for scale detection')
735
+ .option('-s, --scale <scale>', 'Project scale: QUICK, SMALL, MEDIUM, LARGE, ENTERPRISE')
736
+ .option('-r, --repo-path <path>', 'Repository path', process.cwd())
737
+ .action(async (name, options) => {
738
+ try {
739
+ const workflowService = new workflow_1.WorkflowService(options.repoPath, getWorkflowDeps());
740
+ const status = await workflowService.init({
741
+ name,
742
+ description: options.description,
743
+ scale: options.scale
744
+ });
745
+ ui.displaySuccess(`Workflow PREVC initialized: ${name}`);
746
+ ui.displayInfo('Scale', (0, workflow_2.getScaleName)(status.project.scale));
747
+ ui.displayInfo('Current Phase', `${status.project.current_phase} - ${workflow_2.PHASE_NAMES_PT[status.project.current_phase]}`);
748
+ }
749
+ catch (error) {
750
+ ui.displayError('Failed to initialize workflow', error);
751
+ process.exit(1);
752
+ }
753
+ });
754
+ workflowCommand
755
+ .command('status')
756
+ .description('Show current workflow status')
757
+ .option('-r, --repo-path <path>', 'Repository path', process.cwd())
758
+ .action(async (options) => {
759
+ try {
760
+ const workflowService = new workflow_1.WorkflowService(options.repoPath, getWorkflowDeps());
761
+ if (!await workflowService.hasWorkflow()) {
762
+ ui.displayError('No workflow found. Run "workflow init <name>" first.');
763
+ process.exit(1);
764
+ }
765
+ const formattedStatus = await workflowService.getFormattedStatus();
766
+ console.log(formattedStatus);
767
+ const actions = await workflowService.getRecommendedActions();
768
+ if (actions.length > 0) {
769
+ console.log('\nRecommended actions:');
770
+ actions.forEach((action, i) => console.log(` ${i + 1}. ${action}`));
771
+ }
772
+ }
773
+ catch (error) {
774
+ ui.displayError('Failed to get workflow status', error);
775
+ process.exit(1);
776
+ }
777
+ });
778
+ workflowCommand
779
+ .command('advance')
780
+ .description('Complete current phase and advance to next')
781
+ .option('-r, --repo-path <path>', 'Repository path', process.cwd())
782
+ .option('-o, --outputs <files...>', 'Output files generated in current phase')
783
+ .action(async (options) => {
784
+ try {
785
+ const workflowService = new workflow_1.WorkflowService(options.repoPath, getWorkflowDeps());
786
+ if (!await workflowService.hasWorkflow()) {
787
+ ui.displayError('No workflow found. Run "workflow init <name>" first.');
788
+ process.exit(1);
789
+ }
790
+ const nextPhase = await workflowService.advance(options.outputs);
791
+ if (nextPhase) {
792
+ ui.displaySuccess(`Advanced to phase: ${nextPhase} - ${workflow_2.PHASE_NAMES_PT[nextPhase]}`);
793
+ }
794
+ else {
795
+ ui.displaySuccess('Workflow completed!');
796
+ }
797
+ }
798
+ catch (error) {
799
+ ui.displayError('Failed to advance workflow', error);
800
+ process.exit(1);
801
+ }
802
+ });
803
+ workflowCommand
804
+ .command('handoff <from> <to>')
805
+ .description('Perform handoff between roles')
806
+ .option('-r, --repo-path <path>', 'Repository path', process.cwd())
807
+ .option('-a, --artifacts <files...>', 'Artifacts to hand off')
808
+ .action(async (from, to, options) => {
809
+ try {
810
+ const workflowService = new workflow_1.WorkflowService(options.repoPath, getWorkflowDeps());
811
+ if (!await workflowService.hasWorkflow()) {
812
+ ui.displayError('No workflow found. Run "workflow init <name>" first.');
813
+ process.exit(1);
814
+ }
815
+ await workflowService.handoff(from, to, options.artifacts || []);
816
+ ui.displaySuccess(`Handoff: ${workflow_2.ROLE_DISPLAY_NAMES[from]} → ${workflow_2.ROLE_DISPLAY_NAMES[to]}`);
817
+ }
818
+ catch (error) {
819
+ ui.displayError('Failed to perform handoff', error);
820
+ process.exit(1);
821
+ }
822
+ });
823
+ workflowCommand
824
+ .command('collaborate <topic>')
825
+ .description('Start a collaboration session between roles')
826
+ .option('-r, --repo-path <path>', 'Repository path', process.cwd())
827
+ .option('-p, --participants <roles...>', 'Participating roles')
828
+ .action(async (topic, options) => {
829
+ try {
830
+ const workflowService = new workflow_1.WorkflowService(options.repoPath, getWorkflowDeps());
831
+ const session = await workflowService.startCollaboration(topic, options.participants);
832
+ ui.displaySuccess(`Collaboration started: ${topic}`);
833
+ ui.displayInfo('Session ID', session.getId());
834
+ ui.displayInfo('Participants', session.getParticipantNames().join(', '));
835
+ console.log('\nUse MCP tools to contribute and synthesize the collaboration.');
836
+ }
837
+ catch (error) {
838
+ ui.displayError('Failed to start collaboration', error);
839
+ process.exit(1);
840
+ }
841
+ });
842
+ workflowCommand
843
+ .command('role <action> <role>')
844
+ .description('Manage role status (start/complete)')
845
+ .option('-r, --repo-path <path>', 'Repository path', process.cwd())
846
+ .option('-o, --outputs <files...>', 'Output files (for complete action)')
847
+ .action(async (action, role, options) => {
848
+ try {
849
+ const workflowService = new workflow_1.WorkflowService(options.repoPath, getWorkflowDeps());
850
+ if (!await workflowService.hasWorkflow()) {
851
+ ui.displayError('No workflow found. Run "workflow init <name>" first.');
852
+ process.exit(1);
853
+ }
854
+ if (action === 'start') {
855
+ await workflowService.startRole(role);
856
+ ui.displaySuccess(`Started role: ${workflow_2.ROLE_DISPLAY_NAMES[role]}`);
857
+ }
858
+ else if (action === 'complete') {
859
+ await workflowService.completeRole(role, options.outputs || []);
860
+ ui.displaySuccess(`Completed role: ${workflow_2.ROLE_DISPLAY_NAMES[role]}`);
861
+ }
862
+ else {
863
+ ui.displayError(`Unknown action: ${action}. Use 'start' or 'complete'.`);
864
+ process.exit(1);
865
+ }
866
+ }
867
+ catch (error) {
868
+ ui.displayError('Failed to manage role', error);
869
+ process.exit(1);
870
+ }
871
+ });
365
872
  async function runInit(repoPath, type, rawOptions) {
366
873
  await initService.run(repoPath, type, rawOptions);
367
874
  }
@@ -409,31 +916,63 @@ async function selectLocale(showWelcome) {
409
916
  translateFn = (0, i18n_1.createTranslator)(normalizedLocale);
410
917
  if (showWelcome) {
411
918
  ui.displayWelcome(version_1.VERSION);
919
+ ui.displayPrevcExplanation();
412
920
  }
413
921
  }
414
922
  async function runInteractive() {
415
- await selectLocale(true);
923
+ await selectLocale(false); // Don't show welcome yet
924
+ // Show welcome screen with PREVC explanation
925
+ ui.displayWelcome(version_1.VERSION);
926
+ ui.displayPrevcExplanation();
927
+ // Wait for user to press Enter
928
+ await inquirer_1.default.prompt([
929
+ {
930
+ type: 'input',
931
+ name: 'continue',
932
+ message: t('prompts.pressEnter'),
933
+ },
934
+ ]);
935
+ console.log('\n');
416
936
  const projectPath = process.cwd();
417
937
  const detector = new state_1.StateDetector({ projectPath });
418
938
  const result = await detector.detect();
419
- // Display project info
939
+ // Get quick stats for compact status
940
+ const quickSyncService = new quickSync_1.QuickSyncService({
941
+ ui,
942
+ t,
943
+ version: version_1.VERSION,
944
+ defaultModel: DEFAULT_MODEL,
945
+ });
946
+ const stats = await quickSyncService.getStats(projectPath);
947
+ // Display compact header
420
948
  console.log('');
421
- ui.displayInfo(`${version_1.PACKAGE_NAME} v${version_1.VERSION}`, `Project: ${projectPath}`);
422
- // Show state-specific information
949
+ console.log(`${theme_1.colors.primaryBold(`${version_1.PACKAGE_NAME}`)} ${theme_1.colors.secondary(`v${version_1.VERSION}`)}`);
950
+ console.log(`${theme_1.colors.secondary('Project:')} ${projectPath}`);
951
+ // Show compact status line based on state
423
952
  switch (result.state) {
424
953
  case 'new':
425
- console.log(theme_1.colors.secondaryDim(' No context documentation found.\n'));
954
+ console.log(theme_1.colors.secondaryDim(t('status.new')));
426
955
  break;
427
956
  case 'unfilled':
428
- console.log(theme_1.colors.secondaryDim(` Context: ${result.details.unfilledFiles} files need filling\n`));
957
+ console.log(theme_1.colors.secondaryDim(t('status.unfilled', { count: result.details.unfilledFiles })));
429
958
  break;
430
959
  case 'outdated':
431
- console.log(theme_1.colors.warning(` Code modified ${result.details.daysBehind} day(s) ago (docs not updated)\n`));
960
+ console.log(theme_1.colors.warning(t('status.outdated', {
961
+ docs: stats.docs,
962
+ days: result.details.daysBehind || 0,
963
+ agents: stats.agents,
964
+ skills: stats.skills
965
+ })));
432
966
  break;
433
967
  case 'ready':
434
- console.log(theme_1.colors.success(` Context: ${result.details.totalFiles} docs, all up to date\n`));
968
+ console.log(theme_1.colors.success(t('status.compact', {
969
+ docs: stats.docs,
970
+ agents: stats.agents,
971
+ skills: stats.skills
972
+ })));
435
973
  break;
436
974
  }
975
+ console.log('');
437
976
  // Handle state-based flow
438
977
  if (result.state === 'new') {
439
978
  const { action } = await inquirer_1.default.prompt([
@@ -442,15 +981,20 @@ async function runInteractive() {
442
981
  name: 'action',
443
982
  message: t('prompts.main.action'),
444
983
  choices: [
445
- { name: t('prompts.main.choice.create'), value: 'create' },
984
+ { name: t('prompts.main.choice.quickSetup'), value: 'create' },
985
+ { name: t('prompts.main.choice.scaffoldOnly'), value: 'scaffold' },
446
986
  { name: t('prompts.main.choice.exit'), value: 'exit' }
447
987
  ]
448
988
  }
449
989
  ]);
450
990
  if (action === 'create') {
451
- // Run init + fill automatically
991
+ // Run init + fill with AI + LSP automatically
452
992
  await runQuickSetup(projectPath);
453
993
  }
994
+ else if (action === 'scaffold') {
995
+ // Scaffold only without AI fill
996
+ await runInteractiveScaffold();
997
+ }
454
998
  return;
455
999
  }
456
1000
  if (result.state === 'unfilled') {
@@ -479,6 +1023,27 @@ async function runInteractive() {
479
1023
  await runFullMenu(result.state === 'outdated' ? result.details.daysBehind : undefined);
480
1024
  }
481
1025
  async function runQuickSetup(projectPath) {
1026
+ // AI-first: Detect smart defaults automatically
1027
+ const defaults = await (0, prompts_1.detectSmartDefaults)();
1028
+ // If no API key found, prompt for one
1029
+ let llmConfig = null;
1030
+ if (defaults.apiKeyConfigured && defaults.provider) {
1031
+ // Auto-detected config
1032
+ llmConfig = {
1033
+ provider: defaults.provider,
1034
+ model: DEFAULT_MODEL,
1035
+ apiKey: (0, providerFactory_1.getApiKeyFromEnv)(defaults.provider),
1036
+ };
1037
+ console.log(theme_1.colors.secondary(` Auto-detected: ${defaults.provider} API key found`));
1038
+ }
1039
+ else {
1040
+ // Need to get API key from user
1041
+ llmConfig = await (0, prompts_1.promptLLMConfig)(t);
1042
+ if (!llmConfig) {
1043
+ ui.displayInfo(t('info.setup.incomplete.title'), t('info.setup.incomplete.detail'));
1044
+ return;
1045
+ }
1046
+ }
482
1047
  const { confirm } = await inquirer_1.default.prompt([
483
1048
  {
484
1049
  type: 'confirm',
@@ -490,11 +1055,11 @@ async function runQuickSetup(projectPath) {
490
1055
  if (!confirm) {
491
1056
  return;
492
1057
  }
493
- // Run init
1058
+ // Run init with semantic analysis
494
1059
  ui.startSpinner(t('spinner.setup.creatingStructure'));
495
1060
  try {
496
- const initService = new initService_1.InitService({ ui, t, version: version_1.VERSION });
497
- await initService.run(projectPath, 'both', {
1061
+ const localInitService = new initService_1.InitService({ ui, t, version: version_1.VERSION });
1062
+ await localInitService.run(projectPath, 'both', {
498
1063
  semantic: true
499
1064
  });
500
1065
  ui.stopSpinner();
@@ -504,22 +1069,27 @@ async function runQuickSetup(projectPath) {
504
1069
  ui.displayError('Failed to create structure', error);
505
1070
  return;
506
1071
  }
507
- // Prompt for LLM config and run fill
508
- const llmConfig = await (0, prompts_1.promptLLMConfig)(t);
509
- if (!llmConfig) {
510
- ui.displayInfo(t('info.setup.incomplete.title'), t('info.setup.incomplete.detail'));
511
- return;
1072
+ // Initialize skills too (AI-first)
1073
+ try {
1074
+ const { createSkillGenerator } = await Promise.resolve().then(() => __importStar(require('./generators/skills')));
1075
+ const skillGenerator = createSkillGenerator({ repoPath: projectPath });
1076
+ await skillGenerator.generate({});
512
1077
  }
1078
+ catch {
1079
+ // Skills init failure is not critical
1080
+ }
1081
+ // Fill with AI + LSP (default behavior)
513
1082
  ui.startSpinner(t('spinner.setup.fillingDocs'));
514
1083
  try {
515
- const fillService = new fillService_1.FillService({ ui, t, version: version_1.VERSION, defaultModel: DEFAULT_MODEL });
516
- await fillService.run(projectPath, {
1084
+ const localFillService = new fillService_1.FillService({ ui, t, version: version_1.VERSION, defaultModel: DEFAULT_MODEL });
1085
+ await localFillService.run(projectPath, {
517
1086
  model: llmConfig.model,
518
1087
  provider: llmConfig.provider,
519
1088
  apiKey: llmConfig.apiKey,
520
1089
  baseUrl: llmConfig.baseUrl,
521
1090
  verbose: false,
522
- semantic: true
1091
+ semantic: true,
1092
+ useLsp: true // LSP enabled by default
523
1093
  });
524
1094
  ui.stopSpinner();
525
1095
  ui.displaySuccess(t('success.setup.docsCreated'));
@@ -536,12 +1106,21 @@ async function runFullMenu(daysBehind) {
536
1106
  const updateLabel = daysBehind
537
1107
  ? t('prompts.main.choice.updateDocsBehind', { daysBehind })
538
1108
  : t('prompts.main.choice.updateDocs');
1109
+ // New menu structure with separators - organized by frequency of use
539
1110
  const choices = [
540
- { name: t('prompts.main.choice.plan'), value: 'plan' },
1111
+ // Quick Actions (most used)
1112
+ { name: t('prompts.main.choice.quickSync'), value: 'quickSync' },
1113
+ { name: t('prompts.main.choice.startWorkflow'), value: 'workflow' },
1114
+ { name: t('prompts.main.choice.createPlan'), value: 'plan' },
1115
+ new inquirer_1.default.Separator(),
1116
+ // Manage
541
1117
  { name: updateLabel, value: 'fill' },
542
- { name: t('prompts.main.choice.syncAgents'), value: 'syncAgents' },
1118
+ { name: t('prompts.main.choice.manageSkills'), value: 'skills' },
1119
+ { name: t('prompts.main.choice.manageAgents'), value: 'agents' },
1120
+ new inquirer_1.default.Separator(),
1121
+ // Config
543
1122
  { name: t('prompts.main.choice.rescaffold'), value: 'scaffold' },
544
- { name: t('prompts.main.choice.changeLanguage'), value: 'changeLanguage' },
1123
+ { name: t('prompts.main.choice.settings'), value: 'settings' },
545
1124
  { name: t('prompts.main.choice.exit'), value: 'exit' }
546
1125
  ];
547
1126
  const { action } = await inquirer_1.default.prompt([
@@ -552,15 +1131,18 @@ async function runFullMenu(daysBehind) {
552
1131
  choices
553
1132
  }
554
1133
  ]);
555
- if (action === 'changeLanguage') {
556
- await selectLocale(true);
1134
+ if (action === 'settings') {
1135
+ await runSettings();
557
1136
  continue;
558
1137
  }
559
1138
  if (action === 'exit') {
560
1139
  exitRequested = true;
561
1140
  break;
562
1141
  }
563
- if (action === 'scaffold') {
1142
+ if (action === 'quickSync') {
1143
+ await runQuickSync();
1144
+ }
1145
+ else if (action === 'scaffold') {
564
1146
  await runInteractiveScaffold();
565
1147
  }
566
1148
  else if (action === 'fill') {
@@ -569,8 +1151,14 @@ async function runFullMenu(daysBehind) {
569
1151
  else if (action === 'plan') {
570
1152
  await runInteractivePlan();
571
1153
  }
572
- else if (action === 'syncAgents') {
573
- await runInteractiveSync();
1154
+ else if (action === 'agents') {
1155
+ await runManageAgents();
1156
+ }
1157
+ else if (action === 'workflow') {
1158
+ await runInteractiveWorkflow();
1159
+ }
1160
+ else if (action === 'skills') {
1161
+ await runInteractiveSkills();
574
1162
  }
575
1163
  ui.displayInfo(t('info.interactive.returning.title'), t('info.interactive.returning.detail'));
576
1164
  }
@@ -595,19 +1183,24 @@ async function runInteractiveScaffold() {
595
1183
  default: defaultOutput
596
1184
  }
597
1185
  ]);
598
- const { scaffoldType } = await inquirer_1.default.prompt([
1186
+ // Multi-select checkbox for scaffold components
1187
+ const { scaffoldComponents } = await inquirer_1.default.prompt([
599
1188
  {
600
- type: 'list',
601
- name: 'scaffoldType',
602
- message: t('prompts.scaffold.type'),
1189
+ type: 'checkbox',
1190
+ name: 'scaffoldComponents',
1191
+ message: t('prompts.scaffold.selectComponents'),
603
1192
  choices: [
604
- { name: t('prompts.scaffold.typeBoth'), value: 'both' },
605
- { name: t('prompts.scaffold.typeDocs'), value: 'docs' },
606
- { name: t('prompts.scaffold.typeAgents'), value: 'agents' }
607
- ],
608
- default: 'both'
1193
+ { name: t('prompts.scaffold.componentDocs'), value: 'docs', checked: true },
1194
+ { name: t('prompts.scaffold.componentAgents'), value: 'agents', checked: true },
1195
+ { name: t('prompts.scaffold.componentSkills'), value: 'skills', checked: false }
1196
+ ]
609
1197
  }
610
1198
  ]);
1199
+ // Validate: at least one component must be selected
1200
+ if (scaffoldComponents.length === 0) {
1201
+ ui.displayWarning(t('warnings.scaffold.noneSelected'));
1202
+ return;
1203
+ }
611
1204
  const { verbose } = await inquirer_1.default.prompt([
612
1205
  {
613
1206
  type: 'confirm',
@@ -616,11 +1209,58 @@ async function runInteractiveScaffold() {
616
1209
  default: false
617
1210
  }
618
1211
  ]);
619
- await runInit(resolvedRepo, scaffoldType, {
620
- output: outputDir,
621
- verbose,
622
- semantic: true
623
- });
1212
+ // Determine what to scaffold
1213
+ const scaffoldDocs = scaffoldComponents.includes('docs');
1214
+ const scaffoldAgents = scaffoldComponents.includes('agents');
1215
+ const scaffoldSkills = scaffoldComponents.includes('skills');
1216
+ // Scaffold docs and/or agents if selected
1217
+ if (scaffoldDocs || scaffoldAgents) {
1218
+ let scaffoldType;
1219
+ if (scaffoldDocs && scaffoldAgents) {
1220
+ scaffoldType = 'both';
1221
+ }
1222
+ else if (scaffoldDocs) {
1223
+ scaffoldType = 'docs';
1224
+ }
1225
+ else {
1226
+ scaffoldType = 'agents';
1227
+ }
1228
+ await runInit(resolvedRepo, scaffoldType, {
1229
+ output: outputDir,
1230
+ verbose,
1231
+ semantic: true
1232
+ });
1233
+ }
1234
+ // Scaffold skills if selected
1235
+ if (scaffoldSkills) {
1236
+ try {
1237
+ const { createSkillGenerator } = await Promise.resolve().then(() => __importStar(require('./generators/skills')));
1238
+ const generator = createSkillGenerator({
1239
+ repoPath: resolvedRepo,
1240
+ outputDir
1241
+ });
1242
+ // Display step for skills scaffolding
1243
+ const stepNumber = (scaffoldDocs || scaffoldAgents) ? 4 : 1;
1244
+ const totalSteps = (scaffoldDocs || scaffoldAgents) ? 4 : 1;
1245
+ ui.displayStep(stepNumber, totalSteps, t('steps.init.skills'));
1246
+ ui.startSpinner(t('spinner.skills.creating'));
1247
+ const result = await generator.generate({});
1248
+ ui.updateSpinner(t('spinner.skills.created', { count: result.generatedSkills.length }), 'success');
1249
+ // If only skills were selected, show success message
1250
+ if (!scaffoldDocs && !scaffoldAgents) {
1251
+ ui.displaySuccess(t('success.skill.initialized', { path: result.skillsDir }));
1252
+ }
1253
+ if (result.generatedSkills.length > 0) {
1254
+ ui.displayInfo(t('info.skill.generated'), result.generatedSkills.join(', '));
1255
+ }
1256
+ if (result.skippedSkills.length > 0) {
1257
+ ui.displayInfo(t('info.skill.skipped'), result.skippedSkills.join(', '));
1258
+ }
1259
+ }
1260
+ catch (error) {
1261
+ ui.displayError(t('errors.skill.initFailed'), error);
1262
+ }
1263
+ }
624
1264
  }
625
1265
  async function runInteractiveLlmFill() {
626
1266
  const defaults = await (0, prompts_1.detectSmartDefaults)();
@@ -1040,6 +1680,638 @@ async function runInteractiveSync() {
1040
1680
  }
1041
1681
  }
1042
1682
  }
1683
+ async function createNewWorkflow(workflowService) {
1684
+ const { name, description, scale } = await inquirer_1.default.prompt([
1685
+ {
1686
+ type: 'input',
1687
+ name: 'name',
1688
+ message: t('prompts.workflow.projectName'),
1689
+ validate: (input) => input.trim().length > 0 || t('prompts.workflow.projectNameRequired')
1690
+ },
1691
+ {
1692
+ type: 'input',
1693
+ name: 'description',
1694
+ message: t('prompts.workflow.description'),
1695
+ default: ''
1696
+ },
1697
+ {
1698
+ type: 'list',
1699
+ name: 'scale',
1700
+ message: t('prompts.workflow.scale'),
1701
+ choices: [
1702
+ { name: t('prompts.workflow.scale.auto'), value: '' },
1703
+ { name: t('prompts.workflow.scale.quick'), value: 'QUICK' },
1704
+ { name: t('prompts.workflow.scale.small'), value: 'SMALL' },
1705
+ { name: t('prompts.workflow.scale.medium'), value: 'MEDIUM' },
1706
+ { name: t('prompts.workflow.scale.large'), value: 'LARGE' },
1707
+ { name: t('prompts.workflow.scale.enterprise'), value: 'ENTERPRISE' }
1708
+ ],
1709
+ default: ''
1710
+ }
1711
+ ]);
1712
+ try {
1713
+ const status = await workflowService.init({
1714
+ name: name.trim(),
1715
+ description: description.trim() || undefined,
1716
+ scale: scale || undefined
1717
+ });
1718
+ ui.displaySuccess(t('success.workflow.initialized', { name }));
1719
+ ui.displayInfo(t('info.workflow.scale'), (0, workflow_2.getScaleName)(status.project.scale));
1720
+ ui.displayInfo(t('info.workflow.currentPhase'), `${status.project.current_phase} - ${workflow_2.PHASE_NAMES_PT[status.project.current_phase]}`);
1721
+ return true;
1722
+ }
1723
+ catch (error) {
1724
+ ui.displayError(t('errors.workflow.initFailed'), error);
1725
+ return false;
1726
+ }
1727
+ }
1728
+ async function runInteractiveWorkflow() {
1729
+ const projectPath = process.cwd();
1730
+ const workflowService = new workflow_1.WorkflowService(projectPath, getWorkflowDeps());
1731
+ const hasWorkflow = await workflowService.hasWorkflow();
1732
+ if (!hasWorkflow) {
1733
+ // No workflow exists - offer to create one
1734
+ const { createNew } = await inquirer_1.default.prompt([
1735
+ {
1736
+ type: 'confirm',
1737
+ name: 'createNew',
1738
+ message: t('prompts.workflow.noWorkflowFound'),
1739
+ default: true
1740
+ }
1741
+ ]);
1742
+ if (!createNew) {
1743
+ return;
1744
+ }
1745
+ await createNewWorkflow(workflowService);
1746
+ return;
1747
+ }
1748
+ // Workflow exists - check if complete
1749
+ const isComplete = await workflowService.isComplete();
1750
+ if (isComplete) {
1751
+ // Workflow is complete - offer to start a new one or view status
1752
+ console.log('');
1753
+ const formattedStatus = await workflowService.getFormattedStatus();
1754
+ console.log(formattedStatus);
1755
+ const { completeAction } = await inquirer_1.default.prompt([
1756
+ {
1757
+ type: 'list',
1758
+ name: 'completeAction',
1759
+ message: t('prompts.workflow.workflowComplete'),
1760
+ choices: [
1761
+ { name: t('prompts.workflow.action.newWorkflow'), value: 'newWorkflow' },
1762
+ { name: t('prompts.workflow.action.viewStatus'), value: 'viewStatus' },
1763
+ { name: t('prompts.workflow.action.back'), value: 'back' }
1764
+ ]
1765
+ }
1766
+ ]);
1767
+ if (completeAction === 'newWorkflow') {
1768
+ const { confirmNew } = await inquirer_1.default.prompt([
1769
+ {
1770
+ type: 'confirm',
1771
+ name: 'confirmNew',
1772
+ message: t('prompts.workflow.confirmNewWorkflow'),
1773
+ default: true
1774
+ }
1775
+ ]);
1776
+ if (confirmNew) {
1777
+ await createNewWorkflow(workflowService);
1778
+ }
1779
+ }
1780
+ // 'viewStatus' and 'back' just return
1781
+ return;
1782
+ }
1783
+ // Workflow exists and is not complete - show status and actions
1784
+ let continueMenu = true;
1785
+ while (continueMenu) {
1786
+ console.log('');
1787
+ const formattedStatus = await workflowService.getFormattedStatus();
1788
+ console.log(formattedStatus);
1789
+ const choices = [];
1790
+ choices.push({ name: t('prompts.workflow.action.advance'), value: 'advance' });
1791
+ choices.push({ name: t('prompts.workflow.action.newWorkflow'), value: 'newWorkflow' });
1792
+ choices.push({ name: t('prompts.workflow.action.refresh'), value: 'status' });
1793
+ choices.push({ name: t('prompts.workflow.action.back'), value: 'back' });
1794
+ const { action } = await inquirer_1.default.prompt([
1795
+ {
1796
+ type: 'list',
1797
+ name: 'action',
1798
+ message: t('prompts.workflow.action'),
1799
+ choices
1800
+ }
1801
+ ]);
1802
+ if (action === 'back') {
1803
+ continueMenu = false;
1804
+ }
1805
+ else if (action === 'newWorkflow') {
1806
+ const { confirmNew } = await inquirer_1.default.prompt([
1807
+ {
1808
+ type: 'confirm',
1809
+ name: 'confirmNew',
1810
+ message: t('prompts.workflow.confirmNewWorkflow'),
1811
+ default: false
1812
+ }
1813
+ ]);
1814
+ if (confirmNew) {
1815
+ const created = await createNewWorkflow(workflowService);
1816
+ if (created) {
1817
+ // Continue with the new workflow
1818
+ continue;
1819
+ }
1820
+ }
1821
+ }
1822
+ else if (action === 'advance') {
1823
+ try {
1824
+ const nextPhase = await workflowService.advance();
1825
+ if (nextPhase) {
1826
+ ui.displaySuccess(t('success.workflow.advanced', { phase: nextPhase, phaseName: workflow_2.PHASE_NAMES_PT[nextPhase] }));
1827
+ }
1828
+ else {
1829
+ ui.displaySuccess(t('success.workflow.completed'));
1830
+ // Workflow completed - ask if they want to start a new one
1831
+ const { startNew } = await inquirer_1.default.prompt([
1832
+ {
1833
+ type: 'confirm',
1834
+ name: 'startNew',
1835
+ message: t('prompts.workflow.noWorkflowFound'),
1836
+ default: true
1837
+ }
1838
+ ]);
1839
+ if (startNew) {
1840
+ await createNewWorkflow(workflowService);
1841
+ }
1842
+ continueMenu = false;
1843
+ }
1844
+ }
1845
+ catch (error) {
1846
+ ui.displayError(t('errors.workflow.advanceFailed'), error);
1847
+ }
1848
+ }
1849
+ // 'status' just loops and refreshes
1850
+ }
1851
+ }
1852
+ async function runInteractiveSkills() {
1853
+ const projectPath = process.cwd();
1854
+ let continueMenu = true;
1855
+ while (continueMenu) {
1856
+ const { action } = await inquirer_1.default.prompt([
1857
+ {
1858
+ type: 'list',
1859
+ name: 'action',
1860
+ message: t('prompts.skill.action'),
1861
+ choices: [
1862
+ { name: t('prompts.skill.action.init'), value: 'init' },
1863
+ { name: t('prompts.skill.action.list'), value: 'list' },
1864
+ { name: t('prompts.skill.action.export'), value: 'export' },
1865
+ { name: t('prompts.skill.action.create'), value: 'create' },
1866
+ { name: t('prompts.skill.action.back'), value: 'back' }
1867
+ ]
1868
+ }
1869
+ ]);
1870
+ if (action === 'back') {
1871
+ continueMenu = false;
1872
+ break;
1873
+ }
1874
+ if (action === 'init') {
1875
+ try {
1876
+ const { createSkillGenerator } = await Promise.resolve().then(() => __importStar(require('./generators/skills')));
1877
+ const generator = createSkillGenerator({ repoPath: projectPath });
1878
+ const result = await generator.generate({});
1879
+ ui.displaySuccess(t('success.skill.initialized', { path: result.skillsDir }));
1880
+ ui.displayInfo(t('info.skill.generated'), result.generatedSkills.join(', ') || 'none');
1881
+ if (result.skippedSkills.length > 0) {
1882
+ ui.displayInfo(t('info.skill.skipped'), result.skippedSkills.join(', '));
1883
+ }
1884
+ }
1885
+ catch (error) {
1886
+ ui.displayError(t('errors.skill.initFailed'), error);
1887
+ }
1888
+ }
1889
+ else if (action === 'list') {
1890
+ try {
1891
+ const { createSkillRegistry, BUILT_IN_SKILLS } = await Promise.resolve().then(() => __importStar(require('./workflow/skills')));
1892
+ const registry = createSkillRegistry(projectPath);
1893
+ const discovered = await registry.discoverAll();
1894
+ console.log('\nBuilt-in Skills:');
1895
+ for (const skill of discovered.builtIn) {
1896
+ const scaffolded = discovered.all.find(s => s.slug === skill.slug && s.path.includes('.context'));
1897
+ const status = scaffolded ? '[scaffolded]' : '[available]';
1898
+ console.log(` ${skill.slug} ${status}`);
1899
+ console.log(` ${skill.metadata.description}`);
1900
+ }
1901
+ if (discovered.custom.length > 0) {
1902
+ console.log('\nCustom Skills:');
1903
+ for (const skill of discovered.custom) {
1904
+ console.log(` ${skill.slug}`);
1905
+ console.log(` ${skill.metadata.description}`);
1906
+ }
1907
+ }
1908
+ console.log(`\nTotal: ${discovered.all.length} skills (${discovered.builtIn.length} built-in, ${discovered.custom.length} custom)\n`);
1909
+ }
1910
+ catch (error) {
1911
+ ui.displayError(t('errors.skill.listFailed'), error);
1912
+ }
1913
+ }
1914
+ else if (action === 'export') {
1915
+ try {
1916
+ const { preset } = await inquirer_1.default.prompt([
1917
+ {
1918
+ type: 'list',
1919
+ name: 'preset',
1920
+ message: t('prompts.skill.exportPreset'),
1921
+ choices: [
1922
+ { name: t('prompts.skill.exportPreset.all'), value: 'all' },
1923
+ { name: t('prompts.skill.exportPreset.claude'), value: 'claude' },
1924
+ { name: t('prompts.skill.exportPreset.gemini'), value: 'gemini' },
1925
+ { name: t('prompts.skill.exportPreset.codex'), value: 'codex' }
1926
+ ],
1927
+ default: 'all'
1928
+ }
1929
+ ]);
1930
+ const { SkillExportService } = await Promise.resolve().then(() => __importStar(require('./services/export/skillExportService')));
1931
+ const exportService = new SkillExportService({
1932
+ ui,
1933
+ t,
1934
+ version: version_1.VERSION,
1935
+ });
1936
+ const result = await exportService.run(projectPath, {
1937
+ preset,
1938
+ includeBuiltIn: true,
1939
+ });
1940
+ ui.displaySuccess(t('success.skill.exported', {
1941
+ count: String(result.skillsExported.length),
1942
+ targets: String(result.targets.length)
1943
+ }));
1944
+ }
1945
+ catch (error) {
1946
+ ui.displayError(t('errors.skill.exportFailed'), error);
1947
+ }
1948
+ }
1949
+ else if (action === 'create') {
1950
+ try {
1951
+ const { name, description, phases } = await inquirer_1.default.prompt([
1952
+ {
1953
+ type: 'input',
1954
+ name: 'name',
1955
+ message: t('prompts.skill.name'),
1956
+ validate: (input) => input.trim().length > 0 || 'Name is required'
1957
+ },
1958
+ {
1959
+ type: 'input',
1960
+ name: 'description',
1961
+ message: t('prompts.skill.description'),
1962
+ default: ''
1963
+ },
1964
+ {
1965
+ type: 'input',
1966
+ name: 'phases',
1967
+ message: t('prompts.skill.phases'),
1968
+ default: 'E,V' // Default to Execution + Validation
1969
+ }
1970
+ ]);
1971
+ const phaseArray = phases.split(',').map(p => p.trim().toUpperCase()).filter(p => ['P', 'R', 'E', 'V', 'C'].includes(p));
1972
+ ui.startSpinner('Creating skill...');
1973
+ const { createSkillGenerator } = await Promise.resolve().then(() => __importStar(require('./generators/skills')));
1974
+ const generator = createSkillGenerator({ repoPath: projectPath });
1975
+ const skillPath = await generator.generateCustomSkill({
1976
+ name: name.trim(),
1977
+ description: description.trim() || `TODO: Describe when to use ${name}`,
1978
+ phases: phaseArray,
1979
+ });
1980
+ // AI-first: Try to fill skill with AI + LSP
1981
+ const defaults = await (0, prompts_1.detectSmartDefaults)();
1982
+ if (defaults.apiKeyConfigured && defaults.provider) {
1983
+ ui.updateSpinner('Enhancing skill with AI...', 'info');
1984
+ try {
1985
+ const { SkillFillService } = await Promise.resolve().then(() => __importStar(require('./services/fill/skillFillService')));
1986
+ const skillFillService = new SkillFillService({ ui, t, version: version_1.VERSION, defaultModel: DEFAULT_MODEL });
1987
+ await skillFillService.run(projectPath, {
1988
+ provider: defaults.provider,
1989
+ model: DEFAULT_MODEL,
1990
+ apiKey: (0, providerFactory_1.getApiKeyFromEnv)(defaults.provider),
1991
+ skills: [name.trim()],
1992
+ semantic: true,
1993
+ useLsp: true,
1994
+ });
1995
+ }
1996
+ catch {
1997
+ // Fill failure is not critical - template is already created
1998
+ }
1999
+ }
2000
+ ui.updateSpinner('Skill created', 'success');
2001
+ ui.stopSpinner();
2002
+ ui.displaySuccess(t('success.skill.created', { name }));
2003
+ ui.displayInfo(t('info.skill.path'), skillPath);
2004
+ }
2005
+ catch (error) {
2006
+ ui.stopSpinner();
2007
+ ui.displayError(t('errors.skill.createFailed'), error);
2008
+ }
2009
+ }
2010
+ }
2011
+ }
2012
+ // ============================================================================
2013
+ // Quick Sync - Unified sync for agents, skills, and docs
2014
+ // ============================================================================
2015
+ async function runQuickSync() {
2016
+ const projectPath = process.cwd();
2017
+ // Step 1: Select components to sync
2018
+ const { components } = await inquirer_1.default.prompt([
2019
+ {
2020
+ type: 'checkbox',
2021
+ name: 'components',
2022
+ message: t('prompts.quickSync.selectComponents'),
2023
+ choices: [
2024
+ { name: t('prompts.quickSync.components.agents'), value: 'agents', checked: true },
2025
+ { name: t('prompts.quickSync.components.skills'), value: 'skills', checked: true },
2026
+ { name: t('prompts.quickSync.components.docs'), value: 'docs', checked: true },
2027
+ ],
2028
+ },
2029
+ ]);
2030
+ if (components.length === 0) {
2031
+ ui.displayWarning(t('prompts.quickSync.noComponentsSelected'));
2032
+ return;
2033
+ }
2034
+ let agentTargets;
2035
+ let skillTargets;
2036
+ let docTargets;
2037
+ // Step 2: If agents selected, choose targets
2038
+ if (components.includes('agents')) {
2039
+ const { targets } = await inquirer_1.default.prompt([
2040
+ {
2041
+ type: 'checkbox',
2042
+ name: 'targets',
2043
+ message: t('prompts.quickSync.selectAgentTargets'),
2044
+ choices: [
2045
+ { name: '.claude/agents (Claude Code)', value: 'claude', checked: true },
2046
+ { name: '.github/agents (GitHub Copilot)', value: 'github', checked: true },
2047
+ { name: '.cursor/agents (Cursor AI)', value: 'cursor', checked: false },
2048
+ { name: '.windsurf/agents (Windsurf/Codeium)', value: 'windsurf', checked: false },
2049
+ { name: '.cline/agents (Cline)', value: 'cline', checked: false },
2050
+ { name: '.continue/agents (Continue.dev)', value: 'continue', checked: false },
2051
+ ],
2052
+ },
2053
+ ]);
2054
+ agentTargets = targets.length > 0 ? targets : undefined;
2055
+ }
2056
+ // Step 3: If skills selected, choose targets
2057
+ if (components.includes('skills')) {
2058
+ const { targets } = await inquirer_1.default.prompt([
2059
+ {
2060
+ type: 'checkbox',
2061
+ name: 'targets',
2062
+ message: t('prompts.quickSync.selectSkillTargets'),
2063
+ choices: [
2064
+ { name: '.claude/skills (Claude Code)', value: 'claude', checked: true },
2065
+ { name: '.gemini/skills (Gemini CLI)', value: 'gemini', checked: true },
2066
+ { name: '.codex/skills (Codex CLI)', value: 'codex', checked: true },
2067
+ ],
2068
+ },
2069
+ ]);
2070
+ skillTargets = targets.length > 0 ? targets : undefined;
2071
+ }
2072
+ // Step 4: If docs selected, choose targets
2073
+ if (components.includes('docs')) {
2074
+ const { targets } = await inquirer_1.default.prompt([
2075
+ {
2076
+ type: 'checkbox',
2077
+ name: 'targets',
2078
+ message: t('prompts.quickSync.selectDocTargets'),
2079
+ choices: [
2080
+ { name: '.cursorrules (Cursor AI)', value: 'cursor', checked: true },
2081
+ { name: 'CLAUDE.md (Claude Code)', value: 'claude', checked: true },
2082
+ { name: 'AGENTS.md (Universal)', value: 'agents', checked: true },
2083
+ { name: '.windsurfrules (Windsurf)', value: 'windsurf', checked: false },
2084
+ { name: '.clinerules (Cline)', value: 'cline', checked: false },
2085
+ { name: 'CONVENTIONS.md (Aider)', value: 'aider', checked: false },
2086
+ ],
2087
+ },
2088
+ ]);
2089
+ docTargets = targets.length > 0 ? targets : undefined;
2090
+ }
2091
+ // Build options based on selections
2092
+ const options = {
2093
+ skipAgents: !components.includes('agents'),
2094
+ skipSkills: !components.includes('skills'),
2095
+ skipDocs: !components.includes('docs'),
2096
+ agentTargets,
2097
+ skillTargets,
2098
+ docTargets,
2099
+ force: false,
2100
+ dryRun: false,
2101
+ verbose: false,
2102
+ };
2103
+ const quickSyncService = new quickSync_1.QuickSyncService({
2104
+ ui,
2105
+ t,
2106
+ version: version_1.VERSION,
2107
+ defaultModel: DEFAULT_MODEL,
2108
+ });
2109
+ const result = await quickSyncService.run(projectPath, options);
2110
+ // If docs are outdated, ask if user wants to update
2111
+ if (!result.docsUpdated) {
2112
+ const stats = await quickSyncService.getStats(projectPath);
2113
+ if (stats.daysOld) {
2114
+ const { updateDocs } = await inquirer_1.default.prompt([
2115
+ {
2116
+ type: 'confirm',
2117
+ name: 'updateDocs',
2118
+ message: t('prompts.quickSync.updateDocs'),
2119
+ default: true,
2120
+ },
2121
+ ]);
2122
+ if (updateDocs) {
2123
+ // Trigger fill with AI + LSP
2124
+ await runInteractiveLlmFill();
2125
+ }
2126
+ }
2127
+ }
2128
+ ui.displaySuccess(t('success.quickSync.complete'));
2129
+ }
2130
+ async function runManageAgents() {
2131
+ const projectPath = process.cwd();
2132
+ let continueMenu = true;
2133
+ while (continueMenu) {
2134
+ const { action } = await inquirer_1.default.prompt([
2135
+ {
2136
+ type: 'list',
2137
+ name: 'action',
2138
+ message: t('prompts.agents.action'),
2139
+ choices: [
2140
+ { name: t('prompts.agents.choice.sync'), value: 'sync' },
2141
+ { name: t('prompts.agents.choice.create'), value: 'create' },
2142
+ { name: t('prompts.agents.choice.list'), value: 'list' },
2143
+ { name: t('prompts.agents.choice.back'), value: 'back' },
2144
+ ],
2145
+ },
2146
+ ]);
2147
+ if (action === 'back') {
2148
+ continueMenu = false;
2149
+ break;
2150
+ }
2151
+ if (action === 'sync') {
2152
+ await runInteractiveSync();
2153
+ }
2154
+ else if (action === 'list') {
2155
+ await listAgents(projectPath);
2156
+ }
2157
+ else if (action === 'create') {
2158
+ await createCustomAgent(projectPath);
2159
+ }
2160
+ }
2161
+ }
2162
+ async function listAgents(projectPath) {
2163
+ const agentsPath = path.join(projectPath, '.context', 'agents');
2164
+ const fs = await Promise.resolve().then(() => __importStar(require('fs-extra')));
2165
+ if (!(await fs.pathExists(agentsPath))) {
2166
+ ui.displayWarning('No agents directory found. Run scaffold first.');
2167
+ return;
2168
+ }
2169
+ const files = await fs.readdir(agentsPath);
2170
+ const agents = files.filter(f => f.endsWith('.md') && f !== 'README.md');
2171
+ console.log('\nAgents:');
2172
+ for (const agent of agents) {
2173
+ const name = agent.replace('.md', '');
2174
+ console.log(` ${theme_1.colors.primary(name)}`);
2175
+ }
2176
+ console.log(`\nTotal: ${agents.length} agents\n`);
2177
+ }
2178
+ async function createCustomAgent(projectPath) {
2179
+ const { name, description, role } = await inquirer_1.default.prompt([
2180
+ {
2181
+ type: 'input',
2182
+ name: 'name',
2183
+ message: t('prompts.agent.name'),
2184
+ validate: (input) => input.trim().length > 0 || 'Name is required',
2185
+ },
2186
+ {
2187
+ type: 'input',
2188
+ name: 'description',
2189
+ message: t('prompts.agent.description'),
2190
+ },
2191
+ {
2192
+ type: 'list',
2193
+ name: 'role',
2194
+ message: t('prompts.agent.role'),
2195
+ choices: [
2196
+ { name: 'Code Reviewer', value: 'code-reviewer' },
2197
+ { name: 'Bug Fixer', value: 'bug-fixer' },
2198
+ { name: 'Feature Developer', value: 'feature-developer' },
2199
+ { name: 'Test Writer', value: 'test-writer' },
2200
+ { name: 'Documentation Writer', value: 'documentation-writer' },
2201
+ { name: 'Security Auditor', value: 'security-auditor' },
2202
+ { name: 'Performance Optimizer', value: 'performance-optimizer' },
2203
+ { name: 'Custom...', value: 'custom' },
2204
+ ],
2205
+ },
2206
+ ]);
2207
+ let finalRole = role;
2208
+ if (role === 'custom') {
2209
+ const { customRole } = await inquirer_1.default.prompt([
2210
+ {
2211
+ type: 'input',
2212
+ name: 'customRole',
2213
+ message: 'Enter custom role:',
2214
+ validate: (input) => input.trim().length > 0 || 'Role is required',
2215
+ },
2216
+ ]);
2217
+ finalRole = customRole.trim();
2218
+ }
2219
+ ui.startSpinner(t('spinner.agent.creating'));
2220
+ try {
2221
+ const fs = await Promise.resolve().then(() => __importStar(require('fs-extra')));
2222
+ const agentsDir = path.join(projectPath, '.context', 'agents');
2223
+ await fs.ensureDir(agentsDir);
2224
+ const slug = name.trim().toLowerCase().replace(/\s+/g, '-');
2225
+ const agentPath = path.join(agentsDir, `${slug}.md`);
2226
+ // Generate template content
2227
+ const template = `---
2228
+ name: ${name.trim()}
2229
+ description: ${description.trim() || `Custom agent: ${name.trim()}`}
2230
+ role: ${finalRole}
2231
+ custom: true
2232
+ ---
2233
+
2234
+ # ${name.trim()} Agent
2235
+
2236
+ ## Role
2237
+ ${description.trim() || `Custom agent specialized in ${finalRole}`}
2238
+
2239
+ ## Responsibilities
2240
+ - Review and analyze code related to ${finalRole}
2241
+ - Provide recommendations based on best practices
2242
+ - Help maintain code quality and standards
2243
+
2244
+ ## Guidelines
2245
+ - Follow project conventions and patterns
2246
+ - Consider performance and maintainability
2247
+ - Document decisions and rationale
2248
+
2249
+ ## Context
2250
+ This agent should be invoked when working on tasks related to ${finalRole}.
2251
+ `;
2252
+ // Write the agent file
2253
+ await fs.writeFile(agentPath, template, 'utf-8');
2254
+ // Try to fill with AI if API key is available
2255
+ const defaults = await (0, prompts_1.detectSmartDefaults)();
2256
+ if (defaults.apiKeyConfigured && defaults.provider) {
2257
+ ui.updateSpinner('Enhancing agent with AI...', 'info');
2258
+ try {
2259
+ // Run fill on just this agent
2260
+ const singleFillService = new fillService_1.FillService({
2261
+ ui,
2262
+ t,
2263
+ version: version_1.VERSION,
2264
+ defaultModel: DEFAULT_MODEL,
2265
+ });
2266
+ await singleFillService.run(projectPath, {
2267
+ model: DEFAULT_MODEL,
2268
+ provider: defaults.provider,
2269
+ apiKey: (0, providerFactory_1.getApiKeyFromEnv)(defaults.provider),
2270
+ verbose: false,
2271
+ semantic: true,
2272
+ useLsp: true,
2273
+ limit: 1,
2274
+ include: [agentPath],
2275
+ });
2276
+ }
2277
+ catch {
2278
+ // Ignore fill errors - template is already saved
2279
+ }
2280
+ }
2281
+ ui.updateSpinner(t('spinner.agent.created'), 'success');
2282
+ ui.stopSpinner();
2283
+ ui.displaySuccess(t('success.agent.created', { name: name.trim() }));
2284
+ console.log(` Path: ${agentPath}\n`);
2285
+ }
2286
+ catch (error) {
2287
+ ui.updateSpinner('Failed to create agent', 'fail');
2288
+ ui.stopSpinner();
2289
+ ui.displayError('Failed to create agent', error);
2290
+ }
2291
+ }
2292
+ async function runSettings() {
2293
+ let continueMenu = true;
2294
+ while (continueMenu) {
2295
+ const { action } = await inquirer_1.default.prompt([
2296
+ {
2297
+ type: 'list',
2298
+ name: 'action',
2299
+ message: t('prompts.settings.action'),
2300
+ choices: [
2301
+ { name: t('prompts.settings.choice.language'), value: 'language' },
2302
+ { name: t('prompts.settings.choice.back'), value: 'back' },
2303
+ ],
2304
+ },
2305
+ ]);
2306
+ if (action === 'back') {
2307
+ continueMenu = false;
2308
+ break;
2309
+ }
2310
+ if (action === 'language') {
2311
+ await selectLocale(true);
2312
+ }
2313
+ }
2314
+ }
1043
2315
  function filterOutLocaleArgs(args) {
1044
2316
  const filtered = [];
1045
2317
  for (let index = 0; index < args.length; index += 1) {