@agile-vibe-coding/avc 0.1.1 → 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 (289) hide show
  1. package/cli/agent-loader.js +21 -0
  2. package/cli/agents/agent-selector.md +129 -0
  3. package/cli/agents/architecture-recommender.md +418 -0
  4. package/cli/agents/database-deep-dive.md +470 -0
  5. package/cli/agents/database-recommender.md +634 -0
  6. package/cli/agents/doc-distributor.md +176 -0
  7. package/cli/agents/documentation-updater.md +203 -0
  8. package/cli/agents/epic-story-decomposer.md +280 -0
  9. package/cli/agents/feature-context-generator.md +91 -0
  10. package/cli/agents/gap-checker-epic.md +52 -0
  11. package/cli/agents/impact-checker-story.md +51 -0
  12. package/cli/agents/migration-guide-generator.md +305 -0
  13. package/cli/agents/mission-scope-generator.md +79 -0
  14. package/cli/agents/mission-scope-validator.md +112 -0
  15. package/cli/agents/project-context-extractor.md +107 -0
  16. package/cli/agents/project-documentation-creator.json +226 -0
  17. package/cli/agents/project-documentation-creator.md +595 -0
  18. package/cli/agents/question-prefiller.md +269 -0
  19. package/cli/agents/refiner-epic.md +39 -0
  20. package/cli/agents/refiner-story.md +42 -0
  21. package/cli/agents/solver-epic-api.json +15 -0
  22. package/cli/agents/solver-epic-api.md +39 -0
  23. package/cli/agents/solver-epic-backend.json +15 -0
  24. package/cli/agents/solver-epic-backend.md +39 -0
  25. package/cli/agents/solver-epic-cloud.json +15 -0
  26. package/cli/agents/solver-epic-cloud.md +39 -0
  27. package/cli/agents/solver-epic-data.json +15 -0
  28. package/cli/agents/solver-epic-data.md +39 -0
  29. package/cli/agents/solver-epic-database.json +15 -0
  30. package/cli/agents/solver-epic-database.md +39 -0
  31. package/cli/agents/solver-epic-developer.json +15 -0
  32. package/cli/agents/solver-epic-developer.md +39 -0
  33. package/cli/agents/solver-epic-devops.json +15 -0
  34. package/cli/agents/solver-epic-devops.md +39 -0
  35. package/cli/agents/solver-epic-frontend.json +15 -0
  36. package/cli/agents/solver-epic-frontend.md +39 -0
  37. package/cli/agents/solver-epic-mobile.json +15 -0
  38. package/cli/agents/solver-epic-mobile.md +39 -0
  39. package/cli/agents/solver-epic-qa.json +15 -0
  40. package/cli/agents/solver-epic-qa.md +39 -0
  41. package/cli/agents/solver-epic-security.json +15 -0
  42. package/cli/agents/solver-epic-security.md +39 -0
  43. package/cli/agents/solver-epic-solution-architect.json +15 -0
  44. package/cli/agents/solver-epic-solution-architect.md +39 -0
  45. package/cli/agents/solver-epic-test-architect.json +15 -0
  46. package/cli/agents/solver-epic-test-architect.md +39 -0
  47. package/cli/agents/solver-epic-ui.json +15 -0
  48. package/cli/agents/solver-epic-ui.md +39 -0
  49. package/cli/agents/solver-epic-ux.json +15 -0
  50. package/cli/agents/solver-epic-ux.md +39 -0
  51. package/cli/agents/solver-story-api.json +15 -0
  52. package/cli/agents/solver-story-api.md +39 -0
  53. package/cli/agents/solver-story-backend.json +15 -0
  54. package/cli/agents/solver-story-backend.md +39 -0
  55. package/cli/agents/solver-story-cloud.json +15 -0
  56. package/cli/agents/solver-story-cloud.md +39 -0
  57. package/cli/agents/solver-story-data.json +15 -0
  58. package/cli/agents/solver-story-data.md +39 -0
  59. package/cli/agents/solver-story-database.json +15 -0
  60. package/cli/agents/solver-story-database.md +39 -0
  61. package/cli/agents/solver-story-developer.json +15 -0
  62. package/cli/agents/solver-story-developer.md +39 -0
  63. package/cli/agents/solver-story-devops.json +15 -0
  64. package/cli/agents/solver-story-devops.md +39 -0
  65. package/cli/agents/solver-story-frontend.json +15 -0
  66. package/cli/agents/solver-story-frontend.md +39 -0
  67. package/cli/agents/solver-story-mobile.json +15 -0
  68. package/cli/agents/solver-story-mobile.md +39 -0
  69. package/cli/agents/solver-story-qa.json +15 -0
  70. package/cli/agents/solver-story-qa.md +39 -0
  71. package/cli/agents/solver-story-security.json +15 -0
  72. package/cli/agents/solver-story-security.md +39 -0
  73. package/cli/agents/solver-story-solution-architect.json +15 -0
  74. package/cli/agents/solver-story-solution-architect.md +39 -0
  75. package/cli/agents/solver-story-test-architect.json +15 -0
  76. package/cli/agents/solver-story-test-architect.md +39 -0
  77. package/cli/agents/solver-story-ui.json +15 -0
  78. package/cli/agents/solver-story-ui.md +39 -0
  79. package/cli/agents/solver-story-ux.json +15 -0
  80. package/cli/agents/solver-story-ux.md +39 -0
  81. package/cli/agents/story-doc-enricher.md +133 -0
  82. package/cli/agents/suggestion-business-analyst.md +88 -0
  83. package/cli/agents/suggestion-deployment-architect.md +263 -0
  84. package/cli/agents/suggestion-product-manager.md +129 -0
  85. package/cli/agents/suggestion-security-specialist.md +156 -0
  86. package/cli/agents/suggestion-technical-architect.md +269 -0
  87. package/cli/agents/suggestion-ux-researcher.md +93 -0
  88. package/cli/agents/task-subtask-decomposer.md +188 -0
  89. package/cli/agents/validator-documentation.json +152 -0
  90. package/cli/agents/validator-documentation.md +453 -0
  91. package/cli/agents/validator-epic-api.json +93 -0
  92. package/cli/agents/validator-epic-api.md +137 -0
  93. package/cli/agents/validator-epic-backend.json +93 -0
  94. package/cli/agents/validator-epic-backend.md +130 -0
  95. package/cli/agents/validator-epic-cloud.json +93 -0
  96. package/cli/agents/validator-epic-cloud.md +137 -0
  97. package/cli/agents/validator-epic-data.json +93 -0
  98. package/cli/agents/validator-epic-data.md +130 -0
  99. package/cli/agents/validator-epic-database.json +93 -0
  100. package/cli/agents/validator-epic-database.md +137 -0
  101. package/cli/agents/validator-epic-developer.json +74 -0
  102. package/cli/agents/validator-epic-developer.md +153 -0
  103. package/cli/agents/validator-epic-devops.json +74 -0
  104. package/cli/agents/validator-epic-devops.md +153 -0
  105. package/cli/agents/validator-epic-frontend.json +74 -0
  106. package/cli/agents/validator-epic-frontend.md +153 -0
  107. package/cli/agents/validator-epic-mobile.json +93 -0
  108. package/cli/agents/validator-epic-mobile.md +130 -0
  109. package/cli/agents/validator-epic-qa.json +93 -0
  110. package/cli/agents/validator-epic-qa.md +130 -0
  111. package/cli/agents/validator-epic-security.json +74 -0
  112. package/cli/agents/validator-epic-security.md +154 -0
  113. package/cli/agents/validator-epic-solution-architect.json +74 -0
  114. package/cli/agents/validator-epic-solution-architect.md +156 -0
  115. package/cli/agents/validator-epic-test-architect.json +93 -0
  116. package/cli/agents/validator-epic-test-architect.md +130 -0
  117. package/cli/agents/validator-epic-ui.json +93 -0
  118. package/cli/agents/validator-epic-ui.md +130 -0
  119. package/cli/agents/validator-epic-ux.json +93 -0
  120. package/cli/agents/validator-epic-ux.md +130 -0
  121. package/cli/agents/validator-selector.md +211 -0
  122. package/cli/agents/validator-story-api.json +104 -0
  123. package/cli/agents/validator-story-api.md +152 -0
  124. package/cli/agents/validator-story-backend.json +104 -0
  125. package/cli/agents/validator-story-backend.md +152 -0
  126. package/cli/agents/validator-story-cloud.json +104 -0
  127. package/cli/agents/validator-story-cloud.md +152 -0
  128. package/cli/agents/validator-story-data.json +104 -0
  129. package/cli/agents/validator-story-data.md +152 -0
  130. package/cli/agents/validator-story-database.json +104 -0
  131. package/cli/agents/validator-story-database.md +152 -0
  132. package/cli/agents/validator-story-developer.json +104 -0
  133. package/cli/agents/validator-story-developer.md +152 -0
  134. package/cli/agents/validator-story-devops.json +104 -0
  135. package/cli/agents/validator-story-devops.md +152 -0
  136. package/cli/agents/validator-story-frontend.json +104 -0
  137. package/cli/agents/validator-story-frontend.md +152 -0
  138. package/cli/agents/validator-story-mobile.json +104 -0
  139. package/cli/agents/validator-story-mobile.md +152 -0
  140. package/cli/agents/validator-story-qa.json +104 -0
  141. package/cli/agents/validator-story-qa.md +152 -0
  142. package/cli/agents/validator-story-security.json +104 -0
  143. package/cli/agents/validator-story-security.md +152 -0
  144. package/cli/agents/validator-story-solution-architect.json +104 -0
  145. package/cli/agents/validator-story-solution-architect.md +152 -0
  146. package/cli/agents/validator-story-test-architect.json +104 -0
  147. package/cli/agents/validator-story-test-architect.md +152 -0
  148. package/cli/agents/validator-story-ui.json +104 -0
  149. package/cli/agents/validator-story-ui.md +152 -0
  150. package/cli/agents/validator-story-ux.json +104 -0
  151. package/cli/agents/validator-story-ux.md +152 -0
  152. package/cli/ansi-colors.js +21 -0
  153. package/cli/build-docs.js +29 -8
  154. package/cli/ceremony-history.js +369 -0
  155. package/cli/command-logger.js +49 -12
  156. package/cli/components/static-output.js +63 -0
  157. package/cli/console-output-manager.js +94 -0
  158. package/cli/docs-sync.js +306 -0
  159. package/cli/epic-story-validator.js +1174 -0
  160. package/cli/evaluation-prompts.js +1008 -0
  161. package/cli/execution-context.js +195 -0
  162. package/cli/generate-summary-table.js +340 -0
  163. package/cli/index.js +0 -0
  164. package/cli/init-model-config.js +697 -0
  165. package/cli/init.js +1311 -274
  166. package/cli/kanban-server-manager.js +228 -0
  167. package/cli/llm-claude.js +83 -1
  168. package/cli/llm-gemini.js +85 -0
  169. package/cli/llm-mock.js +233 -0
  170. package/cli/llm-openai.js +233 -0
  171. package/cli/llm-provider.js +240 -3
  172. package/cli/llm-token-limits.js +102 -0
  173. package/cli/llm-verifier.js +454 -0
  174. package/cli/message-constants.js +58 -0
  175. package/cli/message-manager.js +334 -0
  176. package/cli/message-types.js +96 -0
  177. package/cli/messaging-api.js +297 -0
  178. package/cli/model-pricing.js +169 -0
  179. package/cli/model-query-engine.js +468 -0
  180. package/cli/model-recommendation-analyzer.js +495 -0
  181. package/cli/model-selector.js +269 -0
  182. package/cli/output-buffer.js +107 -0
  183. package/cli/process-manager.js +73 -2
  184. package/cli/repl-ink.js +4988 -1217
  185. package/cli/repl-old.js +4 -4
  186. package/cli/seed-processor.js +792 -0
  187. package/cli/sprint-planning-processor.js +1813 -0
  188. package/cli/template-processor.js +2102 -105
  189. package/cli/templates/project.md +25 -8
  190. package/cli/templates/vitepress-config.mts.template +5 -4
  191. package/cli/token-tracker.js +520 -0
  192. package/cli/tools/generate-story-validators.js +317 -0
  193. package/cli/tools/generate-validators.js +669 -0
  194. package/cli/update-checker.js +19 -17
  195. package/cli/update-notifier.js +4 -4
  196. package/cli/validation-router.js +605 -0
  197. package/cli/verification-tracker.js +563 -0
  198. package/kanban/README.md +386 -0
  199. package/kanban/client/README.md +205 -0
  200. package/kanban/client/components.json +20 -0
  201. package/kanban/client/dist/assets/index-CiD8PS2e.js +306 -0
  202. package/kanban/client/dist/assets/index-nLh0m82Q.css +1 -0
  203. package/kanban/client/dist/index.html +16 -0
  204. package/kanban/client/dist/vite.svg +1 -0
  205. package/kanban/client/index.html +15 -0
  206. package/kanban/client/package-lock.json +9442 -0
  207. package/kanban/client/package.json +44 -0
  208. package/kanban/client/postcss.config.js +6 -0
  209. package/kanban/client/public/vite.svg +1 -0
  210. package/kanban/client/src/App.jsx +622 -0
  211. package/kanban/client/src/components/ProjectFileEditorPopup.jsx +117 -0
  212. package/kanban/client/src/components/ceremony/AskArchPopup.jsx +416 -0
  213. package/kanban/client/src/components/ceremony/AskModelPopup.jsx +616 -0
  214. package/kanban/client/src/components/ceremony/CeremonyWorkflowModal.jsx +946 -0
  215. package/kanban/client/src/components/ceremony/EpicStorySelectionModal.jsx +254 -0
  216. package/kanban/client/src/components/ceremony/SponsorCallModal.jsx +619 -0
  217. package/kanban/client/src/components/ceremony/SprintPlanningModal.jsx +704 -0
  218. package/kanban/client/src/components/ceremony/steps/ArchitectureStep.jsx +150 -0
  219. package/kanban/client/src/components/ceremony/steps/CompleteStep.jsx +154 -0
  220. package/kanban/client/src/components/ceremony/steps/DatabaseStep.jsx +202 -0
  221. package/kanban/client/src/components/ceremony/steps/DeploymentStep.jsx +123 -0
  222. package/kanban/client/src/components/ceremony/steps/MissionStep.jsx +106 -0
  223. package/kanban/client/src/components/ceremony/steps/ReviewAnswersStep.jsx +125 -0
  224. package/kanban/client/src/components/ceremony/steps/RunningStep.jsx +228 -0
  225. package/kanban/client/src/components/kanban/CardDetailModal.jsx +559 -0
  226. package/kanban/client/src/components/kanban/EpicSection.jsx +146 -0
  227. package/kanban/client/src/components/kanban/FilterToolbar.jsx +222 -0
  228. package/kanban/client/src/components/kanban/GroupingSelector.jsx +57 -0
  229. package/kanban/client/src/components/kanban/KanbanBoard.jsx +211 -0
  230. package/kanban/client/src/components/kanban/KanbanCard.jsx +138 -0
  231. package/kanban/client/src/components/kanban/KanbanColumn.jsx +90 -0
  232. package/kanban/client/src/components/kanban/RefineWorkItemPopup.jsx +789 -0
  233. package/kanban/client/src/components/layout/LoadingScreen.jsx +82 -0
  234. package/kanban/client/src/components/process/ProcessMonitorBar.jsx +80 -0
  235. package/kanban/client/src/components/settings/AgentEditorPopup.jsx +171 -0
  236. package/kanban/client/src/components/settings/AgentsTab.jsx +353 -0
  237. package/kanban/client/src/components/settings/ApiKeysTab.jsx +113 -0
  238. package/kanban/client/src/components/settings/CeremonyModelsTab.jsx +98 -0
  239. package/kanban/client/src/components/settings/CostThresholdsTab.jsx +94 -0
  240. package/kanban/client/src/components/settings/ModelPricingTab.jsx +204 -0
  241. package/kanban/client/src/components/settings/ServersTab.jsx +121 -0
  242. package/kanban/client/src/components/settings/SettingsModal.jsx +84 -0
  243. package/kanban/client/src/components/stats/CostModal.jsx +353 -0
  244. package/kanban/client/src/components/ui/badge.jsx +27 -0
  245. package/kanban/client/src/components/ui/dialog.jsx +121 -0
  246. package/kanban/client/src/components/ui/tabs.jsx +85 -0
  247. package/kanban/client/src/hooks/__tests__/useGrouping.test.js +232 -0
  248. package/kanban/client/src/hooks/useGrouping.js +118 -0
  249. package/kanban/client/src/hooks/useWebSocket.js +120 -0
  250. package/kanban/client/src/lib/__tests__/api.test.js +196 -0
  251. package/kanban/client/src/lib/__tests__/status-grouping.test.js +94 -0
  252. package/kanban/client/src/lib/api.js +401 -0
  253. package/kanban/client/src/lib/status-grouping.js +144 -0
  254. package/kanban/client/src/lib/utils.js +11 -0
  255. package/kanban/client/src/main.jsx +10 -0
  256. package/kanban/client/src/store/__tests__/kanbanStore.test.js +164 -0
  257. package/kanban/client/src/store/ceremonyStore.js +172 -0
  258. package/kanban/client/src/store/filterStore.js +201 -0
  259. package/kanban/client/src/store/kanbanStore.js +115 -0
  260. package/kanban/client/src/store/processStore.js +65 -0
  261. package/kanban/client/src/store/sprintPlanningStore.js +33 -0
  262. package/kanban/client/src/styles/globals.css +59 -0
  263. package/kanban/client/tailwind.config.js +77 -0
  264. package/kanban/client/vite.config.js +28 -0
  265. package/kanban/client/vitest.config.js +28 -0
  266. package/kanban/dev-start.sh +47 -0
  267. package/kanban/package.json +12 -0
  268. package/kanban/server/index.js +516 -0
  269. package/kanban/server/routes/ceremony.js +305 -0
  270. package/kanban/server/routes/costs.js +157 -0
  271. package/kanban/server/routes/processes.js +50 -0
  272. package/kanban/server/routes/settings.js +303 -0
  273. package/kanban/server/routes/websocket.js +276 -0
  274. package/kanban/server/routes/work-items.js +347 -0
  275. package/kanban/server/services/CeremonyService.js +1190 -0
  276. package/kanban/server/services/FileSystemScanner.js +95 -0
  277. package/kanban/server/services/FileWatcher.js +144 -0
  278. package/kanban/server/services/HierarchyBuilder.js +196 -0
  279. package/kanban/server/services/ProcessRegistry.js +122 -0
  280. package/kanban/server/services/WorkItemReader.js +123 -0
  281. package/kanban/server/services/WorkItemRefineService.js +510 -0
  282. package/kanban/server/start.js +49 -0
  283. package/kanban/server/utils/kanban-logger.js +132 -0
  284. package/kanban/server/utils/markdown.js +91 -0
  285. package/kanban/server/utils/status-grouping.js +107 -0
  286. package/kanban/server/workers/sponsor-call-worker.js +84 -0
  287. package/kanban/server/workers/sprint-planning-worker.js +130 -0
  288. package/package.json +18 -5
  289. package/cli/agents/documentation.md +0 -302
@@ -0,0 +1,150 @@
1
+ import { useState } from 'react';
2
+ import { Wand2 } from 'lucide-react';
3
+ import { useCeremonyStore } from '../../../store/ceremonyStore';
4
+ import { AskArchPopup } from '../AskArchPopup';
5
+
6
+ const COST_TIER_COLOR = {
7
+ 'Free': 'text-green-600',
8
+ '$': 'text-green-600',
9
+ '$$': 'text-amber-500',
10
+ '$$$': 'text-orange-500',
11
+ '$$$$': 'text-red-500',
12
+ };
13
+
14
+ function ArchCard({ arch, selected, onSelect }) {
15
+ return (
16
+ <button
17
+ onClick={() => onSelect(arch)}
18
+ className={`text-left rounded-xl border-2 p-4 w-full transition-all ${
19
+ selected
20
+ ? 'border-indigo-500 bg-indigo-50'
21
+ : 'border-slate-200 hover:border-slate-300 bg-white'
22
+ }`}
23
+ >
24
+ <div className="flex items-start justify-between gap-2 mb-2">
25
+ <span className="font-semibold text-slate-900 text-sm">{arch.name}</span>
26
+ {arch.requiresCloudProvider ? (
27
+ <span className="text-xs bg-purple-100 text-purple-700 px-2 py-0.5 rounded-full whitespace-nowrap">
28
+ Cloud
29
+ </span>
30
+ ) : (
31
+ <span className="text-xs bg-green-100 text-green-700 px-2 py-0.5 rounded-full whitespace-nowrap">
32
+ Local
33
+ </span>
34
+ )}
35
+ </div>
36
+
37
+ <p className="text-xs text-slate-600 mb-2 line-clamp-3">{arch.description}</p>
38
+
39
+ {arch.bestFor && (
40
+ <p className="text-xs text-slate-500 italic">Best for: {arch.bestFor}</p>
41
+ )}
42
+
43
+ {arch.costTier && (
44
+ <p className={`mt-2 text-sm font-semibold ${COST_TIER_COLOR[arch.costTier] ?? 'text-slate-500'}`}>
45
+ {arch.costTier}
46
+ </p>
47
+ )}
48
+
49
+ {arch.migrationPath && (
50
+ <div className="mt-2 text-xs text-slate-400">
51
+ Migration to cloud: {arch.migrationPath.estimatedMigrationEffort} (
52
+ {arch.migrationPath.migrationComplexity})
53
+ </div>
54
+ )}
55
+ </button>
56
+ );
57
+ }
58
+
59
+ export function ArchitectureStep({ onNext, onBack, analyzing, onOpenSettings }) {
60
+ const { archOptions, selectedArch, setSelectedArch, setArchOptions } = useCeremonyStore();
61
+ const [showAskArch, setShowAskArch] = useState(false);
62
+
63
+ if (!archOptions || archOptions.length === 0) {
64
+ return (
65
+ <div className="flex items-center justify-center py-16">
66
+ <div className="text-center text-slate-400">
67
+ <p>Loading architecture recommendations...</p>
68
+ </div>
69
+ </div>
70
+ );
71
+ }
72
+
73
+ return (
74
+ <div className="space-y-6">
75
+ <div>
76
+ <h2 className="text-xl font-semibold text-slate-900">Architecture Selection</h2>
77
+ <p className="text-sm text-slate-500 mt-1">
78
+ Choose the deployment architecture that fits your project best.
79
+ </p>
80
+ </div>
81
+
82
+ <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
83
+ {archOptions.map((arch, i) => (
84
+ <ArchCard
85
+ key={i}
86
+ arch={arch}
87
+ selected={selectedArch === arch}
88
+ onSelect={setSelectedArch}
89
+ />
90
+ ))}
91
+ </div>
92
+
93
+ <div className="flex items-center justify-between pt-2">
94
+ <button
95
+ type="button"
96
+ onClick={onBack}
97
+ disabled={analyzing}
98
+ className="text-sm text-slate-400 hover:text-slate-600 disabled:opacity-40 transition-colors"
99
+ >
100
+ ← Back
101
+ </button>
102
+ <div className="flex items-center gap-3">
103
+ <button
104
+ type="button"
105
+ onClick={() => setShowAskArch(true)}
106
+ disabled={analyzing}
107
+ className="flex items-center gap-1.5 px-3 py-2 text-sm text-violet-700 bg-violet-50 border border-violet-200 rounded-lg hover:bg-violet-100 disabled:opacity-40 transition-colors"
108
+ >
109
+ <Wand2 className="w-3.5 h-3.5" />
110
+ Ask a Model
111
+ </button>
112
+ <button
113
+ type="button"
114
+ onClick={onNext}
115
+ disabled={analyzing}
116
+ className="text-sm text-slate-400 hover:text-slate-600 disabled:opacity-40 transition-colors"
117
+ >
118
+ Skip — let the model decide
119
+ </button>
120
+ <button
121
+ onClick={onNext}
122
+ disabled={!selectedArch || analyzing}
123
+ className="px-5 py-2 bg-slate-900 text-white text-sm font-medium rounded-lg disabled:opacity-40 hover:bg-slate-700 transition-colors flex items-center gap-2"
124
+ >
125
+ {analyzing ? (
126
+ <>
127
+ <span className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" />
128
+ Preparing requirements…
129
+ </>
130
+ ) : (
131
+ 'Continue'
132
+ )}
133
+ </button>
134
+ </div>
135
+ </div>
136
+
137
+ {showAskArch && (
138
+ <AskArchPopup
139
+ onUse={(arch) => {
140
+ setArchOptions([...archOptions, arch]);
141
+ setSelectedArch(arch);
142
+ setShowAskArch(false);
143
+ }}
144
+ onClose={() => setShowAskArch(false)}
145
+ onOpenSettings={onOpenSettings}
146
+ />
147
+ )}
148
+ </div>
149
+ );
150
+ }
@@ -0,0 +1,154 @@
1
+ import { useCeremonyStore } from '../../../store/ceremonyStore';
2
+
3
+ const EXAMPLE_ISSUES = [
4
+ { stage: 'Project Documentation', ruleId: 'fix-header-formatting', name: 'Fix Header Spacing', severity: 'major' },
5
+ { stage: 'Project Documentation', ruleId: 'add-section-spacing', name: 'Add Section Spacing', severity: 'minor' },
6
+ { stage: 'Project Context', ruleId: 'token-count-too-short', name: 'Expand If Too Short', severity: 'major' },
7
+ { stage: 'Project Context', ruleId: 'no-redundant-info', name: 'Remove Truly Redundant Information', severity: 'minor' },
8
+ { stage: 'Context Validation', ruleId: 'fix-unclosed-code-blocks', name: 'Fix Unclosed Code Blocks', severity: 'major' },
9
+ ];
10
+
11
+ function IssueTag({ severity }) {
12
+ const cls =
13
+ severity === 'critical' ? 'bg-red-100 text-red-700' :
14
+ severity === 'major' ? 'bg-amber-100 text-amber-700' :
15
+ 'bg-slate-100 text-slate-500';
16
+ return (
17
+ <span className={`flex-shrink-0 px-1.5 py-0.5 rounded text-[10px] font-semibold uppercase ${cls}`}>
18
+ {severity}
19
+ </span>
20
+ );
21
+ }
22
+
23
+ function FileTag({ path }) {
24
+ const short = path?.split('/').slice(-2).join('/') || path;
25
+ return (
26
+ <span className="inline-flex items-center gap-1 bg-green-50 border border-green-200 text-green-700 text-xs px-2 py-1 rounded-md font-mono">
27
+ <span>📄</span>
28
+ {short}
29
+ </span>
30
+ );
31
+ }
32
+
33
+ function Stat({ label, value }) {
34
+ return (
35
+ <div className="bg-slate-50 rounded-lg border border-slate-200 p-3 text-center">
36
+ <div className="text-lg font-bold text-slate-900">{value}</div>
37
+ <div className="text-xs text-slate-500">{label}</div>
38
+ </div>
39
+ );
40
+ }
41
+
42
+ export function CompleteStep({ onClose }) {
43
+ const { ceremonyResult } = useCeremonyStore();
44
+ const r = ceremonyResult || {};
45
+
46
+ const tokenInput = r.tokenUsage?.input || r.tokenUsage?.inputTokens || 0;
47
+ const tokenOutput = r.tokenUsage?.output || r.tokenUsage?.outputTokens || 0;
48
+ const tokenTotal = r.tokenUsage?.total || r.tokenUsage?.totalTokens || tokenInput + tokenOutput;
49
+ const costTotal =
50
+ r.cost?.total != null
51
+ ? `$${r.cost.total.toFixed(4)}`
52
+ : r.cost
53
+ ? `$${Object.values(r.cost).reduce((a, v) => a + (typeof v === 'number' ? v : 0), 0).toFixed(4)}`
54
+ : '—';
55
+
56
+ const files = r.outputPath && r.contextPath
57
+ ? [r.outputPath, r.contextPath]
58
+ : r.filesGenerated || [];
59
+
60
+ // undefined → show example preview; [] → no issues (hide); [...] → real data
61
+ const isExample = r.validationIssues === undefined;
62
+ const rawIssues = r.validationIssues ?? EXAMPLE_ISSUES;
63
+
64
+ // Group duplicate rule applications by ruleId
65
+ const issueMap = {};
66
+ for (const issue of rawIssues) {
67
+ const key = issue.ruleId || issue.name;
68
+ if (!issueMap[key]) {
69
+ issueMap[key] = { ...issue, count: 1, iterations: issue.iteration ? [issue.iteration] : [] };
70
+ } else {
71
+ issueMap[key].count++;
72
+ if (issue.iteration && !issueMap[key].iterations.includes(issue.iteration)) {
73
+ issueMap[key].iterations.push(issue.iteration);
74
+ }
75
+ }
76
+ }
77
+ const issues = Object.values(issueMap);
78
+
79
+ return (
80
+ <div className="space-y-6">
81
+ <div className="text-center">
82
+ <h2 className="text-xl font-semibold text-slate-900">Documentation Generated!</h2>
83
+ <p className="text-sm text-slate-500 mt-1">
84
+ Your project documentation is ready. The kanban board will refresh automatically.
85
+ </p>
86
+ </div>
87
+
88
+ {files.length > 0 && (
89
+ <div>
90
+ <p className="text-xs font-medium text-slate-500 mb-2">Files created</p>
91
+ <div className="flex flex-wrap gap-2">
92
+ {files.map((f, i) => (
93
+ <FileTag key={i} path={f} />
94
+ ))}
95
+ </div>
96
+ </div>
97
+ )}
98
+
99
+ <div className="grid grid-cols-3 gap-3">
100
+ <Stat label="Input tokens" value={tokenInput.toLocaleString()} />
101
+ <Stat label="Output tokens" value={tokenOutput.toLocaleString()} />
102
+ <Stat label="Estimated cost" value={costTotal} />
103
+ </div>
104
+
105
+ {r.model && (
106
+ <p className="text-xs text-center text-slate-400">
107
+ Model: <span className="font-mono">{r.model}</span>
108
+ </p>
109
+ )}
110
+
111
+ {issues.length > 0 && (
112
+ <div>
113
+ <p className="text-xs font-semibold text-slate-500 uppercase tracking-wide mb-2">
114
+ Quality fixes applied
115
+ {isExample && <span className="ml-2 normal-case font-normal text-slate-300">(example preview)</span>}
116
+ </p>
117
+ <div className="space-y-1.5">
118
+ {issues.map((issue, i) => (
119
+ <div key={i} className="bg-amber-50 border border-amber-100 rounded-md px-3 py-2 text-xs">
120
+ <div className="flex items-center gap-2">
121
+ <IssueTag severity={issue.severity} />
122
+ <span className="text-slate-400 flex-shrink-0">{issue.stage}</span>
123
+ <span className="text-slate-700 font-medium">{issue.name}</span>
124
+ {issue.count > 1 && (
125
+ <span className="ml-auto flex-shrink-0 bg-amber-200 text-amber-800 text-[10px] font-bold px-1.5 py-0.5 rounded-full">
126
+ ×{issue.count}
127
+ </span>
128
+ )}
129
+ {issue.iterations?.length > 0 && (
130
+ <span className="flex-shrink-0 text-slate-400">
131
+ iter {issue.iterations.sort((a, b) => a - b).join(', ')}
132
+ </span>
133
+ )}
134
+ </div>
135
+ {issue.description && (
136
+ <p className="mt-1 text-slate-500 pl-1">{issue.description}</p>
137
+ )}
138
+ </div>
139
+ ))}
140
+ </div>
141
+ </div>
142
+ )}
143
+
144
+ <div className="flex justify-center pt-2">
145
+ <button
146
+ onClick={onClose}
147
+ className="px-6 py-2 bg-slate-900 text-white text-sm font-medium rounded-lg hover:bg-slate-700 transition-colors"
148
+ >
149
+ Close
150
+ </button>
151
+ </div>
152
+ </div>
153
+ );
154
+ }
@@ -0,0 +1,202 @@
1
+ import { Info, BarChart2 } from 'lucide-react';
2
+ import { useCeremonyStore } from '../../../store/ceremonyStore';
3
+
4
+ /** Convert a monetary string like "$150-280/month" into a relative $ tier. */
5
+ function costTier(monthly) {
6
+ if (!monthly) return null;
7
+ const str = String(monthly).toLowerCase();
8
+ const nums = (str.match(/\d+/g) || []).map(Number).filter((n) => n > 0);
9
+ const avg = nums.length ? nums.reduce((a, b) => a + b, 0) / nums.length : 0;
10
+ if (avg === 0) return { symbols: 'Free', color: 'text-green-600' };
11
+ if (avg <= 50) return { symbols: '$', color: 'text-green-600' };
12
+ if (avg <= 150) return { symbols: '$$', color: 'text-amber-500' };
13
+ if (avg <= 350) return { symbols: '$$$', color: 'text-orange-500' };
14
+ return { symbols: '$$$$', color: 'text-red-500' };
15
+ }
16
+
17
+ function DbOptionCard({ option, type, selected, onSelect }) {
18
+ const label = type === 'sql' ? 'SQL' : 'NoSQL';
19
+ const color = type === 'sql' ? 'blue' : 'emerald';
20
+
21
+ const colorMap = {
22
+ blue: {
23
+ badge: 'bg-blue-100 text-blue-700',
24
+ border: 'border-blue-500',
25
+ bg: 'bg-blue-50',
26
+ btn: 'ring-blue-500',
27
+ },
28
+ emerald: {
29
+ badge: 'bg-emerald-100 text-emerald-700',
30
+ border: 'border-emerald-500',
31
+ bg: 'bg-emerald-50',
32
+ btn: 'ring-emerald-500',
33
+ },
34
+ };
35
+ const c = colorMap[color];
36
+
37
+ return (
38
+ <button
39
+ onClick={() => onSelect(type)}
40
+ className={`text-left rounded-xl border-2 p-5 w-full transition-all ${
41
+ selected ? `${c.border} ${c.bg}` : 'border-slate-200 hover:border-slate-300 bg-white'
42
+ }`}
43
+ >
44
+ <div className="flex items-center gap-2 mb-3">
45
+ <span className={`text-xs font-semibold px-2 py-0.5 rounded-full ${c.badge}`}>{label}</span>
46
+ <span className="font-semibold text-slate-900">{option.database}</span>
47
+ </div>
48
+
49
+ {option.specificVersion && (
50
+ <p className="text-xs text-slate-500 mb-2">Version: {option.specificVersion}</p>
51
+ )}
52
+
53
+ {option.estimatedCosts && (() => {
54
+ const tier = costTier(option.estimatedCosts.monthly);
55
+ return tier ? (
56
+ <p className={`text-sm font-semibold mb-2 ${tier.color}`}>{tier.symbols}</p>
57
+ ) : null;
58
+ })()}
59
+
60
+ {option.keyStrengths && option.keyStrengths.length > 0 && (
61
+ <div className="mt-2">
62
+ <p className="text-xs font-medium text-slate-500 mb-1">Strengths</p>
63
+ <ul className="space-y-0.5">
64
+ {option.keyStrengths.slice(0, 3).map((s, i) => (
65
+ <li key={i} className="text-xs text-slate-600 flex items-start gap-1.5">
66
+ <span className="mt-1 w-1 h-1 rounded-full bg-slate-400 flex-shrink-0" />
67
+ {s}
68
+ </li>
69
+ ))}
70
+ </ul>
71
+ </div>
72
+ )}
73
+
74
+ {option.tradeoffs && (
75
+ <p className="text-xs text-slate-400 mt-2 italic">{option.tradeoffs}</p>
76
+ )}
77
+ </button>
78
+ );
79
+ }
80
+
81
+ export function DatabaseStep({ onNext, onBack, analyzing }) {
82
+ const { dbResult, dbChoice, setDbChoice } = useCeremonyStore();
83
+
84
+ if (!dbResult) {
85
+ return (
86
+ <div className="flex items-center justify-center py-16">
87
+ <div className="text-center text-slate-400">
88
+ <p>Loading database analysis...</p>
89
+ </div>
90
+ </div>
91
+ );
92
+ }
93
+
94
+ const { comparison, rationale } = dbResult;
95
+
96
+ return (
97
+ <div className="space-y-6">
98
+ <div>
99
+ <h2 className="text-xl font-semibold text-slate-900">Database Choice</h2>
100
+ <p className="text-sm text-slate-500 mt-1">
101
+ Choose between SQL and NoSQL based on your project's data needs.
102
+ </p>
103
+ {rationale && (
104
+ <p className="text-sm text-slate-600 mt-2 bg-slate-50 border border-slate-200 rounded-lg px-3 py-2">
105
+ {rationale}
106
+ </p>
107
+ )}
108
+ </div>
109
+
110
+ {comparison && (
111
+ <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
112
+ <DbOptionCard
113
+ option={comparison.sqlOption}
114
+ type="sql"
115
+ selected={dbChoice === 'sql'}
116
+ onSelect={setDbChoice}
117
+ />
118
+ <DbOptionCard
119
+ option={comparison.nosqlOption}
120
+ type="nosql"
121
+ selected={dbChoice === 'nosql'}
122
+ onSelect={setDbChoice}
123
+ />
124
+ </div>
125
+ )}
126
+
127
+ {dbResult.keyMetrics && (
128
+ <div className="rounded-xl border border-slate-200 bg-slate-50 overflow-hidden">
129
+ <div className="flex items-center gap-1.5 px-4 py-2 border-b border-slate-200 bg-white">
130
+ <BarChart2 className="w-3.5 h-3.5 text-slate-400" />
131
+ <span className="text-xs font-semibold text-slate-500">Project metrics analysed</span>
132
+ </div>
133
+ <div className="flex divide-x divide-slate-200">
134
+ {dbResult.keyMetrics.estimatedReadWriteRatio && (
135
+ <div className="flex-1 px-4 py-3">
136
+ <p className="text-[10px] font-medium text-slate-400 uppercase tracking-wide mb-1">Read / Write ratio</p>
137
+ <p className="text-sm font-semibold text-slate-700">{dbResult.keyMetrics.estimatedReadWriteRatio}</p>
138
+ </div>
139
+ )}
140
+ {dbResult.keyMetrics.expectedThroughput && (
141
+ <div className="flex-1 px-4 py-3">
142
+ <p className="text-[10px] font-medium text-slate-400 uppercase tracking-wide mb-1">Expected throughput</p>
143
+ <p className="text-sm font-semibold text-slate-700">{dbResult.keyMetrics.expectedThroughput}</p>
144
+ </div>
145
+ )}
146
+ {dbResult.keyMetrics.dataComplexity && (
147
+ <div className="flex-1 px-4 py-3">
148
+ <p className="text-[10px] font-medium text-slate-400 uppercase tracking-wide mb-1">Data complexity</p>
149
+ <p className="text-sm font-semibold text-slate-700">{dbResult.keyMetrics.dataComplexity}</p>
150
+ </div>
151
+ )}
152
+ </div>
153
+ </div>
154
+ )}
155
+
156
+ <div className="flex items-start gap-2 px-1 py-2 text-xs text-slate-400">
157
+ <Info className="w-3.5 h-3.5 flex-shrink-0 mt-0.5 text-slate-300" />
158
+ <p>
159
+ The SQL and NoSQL candidates above are AI-suggested based on your mission and scope —
160
+ specific technology (e.g. PostgreSQL vs MySQL, MongoDB vs DynamoDB) and configuration
161
+ will be refined during architecture analysis. Skipping lets the model choose the best fit autonomously,
162
+ which may include a vector database, a time-series store, or no database at all.
163
+ </p>
164
+ </div>
165
+
166
+ <div className="flex items-center justify-between pt-2">
167
+ <button
168
+ type="button"
169
+ onClick={onBack}
170
+ disabled={analyzing}
171
+ className="text-sm text-slate-400 hover:text-slate-600 disabled:opacity-40 transition-colors"
172
+ >
173
+ ← Back
174
+ </button>
175
+ <div className="flex items-center gap-3">
176
+ <button
177
+ type="button"
178
+ onClick={onNext}
179
+ disabled={analyzing}
180
+ className="text-sm text-slate-400 hover:text-slate-600 disabled:opacity-40 transition-colors"
181
+ >
182
+ Skip — let the model decide
183
+ </button>
184
+ <button
185
+ onClick={onNext}
186
+ disabled={!dbChoice || analyzing}
187
+ className="px-5 py-2 bg-slate-900 text-white text-sm font-medium rounded-lg disabled:opacity-40 hover:bg-slate-700 transition-colors flex items-center gap-2"
188
+ >
189
+ {analyzing ? (
190
+ <>
191
+ <span className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" />
192
+ Analyzing...
193
+ </>
194
+ ) : (
195
+ 'Continue'
196
+ )}
197
+ </button>
198
+ </div>
199
+ </div>
200
+ </div>
201
+ );
202
+ }
@@ -0,0 +1,123 @@
1
+ import { Info } from 'lucide-react';
2
+ import { useCeremonyStore } from '../../../store/ceremonyStore';
3
+
4
+ const strategies = [
5
+ {
6
+ id: 'local-mvp',
7
+ icon: '💻',
8
+ title: 'Local MVP First',
9
+ subtitle: 'Start on your machine, migrate later',
10
+ bullets: [
11
+ 'Zero cloud costs during development',
12
+ 'Fast iteration — no deployment delays',
13
+ 'SQLite or local PostgreSQL/MongoDB',
14
+ 'Docker Compose for production parity',
15
+ ],
16
+ color: 'blue',
17
+ },
18
+ {
19
+ id: 'cloud',
20
+ icon: '☁️',
21
+ title: 'Cloud Deployment',
22
+ subtitle: 'Production-ready from day one',
23
+ bullets: [
24
+ 'Managed infrastructure (AWS / Azure / GCP)',
25
+ 'Auto-scaling and high availability',
26
+ 'Managed databases with backups',
27
+ 'CI/CD pipeline recommendations',
28
+ 'Monthly cost estimates included',
29
+ ],
30
+ color: 'purple',
31
+ },
32
+ ];
33
+
34
+ export function DeploymentStep({ onNext }) {
35
+ const { strategy, setStrategy } = useCeremonyStore();
36
+
37
+ const colorMap = {
38
+ blue: {
39
+ border: 'border-blue-500',
40
+ bg: 'bg-blue-50',
41
+ icon: 'text-blue-600',
42
+ bullet: 'bg-blue-500',
43
+ btn: 'bg-blue-600 hover:bg-blue-700',
44
+ },
45
+ purple: {
46
+ border: 'border-purple-500',
47
+ bg: 'bg-purple-50',
48
+ icon: 'text-purple-600',
49
+ bullet: 'bg-purple-500',
50
+ btn: 'bg-purple-600 hover:bg-purple-700',
51
+ },
52
+ };
53
+
54
+ const handleSelect = (id) => {
55
+ setStrategy(id);
56
+ };
57
+
58
+ return (
59
+ <div className="space-y-6">
60
+ <div>
61
+ <h2 className="text-xl font-semibold text-slate-900">Deployment Strategy</h2>
62
+ <p className="text-sm text-slate-500 mt-1">
63
+ Choose how you want to deploy your project. This shapes architecture and technology recommendations.
64
+ </p>
65
+ </div>
66
+
67
+ <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
68
+ {strategies.map((s) => {
69
+ const c = colorMap[s.color];
70
+ const selected = strategy === s.id;
71
+ return (
72
+ <button
73
+ key={s.id}
74
+ onClick={() => handleSelect(s.id)}
75
+ className={`text-left rounded-xl border-2 p-5 transition-all ${
76
+ selected ? `${c.border} ${c.bg}` : 'border-slate-200 hover:border-slate-300 bg-white'
77
+ }`}
78
+ >
79
+ <div className={`text-3xl mb-3 ${c.icon}`}>{s.icon}</div>
80
+ <div className="font-semibold text-slate-900 text-base">{s.title}</div>
81
+ <div className="text-xs text-slate-500 mb-3">{s.subtitle}</div>
82
+ <ul className="space-y-1">
83
+ {s.bullets.map((b, i) => (
84
+ <li key={i} className="flex items-start gap-2 text-xs text-slate-600">
85
+ <span className={`mt-1.5 w-1.5 h-1.5 rounded-full flex-shrink-0 ${c.bullet}`} />
86
+ {b}
87
+ </li>
88
+ ))}
89
+ </ul>
90
+ </button>
91
+ );
92
+ })}
93
+ </div>
94
+
95
+ <div className="flex items-start gap-2 px-1 py-2 text-xs text-slate-400">
96
+ <Info className="w-3.5 h-3.5 flex-shrink-0 mt-0.5 text-slate-300" />
97
+ <p>
98
+ Technologies listed (e.g. SQLite, MongoDB) are illustrative examples.
99
+ The ceremony tailors all recommendations to your actual requirements — your project may end up
100
+ using a vector database, a search engine, no database at all, or something else entirely.
101
+ </p>
102
+ </div>
103
+
104
+ <div className="flex items-center justify-end gap-3 pt-2">
105
+ <button
106
+ type="button"
107
+ onClick={onNext}
108
+ className="text-sm text-slate-400 hover:text-slate-600 transition-colors"
109
+ >
110
+ Skip — let the model decide
111
+ </button>
112
+ <button
113
+ type="button"
114
+ onClick={onNext}
115
+ disabled={!strategy}
116
+ className="px-5 py-2 bg-slate-900 text-white text-sm font-medium rounded-lg disabled:opacity-40 hover:bg-slate-700 transition-colors"
117
+ >
118
+ Continue
119
+ </button>
120
+ </div>
121
+ </div>
122
+ );
123
+ }