@agile-vibe-coding/avc 0.1.0 → 0.2.3

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 (290) hide show
  1. package/README.md +2 -0
  2. package/cli/agent-loader.js +21 -0
  3. package/cli/agents/agent-selector.md +129 -0
  4. package/cli/agents/architecture-recommender.md +418 -0
  5. package/cli/agents/database-deep-dive.md +470 -0
  6. package/cli/agents/database-recommender.md +634 -0
  7. package/cli/agents/doc-distributor.md +176 -0
  8. package/cli/agents/documentation-updater.md +203 -0
  9. package/cli/agents/epic-story-decomposer.md +280 -0
  10. package/cli/agents/feature-context-generator.md +91 -0
  11. package/cli/agents/gap-checker-epic.md +52 -0
  12. package/cli/agents/impact-checker-story.md +51 -0
  13. package/cli/agents/migration-guide-generator.md +305 -0
  14. package/cli/agents/mission-scope-generator.md +79 -0
  15. package/cli/agents/mission-scope-validator.md +112 -0
  16. package/cli/agents/project-context-extractor.md +107 -0
  17. package/cli/agents/project-documentation-creator.json +226 -0
  18. package/cli/agents/project-documentation-creator.md +595 -0
  19. package/cli/agents/question-prefiller.md +269 -0
  20. package/cli/agents/refiner-epic.md +39 -0
  21. package/cli/agents/refiner-story.md +42 -0
  22. package/cli/agents/solver-epic-api.json +15 -0
  23. package/cli/agents/solver-epic-api.md +39 -0
  24. package/cli/agents/solver-epic-backend.json +15 -0
  25. package/cli/agents/solver-epic-backend.md +39 -0
  26. package/cli/agents/solver-epic-cloud.json +15 -0
  27. package/cli/agents/solver-epic-cloud.md +39 -0
  28. package/cli/agents/solver-epic-data.json +15 -0
  29. package/cli/agents/solver-epic-data.md +39 -0
  30. package/cli/agents/solver-epic-database.json +15 -0
  31. package/cli/agents/solver-epic-database.md +39 -0
  32. package/cli/agents/solver-epic-developer.json +15 -0
  33. package/cli/agents/solver-epic-developer.md +39 -0
  34. package/cli/agents/solver-epic-devops.json +15 -0
  35. package/cli/agents/solver-epic-devops.md +39 -0
  36. package/cli/agents/solver-epic-frontend.json +15 -0
  37. package/cli/agents/solver-epic-frontend.md +39 -0
  38. package/cli/agents/solver-epic-mobile.json +15 -0
  39. package/cli/agents/solver-epic-mobile.md +39 -0
  40. package/cli/agents/solver-epic-qa.json +15 -0
  41. package/cli/agents/solver-epic-qa.md +39 -0
  42. package/cli/agents/solver-epic-security.json +15 -0
  43. package/cli/agents/solver-epic-security.md +39 -0
  44. package/cli/agents/solver-epic-solution-architect.json +15 -0
  45. package/cli/agents/solver-epic-solution-architect.md +39 -0
  46. package/cli/agents/solver-epic-test-architect.json +15 -0
  47. package/cli/agents/solver-epic-test-architect.md +39 -0
  48. package/cli/agents/solver-epic-ui.json +15 -0
  49. package/cli/agents/solver-epic-ui.md +39 -0
  50. package/cli/agents/solver-epic-ux.json +15 -0
  51. package/cli/agents/solver-epic-ux.md +39 -0
  52. package/cli/agents/solver-story-api.json +15 -0
  53. package/cli/agents/solver-story-api.md +39 -0
  54. package/cli/agents/solver-story-backend.json +15 -0
  55. package/cli/agents/solver-story-backend.md +39 -0
  56. package/cli/agents/solver-story-cloud.json +15 -0
  57. package/cli/agents/solver-story-cloud.md +39 -0
  58. package/cli/agents/solver-story-data.json +15 -0
  59. package/cli/agents/solver-story-data.md +39 -0
  60. package/cli/agents/solver-story-database.json +15 -0
  61. package/cli/agents/solver-story-database.md +39 -0
  62. package/cli/agents/solver-story-developer.json +15 -0
  63. package/cli/agents/solver-story-developer.md +39 -0
  64. package/cli/agents/solver-story-devops.json +15 -0
  65. package/cli/agents/solver-story-devops.md +39 -0
  66. package/cli/agents/solver-story-frontend.json +15 -0
  67. package/cli/agents/solver-story-frontend.md +39 -0
  68. package/cli/agents/solver-story-mobile.json +15 -0
  69. package/cli/agents/solver-story-mobile.md +39 -0
  70. package/cli/agents/solver-story-qa.json +15 -0
  71. package/cli/agents/solver-story-qa.md +39 -0
  72. package/cli/agents/solver-story-security.json +15 -0
  73. package/cli/agents/solver-story-security.md +39 -0
  74. package/cli/agents/solver-story-solution-architect.json +15 -0
  75. package/cli/agents/solver-story-solution-architect.md +39 -0
  76. package/cli/agents/solver-story-test-architect.json +15 -0
  77. package/cli/agents/solver-story-test-architect.md +39 -0
  78. package/cli/agents/solver-story-ui.json +15 -0
  79. package/cli/agents/solver-story-ui.md +39 -0
  80. package/cli/agents/solver-story-ux.json +15 -0
  81. package/cli/agents/solver-story-ux.md +39 -0
  82. package/cli/agents/story-doc-enricher.md +133 -0
  83. package/cli/agents/suggestion-business-analyst.md +88 -0
  84. package/cli/agents/suggestion-deployment-architect.md +263 -0
  85. package/cli/agents/suggestion-product-manager.md +129 -0
  86. package/cli/agents/suggestion-security-specialist.md +156 -0
  87. package/cli/agents/suggestion-technical-architect.md +269 -0
  88. package/cli/agents/suggestion-ux-researcher.md +93 -0
  89. package/cli/agents/task-subtask-decomposer.md +188 -0
  90. package/cli/agents/validator-documentation.json +152 -0
  91. package/cli/agents/validator-documentation.md +453 -0
  92. package/cli/agents/validator-epic-api.json +93 -0
  93. package/cli/agents/validator-epic-api.md +137 -0
  94. package/cli/agents/validator-epic-backend.json +93 -0
  95. package/cli/agents/validator-epic-backend.md +130 -0
  96. package/cli/agents/validator-epic-cloud.json +93 -0
  97. package/cli/agents/validator-epic-cloud.md +137 -0
  98. package/cli/agents/validator-epic-data.json +93 -0
  99. package/cli/agents/validator-epic-data.md +130 -0
  100. package/cli/agents/validator-epic-database.json +93 -0
  101. package/cli/agents/validator-epic-database.md +137 -0
  102. package/cli/agents/validator-epic-developer.json +74 -0
  103. package/cli/agents/validator-epic-developer.md +153 -0
  104. package/cli/agents/validator-epic-devops.json +74 -0
  105. package/cli/agents/validator-epic-devops.md +153 -0
  106. package/cli/agents/validator-epic-frontend.json +74 -0
  107. package/cli/agents/validator-epic-frontend.md +153 -0
  108. package/cli/agents/validator-epic-mobile.json +93 -0
  109. package/cli/agents/validator-epic-mobile.md +130 -0
  110. package/cli/agents/validator-epic-qa.json +93 -0
  111. package/cli/agents/validator-epic-qa.md +130 -0
  112. package/cli/agents/validator-epic-security.json +74 -0
  113. package/cli/agents/validator-epic-security.md +154 -0
  114. package/cli/agents/validator-epic-solution-architect.json +74 -0
  115. package/cli/agents/validator-epic-solution-architect.md +156 -0
  116. package/cli/agents/validator-epic-test-architect.json +93 -0
  117. package/cli/agents/validator-epic-test-architect.md +130 -0
  118. package/cli/agents/validator-epic-ui.json +93 -0
  119. package/cli/agents/validator-epic-ui.md +130 -0
  120. package/cli/agents/validator-epic-ux.json +93 -0
  121. package/cli/agents/validator-epic-ux.md +130 -0
  122. package/cli/agents/validator-selector.md +211 -0
  123. package/cli/agents/validator-story-api.json +104 -0
  124. package/cli/agents/validator-story-api.md +152 -0
  125. package/cli/agents/validator-story-backend.json +104 -0
  126. package/cli/agents/validator-story-backend.md +152 -0
  127. package/cli/agents/validator-story-cloud.json +104 -0
  128. package/cli/agents/validator-story-cloud.md +152 -0
  129. package/cli/agents/validator-story-data.json +104 -0
  130. package/cli/agents/validator-story-data.md +152 -0
  131. package/cli/agents/validator-story-database.json +104 -0
  132. package/cli/agents/validator-story-database.md +152 -0
  133. package/cli/agents/validator-story-developer.json +104 -0
  134. package/cli/agents/validator-story-developer.md +152 -0
  135. package/cli/agents/validator-story-devops.json +104 -0
  136. package/cli/agents/validator-story-devops.md +152 -0
  137. package/cli/agents/validator-story-frontend.json +104 -0
  138. package/cli/agents/validator-story-frontend.md +152 -0
  139. package/cli/agents/validator-story-mobile.json +104 -0
  140. package/cli/agents/validator-story-mobile.md +152 -0
  141. package/cli/agents/validator-story-qa.json +104 -0
  142. package/cli/agents/validator-story-qa.md +152 -0
  143. package/cli/agents/validator-story-security.json +104 -0
  144. package/cli/agents/validator-story-security.md +152 -0
  145. package/cli/agents/validator-story-solution-architect.json +104 -0
  146. package/cli/agents/validator-story-solution-architect.md +152 -0
  147. package/cli/agents/validator-story-test-architect.json +104 -0
  148. package/cli/agents/validator-story-test-architect.md +152 -0
  149. package/cli/agents/validator-story-ui.json +104 -0
  150. package/cli/agents/validator-story-ui.md +152 -0
  151. package/cli/agents/validator-story-ux.json +104 -0
  152. package/cli/agents/validator-story-ux.md +152 -0
  153. package/cli/ansi-colors.js +21 -0
  154. package/cli/build-docs.js +298 -0
  155. package/cli/ceremony-history.js +369 -0
  156. package/cli/command-logger.js +245 -0
  157. package/cli/components/static-output.js +63 -0
  158. package/cli/console-output-manager.js +94 -0
  159. package/cli/docs-sync.js +306 -0
  160. package/cli/epic-story-validator.js +1174 -0
  161. package/cli/evaluation-prompts.js +1008 -0
  162. package/cli/execution-context.js +195 -0
  163. package/cli/generate-summary-table.js +340 -0
  164. package/cli/index.js +3 -25
  165. package/cli/init-model-config.js +697 -0
  166. package/cli/init.js +1765 -100
  167. package/cli/kanban-server-manager.js +228 -0
  168. package/cli/llm-claude.js +109 -0
  169. package/cli/llm-gemini.js +115 -0
  170. package/cli/llm-mock.js +233 -0
  171. package/cli/llm-openai.js +233 -0
  172. package/cli/llm-provider.js +300 -0
  173. package/cli/llm-token-limits.js +102 -0
  174. package/cli/llm-verifier.js +454 -0
  175. package/cli/logger.js +32 -5
  176. package/cli/message-constants.js +58 -0
  177. package/cli/message-manager.js +334 -0
  178. package/cli/message-types.js +96 -0
  179. package/cli/messaging-api.js +297 -0
  180. package/cli/model-pricing.js +169 -0
  181. package/cli/model-query-engine.js +468 -0
  182. package/cli/model-recommendation-analyzer.js +495 -0
  183. package/cli/model-selector.js +269 -0
  184. package/cli/output-buffer.js +107 -0
  185. package/cli/process-manager.js +332 -0
  186. package/cli/repl-ink.js +5840 -504
  187. package/cli/repl-old.js +4 -4
  188. package/cli/seed-processor.js +792 -0
  189. package/cli/sprint-planning-processor.js +1813 -0
  190. package/cli/template-processor.js +2306 -108
  191. package/cli/templates/project.md +25 -8
  192. package/cli/templates/vitepress-config.mts.template +34 -0
  193. package/cli/token-tracker.js +520 -0
  194. package/cli/tools/generate-story-validators.js +317 -0
  195. package/cli/tools/generate-validators.js +669 -0
  196. package/cli/update-checker.js +19 -17
  197. package/cli/update-notifier.js +4 -4
  198. package/cli/validation-router.js +605 -0
  199. package/cli/verification-tracker.js +563 -0
  200. package/kanban/README.md +386 -0
  201. package/kanban/client/README.md +205 -0
  202. package/kanban/client/components.json +20 -0
  203. package/kanban/client/dist/assets/index-CiD8PS2e.js +306 -0
  204. package/kanban/client/dist/assets/index-nLh0m82Q.css +1 -0
  205. package/kanban/client/dist/index.html +16 -0
  206. package/kanban/client/dist/vite.svg +1 -0
  207. package/kanban/client/index.html +15 -0
  208. package/kanban/client/package-lock.json +9442 -0
  209. package/kanban/client/package.json +44 -0
  210. package/kanban/client/postcss.config.js +6 -0
  211. package/kanban/client/public/vite.svg +1 -0
  212. package/kanban/client/src/App.jsx +622 -0
  213. package/kanban/client/src/components/ProjectFileEditorPopup.jsx +117 -0
  214. package/kanban/client/src/components/ceremony/AskArchPopup.jsx +416 -0
  215. package/kanban/client/src/components/ceremony/AskModelPopup.jsx +616 -0
  216. package/kanban/client/src/components/ceremony/CeremonyWorkflowModal.jsx +946 -0
  217. package/kanban/client/src/components/ceremony/EpicStorySelectionModal.jsx +254 -0
  218. package/kanban/client/src/components/ceremony/SponsorCallModal.jsx +619 -0
  219. package/kanban/client/src/components/ceremony/SprintPlanningModal.jsx +704 -0
  220. package/kanban/client/src/components/ceremony/steps/ArchitectureStep.jsx +150 -0
  221. package/kanban/client/src/components/ceremony/steps/CompleteStep.jsx +154 -0
  222. package/kanban/client/src/components/ceremony/steps/DatabaseStep.jsx +202 -0
  223. package/kanban/client/src/components/ceremony/steps/DeploymentStep.jsx +123 -0
  224. package/kanban/client/src/components/ceremony/steps/MissionStep.jsx +106 -0
  225. package/kanban/client/src/components/ceremony/steps/ReviewAnswersStep.jsx +125 -0
  226. package/kanban/client/src/components/ceremony/steps/RunningStep.jsx +228 -0
  227. package/kanban/client/src/components/kanban/CardDetailModal.jsx +559 -0
  228. package/kanban/client/src/components/kanban/EpicSection.jsx +146 -0
  229. package/kanban/client/src/components/kanban/FilterToolbar.jsx +222 -0
  230. package/kanban/client/src/components/kanban/GroupingSelector.jsx +57 -0
  231. package/kanban/client/src/components/kanban/KanbanBoard.jsx +211 -0
  232. package/kanban/client/src/components/kanban/KanbanCard.jsx +138 -0
  233. package/kanban/client/src/components/kanban/KanbanColumn.jsx +90 -0
  234. package/kanban/client/src/components/kanban/RefineWorkItemPopup.jsx +789 -0
  235. package/kanban/client/src/components/layout/LoadingScreen.jsx +82 -0
  236. package/kanban/client/src/components/process/ProcessMonitorBar.jsx +80 -0
  237. package/kanban/client/src/components/settings/AgentEditorPopup.jsx +171 -0
  238. package/kanban/client/src/components/settings/AgentsTab.jsx +353 -0
  239. package/kanban/client/src/components/settings/ApiKeysTab.jsx +113 -0
  240. package/kanban/client/src/components/settings/CeremonyModelsTab.jsx +98 -0
  241. package/kanban/client/src/components/settings/CostThresholdsTab.jsx +94 -0
  242. package/kanban/client/src/components/settings/ModelPricingTab.jsx +204 -0
  243. package/kanban/client/src/components/settings/ServersTab.jsx +121 -0
  244. package/kanban/client/src/components/settings/SettingsModal.jsx +84 -0
  245. package/kanban/client/src/components/stats/CostModal.jsx +353 -0
  246. package/kanban/client/src/components/ui/badge.jsx +27 -0
  247. package/kanban/client/src/components/ui/dialog.jsx +121 -0
  248. package/kanban/client/src/components/ui/tabs.jsx +85 -0
  249. package/kanban/client/src/hooks/__tests__/useGrouping.test.js +232 -0
  250. package/kanban/client/src/hooks/useGrouping.js +118 -0
  251. package/kanban/client/src/hooks/useWebSocket.js +120 -0
  252. package/kanban/client/src/lib/__tests__/api.test.js +196 -0
  253. package/kanban/client/src/lib/__tests__/status-grouping.test.js +94 -0
  254. package/kanban/client/src/lib/api.js +401 -0
  255. package/kanban/client/src/lib/status-grouping.js +144 -0
  256. package/kanban/client/src/lib/utils.js +11 -0
  257. package/kanban/client/src/main.jsx +10 -0
  258. package/kanban/client/src/store/__tests__/kanbanStore.test.js +164 -0
  259. package/kanban/client/src/store/ceremonyStore.js +172 -0
  260. package/kanban/client/src/store/filterStore.js +201 -0
  261. package/kanban/client/src/store/kanbanStore.js +115 -0
  262. package/kanban/client/src/store/processStore.js +65 -0
  263. package/kanban/client/src/store/sprintPlanningStore.js +33 -0
  264. package/kanban/client/src/styles/globals.css +59 -0
  265. package/kanban/client/tailwind.config.js +77 -0
  266. package/kanban/client/vite.config.js +28 -0
  267. package/kanban/client/vitest.config.js +28 -0
  268. package/kanban/dev-start.sh +47 -0
  269. package/kanban/package.json +12 -0
  270. package/kanban/server/index.js +516 -0
  271. package/kanban/server/routes/ceremony.js +305 -0
  272. package/kanban/server/routes/costs.js +157 -0
  273. package/kanban/server/routes/processes.js +50 -0
  274. package/kanban/server/routes/settings.js +303 -0
  275. package/kanban/server/routes/websocket.js +276 -0
  276. package/kanban/server/routes/work-items.js +347 -0
  277. package/kanban/server/services/CeremonyService.js +1190 -0
  278. package/kanban/server/services/FileSystemScanner.js +95 -0
  279. package/kanban/server/services/FileWatcher.js +144 -0
  280. package/kanban/server/services/HierarchyBuilder.js +196 -0
  281. package/kanban/server/services/ProcessRegistry.js +122 -0
  282. package/kanban/server/services/WorkItemReader.js +123 -0
  283. package/kanban/server/services/WorkItemRefineService.js +510 -0
  284. package/kanban/server/start.js +49 -0
  285. package/kanban/server/utils/kanban-logger.js +132 -0
  286. package/kanban/server/utils/markdown.js +91 -0
  287. package/kanban/server/utils/status-grouping.js +107 -0
  288. package/kanban/server/workers/sponsor-call-worker.js +84 -0
  289. package/kanban/server/workers/sprint-planning-worker.js +130 -0
  290. package/package.json +34 -7
@@ -0,0 +1,91 @@
1
+ import { marked } from 'marked';
2
+
3
+ /**
4
+ * Configure marked with safe defaults
5
+ */
6
+ marked.setOptions({
7
+ gfm: true, // GitHub Flavored Markdown
8
+ breaks: true, // Line breaks as <br>
9
+ headerIds: true, // Add IDs to headers
10
+ mangle: false, // Don't mangle email addresses
11
+ });
12
+
13
+ /**
14
+ * Render markdown to HTML
15
+ * @param {string} markdown - Markdown content
16
+ * @returns {string} HTML content
17
+ */
18
+ export function renderMarkdown(markdown) {
19
+ if (!markdown || typeof markdown !== 'string') {
20
+ return '';
21
+ }
22
+
23
+ try {
24
+ return marked.parse(markdown);
25
+ } catch (error) {
26
+ console.error('Error rendering markdown:', error);
27
+ return `<p>Error rendering markdown: ${error.message}</p>`;
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Sanitize markdown content (remove potentially dangerous content)
33
+ * Note: For MVP, we're assuming trusted content from .avc/project/
34
+ * In production, consider using DOMPurify or similar
35
+ * @param {string} html - HTML content
36
+ * @returns {string} Sanitized HTML
37
+ */
38
+ export function sanitizeHtml(html) {
39
+ // For now, just return as-is since content is from trusted source
40
+ // TODO: Add proper sanitization if exposing to untrusted users
41
+ return html;
42
+ }
43
+
44
+ /**
45
+ * Extract the description (first paragraph after H1) from a doc.md string.
46
+ * @param {string} markdown
47
+ * @returns {string}
48
+ */
49
+ export function extractDescriptionFromDoc(markdown) {
50
+ if (!markdown) return '';
51
+ const lines = markdown.split('\n');
52
+ let pastH1 = false;
53
+ const descLines = [];
54
+ for (const line of lines) {
55
+ if (!pastH1) {
56
+ if (line.startsWith('# ')) pastH1 = true;
57
+ continue;
58
+ }
59
+ if (line.startsWith('#') || line.startsWith('---')) break;
60
+ if (line.trim() === '' && descLines.length > 0) break;
61
+ if (line.trim()) descLines.push(line.trim());
62
+ }
63
+ return descLines.join(' ');
64
+ }
65
+
66
+ /**
67
+ * Replace the first paragraph after H1 with newDescription.
68
+ * Preserves all content below the first paragraph unchanged.
69
+ * @param {string} markdown
70
+ * @param {string} newDescription
71
+ * @returns {string}
72
+ */
73
+ export function updateDescriptionInDoc(markdown, newDescription) {
74
+ if (!markdown) return `\n\n${newDescription}\n`;
75
+ const lines = markdown.split('\n');
76
+ let h1Idx = -1, paraStart = -1, paraEnd = -1;
77
+ for (let i = 0; i < lines.length; i++) {
78
+ if (h1Idx === -1 && lines[i].startsWith('# ')) { h1Idx = i; continue; }
79
+ if (h1Idx !== -1 && paraStart === -1 && lines[i].trim()) { paraStart = i; continue; }
80
+ if (paraStart !== -1 && (!lines[i].trim() || lines[i].startsWith('#') || lines[i] === '---')) {
81
+ paraEnd = i; break;
82
+ }
83
+ }
84
+ if (paraStart === -1) {
85
+ lines.splice(h1Idx + 1, 0, '', newDescription);
86
+ return lines.join('\n');
87
+ }
88
+ if (paraEnd === -1) paraEnd = lines.length;
89
+ lines.splice(paraStart, paraEnd - paraStart, newDescription);
90
+ return lines.join('\n');
91
+ }
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Status Column Grouping Logic
3
+ * Maps AVC work item statuses to logical kanban columns
4
+ */
5
+
6
+ /**
7
+ * Maps status values to their display column
8
+ * Key: Column name
9
+ * Value: Array of status values that belong in that column
10
+ */
11
+ export const STATUS_COLUMN_MAPPING = {
12
+ Backlog: ['planned', 'pending'],
13
+ Ready: ['ready'],
14
+ 'In Progress': ['implementing', 'feedback'],
15
+ Review: ['implemented', 'testing'],
16
+ Done: ['completed'],
17
+ };
18
+
19
+ /**
20
+ * Metadata for each status value
21
+ * Used for badges, colors, icons within grouped columns
22
+ */
23
+ export const STATUS_METADATA = {
24
+ planned: { color: 'gray', icon: '📋', label: 'Planned' },
25
+ pending: { color: 'slate', icon: '⏸️', label: 'Pending' },
26
+ ready: { color: 'blue', icon: '🚀', label: 'Ready' },
27
+ implementing: { color: 'yellow', icon: '⚙️', label: 'Implementing' },
28
+ feedback: { color: 'amber', icon: '💬', label: 'Feedback' },
29
+ implemented: { color: 'purple', icon: '✅', label: 'Implemented' },
30
+ testing: { color: 'violet', icon: '🧪', label: 'Testing' },
31
+ completed: { color: 'green', icon: '🎉', label: 'Completed' },
32
+ blocked: { color: 'red', icon: '🚫', label: 'Blocked' },
33
+ };
34
+
35
+ /**
36
+ * Canonical order for columns on the board
37
+ */
38
+ export const COLUMN_ORDER = ['Backlog', 'Ready', 'In Progress', 'Review', 'Done'];
39
+
40
+ /**
41
+ * Get the column name for a given status
42
+ * @param {string} status - Work item status
43
+ * @returns {string|null} Column name or null if not found
44
+ */
45
+ export function getColumnForStatus(status) {
46
+ for (const [column, statuses] of Object.entries(STATUS_COLUMN_MAPPING)) {
47
+ if (statuses.includes(status)) {
48
+ return column;
49
+ }
50
+ }
51
+ return null;
52
+ }
53
+
54
+ /**
55
+ * Get metadata for a status
56
+ * @param {string} status - Work item status
57
+ * @returns {object|null} Status metadata or null if not found
58
+ */
59
+ export function getStatusMetadata(status) {
60
+ return STATUS_METADATA[status] || null;
61
+ }
62
+
63
+ /**
64
+ * Group work items by column
65
+ * @param {Array} workItems - Array of work items
66
+ * @returns {object} Object with column names as keys, arrays of work items as values
67
+ */
68
+ export function groupItemsByColumn(workItems) {
69
+ const grouped = {};
70
+
71
+ // Initialize all columns as empty arrays
72
+ COLUMN_ORDER.forEach((column) => {
73
+ grouped[column] = [];
74
+ });
75
+
76
+ // Group items by their column
77
+ workItems.forEach((item) => {
78
+ const column = getColumnForStatus(item.status);
79
+ if (column && grouped[column]) {
80
+ grouped[column].push(item);
81
+ }
82
+ });
83
+
84
+ return grouped;
85
+ }
86
+
87
+ /**
88
+ * Get statistics for a column
89
+ * @param {Array} workItems - Work items in the column
90
+ * @returns {object} Statistics object with total count and breakdown by status
91
+ */
92
+ export function getColumnStats(workItems) {
93
+ const stats = {
94
+ total: workItems.length,
95
+ byStatus: {},
96
+ };
97
+
98
+ workItems.forEach((item) => {
99
+ const status = item.status;
100
+ if (!stats.byStatus[status]) {
101
+ stats.byStatus[status] = 0;
102
+ }
103
+ stats.byStatus[status]++;
104
+ });
105
+
106
+ return stats;
107
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Sponsor Call Worker
3
+ * Forked by CeremonyService.runSponsorCallInProcess().
4
+ * Same IPC protocol as sprint-planning-worker.js.
5
+ * Receives `requirements` in the init message.
6
+ */
7
+
8
+ import { ProjectInitiator } from '../../../cli/init.js';
9
+ import { CommandLogger } from '../../../cli/command-logger.js';
10
+
11
+ let _paused = false;
12
+ let _cancelled = false;
13
+ let _requirements = null;
14
+ let _costThreshold = null;
15
+ let _waitingCostLimit = false;
16
+
17
+ // Parent server stopped — exit rather than running as an orphan.
18
+ process.on('disconnect', () => {
19
+ _cancelled = true;
20
+ // Give the current LLM call up to 5s to finish, then hard-exit.
21
+ setTimeout(() => process.exit(1), 5000).unref();
22
+ });
23
+
24
+ process.on('message', async (msg) => {
25
+ if (msg.type === 'init') {
26
+ _requirements = msg.requirements;
27
+ _costThreshold = msg.costThreshold ?? null;
28
+ run();
29
+ } else if (msg.type === 'pause') {
30
+ _paused = true;
31
+ process.send({ type: 'paused' });
32
+ } else if (msg.type === 'resume') {
33
+ _paused = false;
34
+ process.send({ type: 'resumed' });
35
+ } else if (msg.type === 'cancel') {
36
+ _cancelled = true;
37
+ } else if (msg.type === 'cost-limit-continue') {
38
+ _waitingCostLimit = false;
39
+ }
40
+ });
41
+
42
+ async function run() {
43
+ const logger = new CommandLogger('sponsor-call', process.cwd());
44
+ logger.start();
45
+ try {
46
+ const initiator = new ProjectInitiator();
47
+
48
+ const progressCallback = async (msg, substep, meta) => {
49
+ if (_cancelled) throw new Error('CEREMONY_CANCELLED');
50
+ while (_paused) {
51
+ await new Promise(r => setTimeout(r, 200));
52
+ if (_cancelled) throw new Error('CEREMONY_CANCELLED');
53
+ }
54
+ if (msg) process.send({ type: 'progress', message: msg });
55
+ if (substep) process.send({ type: 'substep', substep, meta: meta || {} });
56
+ if (meta?.detail) process.send({ type: 'detail', detail: meta.detail });
57
+ };
58
+
59
+ const costLimitReachedCallback = async (cost) => {
60
+ _waitingCostLimit = true;
61
+ process.send({ type: 'cost-limit', cost, threshold: _costThreshold });
62
+ while (_waitingCostLimit) {
63
+ await new Promise(r => setTimeout(r, 200));
64
+ if (_cancelled) throw new Error('CEREMONY_CANCELLED');
65
+ }
66
+ };
67
+
68
+ const result = await initiator.sponsorCallWithAnswers(_requirements, progressCallback, {
69
+ costThreshold: _costThreshold,
70
+ costLimitReachedCallback,
71
+ });
72
+ logger.stop();
73
+ process.send({ type: 'complete', result });
74
+ process.exit(0);
75
+ } catch (err) {
76
+ logger.stop();
77
+ if (err.message === 'CEREMONY_CANCELLED') {
78
+ process.send({ type: 'cancelled' });
79
+ } else {
80
+ process.send({ type: 'error', error: err.message });
81
+ }
82
+ process.exit(0);
83
+ }
84
+ }
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Sprint Planning Worker
3
+ * Forked by CeremonyService.runSprintPlanningInProcess().
4
+ * Communicates with the parent via IPC (process.send / process.on('message')).
5
+ *
6
+ * Parent → Worker:
7
+ * { type: 'init' }
8
+ * { type: 'pause' }
9
+ * { type: 'resume' }
10
+ * { type: 'cancel' }
11
+ * { type: 'selection-confirmed', selectedEpicIds, selectedStoryIds }
12
+ *
13
+ * Worker → Parent:
14
+ * { type: 'progress', message }
15
+ * { type: 'substep', substep, meta }
16
+ * { type: 'detail', detail }
17
+ * { type: 'paused' }
18
+ * { type: 'resumed' }
19
+ * { type: 'decomposition-complete', hierarchy }
20
+ * { type: 'complete', result }
21
+ * { type: 'cancelled' }
22
+ * { type: 'error', error }
23
+ */
24
+
25
+ import { ProjectInitiator } from '../../../cli/init.js';
26
+ import { CommandLogger } from '../../../cli/command-logger.js';
27
+
28
+ let _paused = false;
29
+ let _cancelled = false;
30
+ let _costThreshold = null;
31
+ let _waitingCostLimit = false;
32
+ let _waitingSelection = false;
33
+ let _selectionResult = null;
34
+
35
+ // Parent server stopped — exit rather than running as an orphan.
36
+ process.on('disconnect', () => {
37
+ _cancelled = true;
38
+ // Give the current LLM call up to 5s to finish, then hard-exit.
39
+ setTimeout(() => process.exit(1), 5000).unref();
40
+ });
41
+
42
+ process.on('message', async (msg) => {
43
+ if (msg.type === 'init') {
44
+ _costThreshold = msg.costThreshold ?? null;
45
+ run();
46
+ } else if (msg.type === 'pause') {
47
+ _paused = true;
48
+ process.send({ type: 'paused' });
49
+ } else if (msg.type === 'resume') {
50
+ _paused = false;
51
+ process.send({ type: 'resumed' });
52
+ } else if (msg.type === 'cancel') {
53
+ _cancelled = true;
54
+ } else if (msg.type === 'cost-limit-continue') {
55
+ _waitingCostLimit = false;
56
+ } else if (msg.type === 'selection-confirmed') {
57
+ _selectionResult = { selectedEpicIds: msg.selectedEpicIds, selectedStoryIds: msg.selectedStoryIds };
58
+ _waitingSelection = false;
59
+ }
60
+ });
61
+
62
+ async function run() {
63
+ const logger = new CommandLogger('sprint-planning', process.cwd());
64
+ logger.start();
65
+ try {
66
+ const initiator = new ProjectInitiator();
67
+
68
+ const progressCallback = async (msg, substep, meta) => {
69
+ if (_cancelled) throw new Error('CEREMONY_CANCELLED');
70
+ while (_paused) {
71
+ await new Promise(r => setTimeout(r, 200));
72
+ if (_cancelled) throw new Error('CEREMONY_CANCELLED');
73
+ }
74
+ if (msg) process.send({ type: 'progress', message: msg });
75
+ if (substep) process.send({ type: 'substep', substep, meta: meta || {} });
76
+ if (meta?.detail) process.send({ type: 'detail', detail: meta.detail });
77
+ };
78
+
79
+ const costLimitReachedCallback = async (cost) => {
80
+ _waitingCostLimit = true;
81
+ process.send({ type: 'cost-limit', cost, threshold: _costThreshold });
82
+ while (_waitingCostLimit) {
83
+ await new Promise(r => setTimeout(r, 200));
84
+ if (_cancelled) throw new Error('CEREMONY_CANCELLED');
85
+ }
86
+ };
87
+
88
+ const selectionCallback = async (hierarchy) => {
89
+ _waitingSelection = true;
90
+ _selectionResult = null;
91
+ process.send({ type: 'decomposition-complete', hierarchy });
92
+ while (_waitingSelection) {
93
+ await new Promise(r => setTimeout(r, 200));
94
+ if (_cancelled) throw new Error('CEREMONY_CANCELLED');
95
+ }
96
+ return _selectionResult;
97
+ };
98
+
99
+ const result = await initiator.sprintPlanningWithCallback(progressCallback, {
100
+ costThreshold: _costThreshold,
101
+ costLimitReachedCallback,
102
+ selectionCallback,
103
+ });
104
+ logger.stop();
105
+ process.send({ type: 'complete', result });
106
+
107
+ // Non-fatal docs sync after ceremony completes
108
+ try {
109
+ const { DocsSyncProcessor } = await import('../../../cli/docs-sync.js');
110
+ const syncer = new DocsSyncProcessor(process.cwd());
111
+ const { existsSync } = await import('fs');
112
+ if (existsSync(syncer.docsDir)) {
113
+ await syncer.sync();
114
+ process.send({ type: 'docs-synced' });
115
+ }
116
+ } catch (e) {
117
+ process.send({ type: 'docs-sync-failed', error: e.message });
118
+ }
119
+
120
+ process.exit(0);
121
+ } catch (err) {
122
+ logger.stop();
123
+ if (err.message === 'CEREMONY_CANCELLED') {
124
+ process.send({ type: 'cancelled' });
125
+ } else {
126
+ process.send({ type: 'error', error: err.message });
127
+ }
128
+ process.exit(0);
129
+ }
130
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agile-vibe-coding/avc",
3
- "version": "0.1.0",
3
+ "version": "0.2.3",
4
4
  "description": "Agile Vibe Coding (AVC) - Framework for managing AI agent-based software development projects",
5
5
  "type": "module",
6
6
  "main": "cli/index.js",
@@ -9,6 +9,7 @@
9
9
  },
10
10
  "files": [
11
11
  "cli/",
12
+ "kanban/",
12
13
  "README.md",
13
14
  "LICENSE"
14
15
  ],
@@ -16,7 +17,15 @@
16
17
  "access": "public"
17
18
  },
18
19
  "scripts": {
19
- "test": "echo \"No tests specified yet\" && exit 0",
20
+ "test": "vitest run",
21
+ "test:unit": "vitest run tests/unit",
22
+ "test:integration": "vitest run tests/integration",
23
+ "test:watch": "vitest watch",
24
+ "test:coverage": "vitest run --coverage",
25
+ "test:ui": "vitest --ui",
26
+ "models:evaluate": "node cli/model-selector.js",
27
+ "models:tables": "node cli/generate-summary-table.js",
28
+ "test:e2e": "node tests/e2e/cli-e2e.js",
20
29
  "prepublishOnly": "echo \"Running pre-publish checks...\" && npm test"
21
30
  },
22
31
  "keywords": [
@@ -34,7 +43,7 @@
34
43
  "workflow"
35
44
  ],
36
45
  "author": "Nacho Coll",
37
- "license": "MIT",
46
+ "license": "PolyForm-Noncommercial-1.0.0",
38
47
  "homepage": "https://agilevibecoding.org",
39
48
  "repository": {
40
49
  "type": "git",
@@ -45,14 +54,32 @@
45
54
  "url": "https://github.com/NachoColl/agilevibecoding/issues"
46
55
  },
47
56
  "engines": {
48
- "node": ">=18.0.0"
57
+ "node": ">=20.0.0"
49
58
  },
50
59
  "dependencies": {
51
60
  "@anthropic-ai/sdk": "^0.20.0",
61
+ "@google/genai": "^1.37.0",
62
+ "chokidar": "^4.0.3",
63
+ "cors": "^2.8.5",
52
64
  "dotenv": "^16.4.0",
53
- "ink": "^5.0.1",
65
+ "express": "^4.21.2",
66
+ "ink": "^6.7.0",
54
67
  "ink-select-input": "^6.0.0",
55
68
  "ink-spinner": "^5.0.0",
56
- "react": "^18.3.1"
69
+ "jsonrepair": "^3.13.2",
70
+ "marked": "^15.0.6",
71
+ "openai": "^6.19.0",
72
+ "react": "^19.0.0",
73
+ "vitepress": "^1.6.4",
74
+ "ws": "^8.18.0"
75
+ },
76
+ "devDependencies": {
77
+ "@sinonjs/fake-timers": "^12.0.0",
78
+ "@vitest/coverage-v8": "^2.1.9",
79
+ "@vitest/ui": "^2.1.9",
80
+ "memfs": "^4.56.10",
81
+ "node-pty": "^1.1.0",
82
+ "sinon": "^19.0.5",
83
+ "vitest": "^2.1.9"
57
84
  }
58
- }
85
+ }