@agile-vibe-coding/avc 0.2.3 → 0.3.2

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 (262) hide show
  1. package/README.md +475 -3
  2. package/cli/agents/agent-selector.md +23 -0
  3. package/cli/agents/code-implementer.md +117 -0
  4. package/cli/agents/code-validator.md +80 -0
  5. package/cli/agents/context-reviewer-epic.md +101 -0
  6. package/cli/agents/context-reviewer-story.md +92 -0
  7. package/cli/agents/context-writer-epic.md +145 -0
  8. package/cli/agents/context-writer-story.md +111 -0
  9. package/cli/agents/doc-writer-epic.md +42 -0
  10. package/cli/agents/doc-writer-story.md +43 -0
  11. package/cli/agents/duplicate-detector.md +110 -0
  12. package/cli/agents/epic-story-decomposer.md +318 -39
  13. package/cli/agents/mission-scope-generator.md +68 -4
  14. package/cli/agents/mission-scope-validator.md +40 -6
  15. package/cli/agents/project-context-extractor.md +21 -6
  16. package/cli/agents/scaffolding-generator.md +99 -0
  17. package/cli/agents/seed-validator.md +71 -0
  18. package/cli/agents/story-scope-reviewer.md +147 -0
  19. package/cli/agents/story-splitter.md +83 -0
  20. package/cli/agents/validator-documentation.json +31 -0
  21. package/cli/agents/validator-documentation.md +3 -1
  22. package/cli/api-reference-tool.js +368 -0
  23. package/cli/checks/catalog.json +76 -0
  24. package/cli/checks/code/quality.json +26 -0
  25. package/cli/checks/code/testing.json +14 -0
  26. package/cli/checks/code/traceability.json +26 -0
  27. package/cli/checks/cross-refs/epic.json +171 -0
  28. package/cli/checks/cross-refs/story.json +149 -0
  29. package/cli/checks/epic/api.json +114 -0
  30. package/cli/checks/epic/backend.json +126 -0
  31. package/cli/checks/epic/cloud.json +126 -0
  32. package/cli/checks/epic/data.json +102 -0
  33. package/cli/checks/epic/database.json +114 -0
  34. package/cli/checks/epic/developer.json +182 -0
  35. package/cli/checks/epic/devops.json +174 -0
  36. package/cli/checks/epic/frontend.json +162 -0
  37. package/cli/checks/epic/mobile.json +102 -0
  38. package/cli/checks/epic/qa.json +90 -0
  39. package/cli/checks/epic/security.json +184 -0
  40. package/cli/checks/epic/solution-architect.json +192 -0
  41. package/cli/checks/epic/test-architect.json +90 -0
  42. package/cli/checks/epic/ui.json +102 -0
  43. package/cli/checks/epic/ux.json +90 -0
  44. package/cli/checks/fixes/epic-fix-template.md +10 -0
  45. package/cli/checks/fixes/story-fix-template.md +10 -0
  46. package/cli/checks/story/api.json +186 -0
  47. package/cli/checks/story/backend.json +102 -0
  48. package/cli/checks/story/cloud.json +102 -0
  49. package/cli/checks/story/data.json +210 -0
  50. package/cli/checks/story/database.json +102 -0
  51. package/cli/checks/story/developer.json +168 -0
  52. package/cli/checks/story/devops.json +102 -0
  53. package/cli/checks/story/frontend.json +174 -0
  54. package/cli/checks/story/mobile.json +102 -0
  55. package/cli/checks/story/qa.json +210 -0
  56. package/cli/checks/story/security.json +198 -0
  57. package/cli/checks/story/solution-architect.json +230 -0
  58. package/cli/checks/story/test-architect.json +210 -0
  59. package/cli/checks/story/ui.json +102 -0
  60. package/cli/checks/story/ux.json +102 -0
  61. package/cli/coding-order.js +401 -0
  62. package/cli/dependency-checker.js +72 -0
  63. package/cli/epic-story-validator.js +284 -799
  64. package/cli/index.js +0 -0
  65. package/cli/init-model-config.js +17 -10
  66. package/cli/init.js +514 -92
  67. package/cli/kanban-server-manager.js +1 -2
  68. package/cli/llm-claude.js +98 -31
  69. package/cli/llm-gemini.js +29 -5
  70. package/cli/llm-local.js +493 -0
  71. package/cli/llm-openai.js +262 -41
  72. package/cli/llm-provider.js +147 -8
  73. package/cli/llm-token-limits.js +113 -4
  74. package/cli/llm-verifier.js +209 -1
  75. package/cli/llm-xiaomi.js +143 -0
  76. package/cli/message-constants.js +3 -12
  77. package/cli/messaging-api.js +6 -12
  78. package/cli/micro-check-fixer.js +335 -0
  79. package/cli/micro-check-runner.js +449 -0
  80. package/cli/micro-check-scorer.js +148 -0
  81. package/cli/micro-check-validator.js +538 -0
  82. package/cli/model-pricing.js +23 -0
  83. package/cli/model-selector.js +3 -2
  84. package/cli/prompt-logger.js +57 -0
  85. package/cli/repl-ink.js +106 -346
  86. package/cli/repl-old.js +1 -2
  87. package/cli/seed-processor.js +194 -24
  88. package/cli/sprint-planning-processor.js +2638 -289
  89. package/cli/template-processor.js +50 -3
  90. package/cli/token-tracker.js +50 -23
  91. package/cli/tools/generate-story-validators.js +1 -1
  92. package/cli/validation-router.js +70 -8
  93. package/cli/worktree-runner.js +654 -0
  94. package/kanban/client/dist/assets/index-D_KC5EQT.css +1 -0
  95. package/kanban/client/dist/assets/index-DjY5zqW7.js +351 -0
  96. package/kanban/client/dist/index.html +2 -2
  97. package/kanban/client/src/App.jsx +43 -14
  98. package/kanban/client/src/components/ceremony/AskArchPopup.jsx +7 -3
  99. package/kanban/client/src/components/ceremony/AskModelPopup.jsx +23 -10
  100. package/kanban/client/src/components/ceremony/CeremonyWorkflowModal.jsx +320 -133
  101. package/kanban/client/src/components/ceremony/ProviderSwitcherButton.jsx +290 -0
  102. package/kanban/client/src/components/ceremony/SponsorCallModal.jsx +80 -13
  103. package/kanban/client/src/components/ceremony/SprintPlanningModal.jsx +156 -22
  104. package/kanban/client/src/components/ceremony/steps/ArchitectureStep.jsx +11 -11
  105. package/kanban/client/src/components/ceremony/steps/CompleteStep.jsx +3 -21
  106. package/kanban/client/src/components/ceremony/steps/ReviewAnswersStep.jsx +214 -10
  107. package/kanban/client/src/components/ceremony/steps/RunningStep.jsx +23 -2
  108. package/kanban/client/src/components/kanban/CardDetailModal.jsx +97 -10
  109. package/kanban/client/src/components/kanban/GroupingSelector.jsx +7 -1
  110. package/kanban/client/src/components/kanban/KanbanCard.jsx +23 -14
  111. package/kanban/client/src/components/kanban/RefineWorkItemPopup.jsx +9 -14
  112. package/kanban/client/src/components/kanban/RunButton.jsx +162 -0
  113. package/kanban/client/src/components/kanban/SeedButton.jsx +176 -0
  114. package/kanban/client/src/components/settings/AgentsTab.jsx +103 -75
  115. package/kanban/client/src/components/settings/ApiKeysTab.jsx +31 -2
  116. package/kanban/client/src/components/settings/CeremonyModelsTab.jsx +9 -2
  117. package/kanban/client/src/components/settings/CheckEditorPopup.jsx +507 -0
  118. package/kanban/client/src/components/settings/CostThresholdsTab.jsx +3 -2
  119. package/kanban/client/src/components/settings/ModelPricingTab.jsx +72 -7
  120. package/kanban/client/src/components/settings/OpenAIAuthSection.jsx +412 -0
  121. package/kanban/client/src/components/settings/SettingsModal.jsx +4 -4
  122. package/kanban/client/src/components/stats/CostModal.jsx +34 -3
  123. package/kanban/client/src/hooks/useGrouping.js +59 -0
  124. package/kanban/client/src/lib/api.js +118 -4
  125. package/kanban/client/src/lib/status-grouping.js +10 -0
  126. package/kanban/client/src/store/kanbanStore.js +8 -0
  127. package/kanban/server/index.js +23 -2
  128. package/kanban/server/routes/ceremony.js +153 -4
  129. package/kanban/server/routes/costs.js +9 -3
  130. package/kanban/server/routes/openai-oauth.js +366 -0
  131. package/kanban/server/routes/settings.js +447 -14
  132. package/kanban/server/routes/websocket.js +7 -2
  133. package/kanban/server/routes/work-items.js +141 -1
  134. package/kanban/server/services/CeremonyService.js +275 -24
  135. package/kanban/server/services/TaskRunnerService.js +261 -0
  136. package/kanban/server/workers/run-task-worker.js +121 -0
  137. package/kanban/server/workers/seed-worker.js +94 -0
  138. package/kanban/server/workers/sponsor-call-worker.js +14 -6
  139. package/kanban/server/workers/sprint-planning-worker.js +94 -12
  140. package/package.json +2 -3
  141. package/cli/agents/solver-epic-api.json +0 -15
  142. package/cli/agents/solver-epic-api.md +0 -39
  143. package/cli/agents/solver-epic-backend.json +0 -15
  144. package/cli/agents/solver-epic-backend.md +0 -39
  145. package/cli/agents/solver-epic-cloud.json +0 -15
  146. package/cli/agents/solver-epic-cloud.md +0 -39
  147. package/cli/agents/solver-epic-data.json +0 -15
  148. package/cli/agents/solver-epic-data.md +0 -39
  149. package/cli/agents/solver-epic-database.json +0 -15
  150. package/cli/agents/solver-epic-database.md +0 -39
  151. package/cli/agents/solver-epic-developer.json +0 -15
  152. package/cli/agents/solver-epic-developer.md +0 -39
  153. package/cli/agents/solver-epic-devops.json +0 -15
  154. package/cli/agents/solver-epic-devops.md +0 -39
  155. package/cli/agents/solver-epic-frontend.json +0 -15
  156. package/cli/agents/solver-epic-frontend.md +0 -39
  157. package/cli/agents/solver-epic-mobile.json +0 -15
  158. package/cli/agents/solver-epic-mobile.md +0 -39
  159. package/cli/agents/solver-epic-qa.json +0 -15
  160. package/cli/agents/solver-epic-qa.md +0 -39
  161. package/cli/agents/solver-epic-security.json +0 -15
  162. package/cli/agents/solver-epic-security.md +0 -39
  163. package/cli/agents/solver-epic-solution-architect.json +0 -15
  164. package/cli/agents/solver-epic-solution-architect.md +0 -39
  165. package/cli/agents/solver-epic-test-architect.json +0 -15
  166. package/cli/agents/solver-epic-test-architect.md +0 -39
  167. package/cli/agents/solver-epic-ui.json +0 -15
  168. package/cli/agents/solver-epic-ui.md +0 -39
  169. package/cli/agents/solver-epic-ux.json +0 -15
  170. package/cli/agents/solver-epic-ux.md +0 -39
  171. package/cli/agents/solver-story-api.json +0 -15
  172. package/cli/agents/solver-story-api.md +0 -39
  173. package/cli/agents/solver-story-backend.json +0 -15
  174. package/cli/agents/solver-story-backend.md +0 -39
  175. package/cli/agents/solver-story-cloud.json +0 -15
  176. package/cli/agents/solver-story-cloud.md +0 -39
  177. package/cli/agents/solver-story-data.json +0 -15
  178. package/cli/agents/solver-story-data.md +0 -39
  179. package/cli/agents/solver-story-database.json +0 -15
  180. package/cli/agents/solver-story-database.md +0 -39
  181. package/cli/agents/solver-story-developer.json +0 -15
  182. package/cli/agents/solver-story-developer.md +0 -39
  183. package/cli/agents/solver-story-devops.json +0 -15
  184. package/cli/agents/solver-story-devops.md +0 -39
  185. package/cli/agents/solver-story-frontend.json +0 -15
  186. package/cli/agents/solver-story-frontend.md +0 -39
  187. package/cli/agents/solver-story-mobile.json +0 -15
  188. package/cli/agents/solver-story-mobile.md +0 -39
  189. package/cli/agents/solver-story-qa.json +0 -15
  190. package/cli/agents/solver-story-qa.md +0 -39
  191. package/cli/agents/solver-story-security.json +0 -15
  192. package/cli/agents/solver-story-security.md +0 -39
  193. package/cli/agents/solver-story-solution-architect.json +0 -15
  194. package/cli/agents/solver-story-solution-architect.md +0 -39
  195. package/cli/agents/solver-story-test-architect.json +0 -15
  196. package/cli/agents/solver-story-test-architect.md +0 -39
  197. package/cli/agents/solver-story-ui.json +0 -15
  198. package/cli/agents/solver-story-ui.md +0 -39
  199. package/cli/agents/solver-story-ux.json +0 -15
  200. package/cli/agents/solver-story-ux.md +0 -39
  201. package/cli/agents/validator-epic-api.json +0 -93
  202. package/cli/agents/validator-epic-api.md +0 -137
  203. package/cli/agents/validator-epic-backend.json +0 -93
  204. package/cli/agents/validator-epic-backend.md +0 -130
  205. package/cli/agents/validator-epic-cloud.json +0 -93
  206. package/cli/agents/validator-epic-cloud.md +0 -137
  207. package/cli/agents/validator-epic-data.json +0 -93
  208. package/cli/agents/validator-epic-data.md +0 -130
  209. package/cli/agents/validator-epic-database.json +0 -93
  210. package/cli/agents/validator-epic-database.md +0 -137
  211. package/cli/agents/validator-epic-developer.json +0 -74
  212. package/cli/agents/validator-epic-developer.md +0 -153
  213. package/cli/agents/validator-epic-devops.json +0 -74
  214. package/cli/agents/validator-epic-devops.md +0 -153
  215. package/cli/agents/validator-epic-frontend.json +0 -74
  216. package/cli/agents/validator-epic-frontend.md +0 -153
  217. package/cli/agents/validator-epic-mobile.json +0 -93
  218. package/cli/agents/validator-epic-mobile.md +0 -130
  219. package/cli/agents/validator-epic-qa.json +0 -93
  220. package/cli/agents/validator-epic-qa.md +0 -130
  221. package/cli/agents/validator-epic-security.json +0 -74
  222. package/cli/agents/validator-epic-security.md +0 -154
  223. package/cli/agents/validator-epic-solution-architect.json +0 -74
  224. package/cli/agents/validator-epic-solution-architect.md +0 -156
  225. package/cli/agents/validator-epic-test-architect.json +0 -93
  226. package/cli/agents/validator-epic-test-architect.md +0 -130
  227. package/cli/agents/validator-epic-ui.json +0 -93
  228. package/cli/agents/validator-epic-ui.md +0 -130
  229. package/cli/agents/validator-epic-ux.json +0 -93
  230. package/cli/agents/validator-epic-ux.md +0 -130
  231. package/cli/agents/validator-story-api.json +0 -104
  232. package/cli/agents/validator-story-api.md +0 -152
  233. package/cli/agents/validator-story-backend.json +0 -104
  234. package/cli/agents/validator-story-backend.md +0 -152
  235. package/cli/agents/validator-story-cloud.json +0 -104
  236. package/cli/agents/validator-story-cloud.md +0 -152
  237. package/cli/agents/validator-story-data.json +0 -104
  238. package/cli/agents/validator-story-data.md +0 -152
  239. package/cli/agents/validator-story-database.json +0 -104
  240. package/cli/agents/validator-story-database.md +0 -152
  241. package/cli/agents/validator-story-developer.json +0 -104
  242. package/cli/agents/validator-story-developer.md +0 -152
  243. package/cli/agents/validator-story-devops.json +0 -104
  244. package/cli/agents/validator-story-devops.md +0 -152
  245. package/cli/agents/validator-story-frontend.json +0 -104
  246. package/cli/agents/validator-story-frontend.md +0 -152
  247. package/cli/agents/validator-story-mobile.json +0 -104
  248. package/cli/agents/validator-story-mobile.md +0 -152
  249. package/cli/agents/validator-story-qa.json +0 -104
  250. package/cli/agents/validator-story-qa.md +0 -152
  251. package/cli/agents/validator-story-security.json +0 -104
  252. package/cli/agents/validator-story-security.md +0 -152
  253. package/cli/agents/validator-story-solution-architect.json +0 -104
  254. package/cli/agents/validator-story-solution-architect.md +0 -152
  255. package/cli/agents/validator-story-test-architect.json +0 -104
  256. package/cli/agents/validator-story-test-architect.md +0 -152
  257. package/cli/agents/validator-story-ui.json +0 -104
  258. package/cli/agents/validator-story-ui.md +0 -152
  259. package/cli/agents/validator-story-ux.json +0 -104
  260. package/cli/agents/validator-story-ux.md +0 -152
  261. package/kanban/client/dist/assets/index-CiD8PS2e.js +0 -306
  262. package/kanban/client/dist/assets/index-nLh0m82Q.css +0 -1
@@ -1,6 +1,8 @@
1
1
  import { useState } from 'react';
2
2
  import { X, Pencil } from 'lucide-react';
3
3
  import { AgentEditorPopup } from '../settings/AgentEditorPopup';
4
+ import { CheckEditorPopup } from '../settings/CheckEditorPopup';
5
+ import { ProviderSwitcherButton } from './ProviderSwitcherButton';
4
6
 
5
7
  // Human-readable labels for agent slugs
6
8
  const AGENT_LABELS = {
@@ -21,8 +23,15 @@ const AGENT_LABELS = {
21
23
  'feature-context-generator': 'Feature Context Generator',
22
24
  // Sprint Planning
23
25
  'epic-story-decomposer': 'Epic/Story Decomposer',
26
+ 'story-scope-reviewer': 'Story Scope Reviewer',
24
27
  'project-context-extractor': 'Project Context Extractor',
25
28
  'agent-selector': 'Agent Selector',
29
+ 'context-writer-epic': 'Context Writer (Epic)',
30
+ 'context-reviewer-epic': 'Context Reviewer (Epic)',
31
+ 'context-writer-story': 'Context Writer (Story)',
32
+ 'context-reviewer-story': 'Context Reviewer (Story)',
33
+ 'doc-writer-epic': 'Doc Writer (Epic)',
34
+ 'doc-writer-story': 'Doc Writer (Story)',
26
35
  'story-doc-enricher': 'Story Doc Enricher',
27
36
  'validator-selector': 'Validator Selector',
28
37
  'validator-epic-solution-architect': 'Solution Architect (Epic)',
@@ -39,40 +48,17 @@ const AGENT_LABELS = {
39
48
  'validator-story-backend': 'Backend (Story)',
40
49
  'validator-story-frontend': 'Frontend (Story)',
41
50
  'validator-story-ux': 'UX (Story)',
42
- // Sprint Planning — Epic Solvers
43
- 'solver-epic-solution-architect': 'Solver: Solution Architect (Epic)',
44
- 'solver-epic-developer': 'Solver: Developer (Epic)',
45
- 'solver-epic-security': 'Solver: Security (Epic)',
46
- 'solver-epic-devops': 'Solver: DevOps (Epic)',
47
- 'solver-epic-cloud': 'Solver: Cloud (Epic)',
48
- 'solver-epic-backend': 'Solver: Backend (Epic)',
49
- 'solver-epic-database': 'Solver: Database (Epic)',
50
- 'solver-epic-api': 'Solver: API (Epic)',
51
- 'solver-epic-frontend': 'Solver: Frontend (Epic)',
52
- 'solver-epic-ui': 'Solver: UI (Epic)',
53
- 'solver-epic-ux': 'Solver: UX (Epic)',
54
- 'solver-epic-mobile': 'Solver: Mobile (Epic)',
55
- 'solver-epic-data': 'Solver: Data (Epic)',
56
- 'solver-epic-qa': 'Solver: QA (Epic)',
57
- 'solver-epic-test-architect': 'Solver: Test Architect (Epic)',
58
- // Sprint Planning — Story Solvers
59
- 'solver-story-solution-architect': 'Solver: Solution Architect (Story)',
60
- 'solver-story-developer': 'Solver: Developer (Story)',
61
- 'solver-story-security': 'Solver: Security (Story)',
62
- 'solver-story-devops': 'Solver: DevOps (Story)',
63
- 'solver-story-cloud': 'Solver: Cloud (Story)',
64
- 'solver-story-backend': 'Solver: Backend (Story)',
65
- 'solver-story-database': 'Solver: Database (Story)',
66
- 'solver-story-api': 'Solver: API (Story)',
67
- 'solver-story-frontend': 'Solver: Frontend (Story)',
68
- 'solver-story-ui': 'Solver: UI (Story)',
69
- 'solver-story-ux': 'Solver: UX (Story)',
70
- 'solver-story-mobile': 'Solver: Mobile (Story)',
71
- 'solver-story-data': 'Solver: Data (Story)',
72
- 'solver-story-qa': 'Solver: QA (Story)',
73
- 'solver-story-test-architect': 'Solver: Test Architect (Story)',
51
+ 'story-splitter': 'Story Splitter',
74
52
  };
75
53
 
54
+ // ── Domain check perspectives (matching src/cli/checks/{epic|story}/*.json) ──
55
+
56
+ const DOMAIN_CHECK_PERSPECTIVES = [
57
+ 'solution-architect', 'developer', 'security', 'devops', 'cloud',
58
+ 'backend', 'database', 'api', 'frontend', 'ui', 'ux',
59
+ 'mobile', 'data', 'qa', 'test-architect',
60
+ ];
61
+
76
62
  // ── Step type config ──────────────────────────────────────────────────────────
77
63
 
78
64
  const STEP_TYPE_CONFIG = {
@@ -264,8 +250,6 @@ function buildSponsorCallPhases(ceremony, missionGenValidation) {
264
250
  function buildSprintPlanningPhases(ceremony) {
265
251
  // Stages that aren't explicitly configured fall back to ceremony.defaultModel
266
252
  const fallbackModel = ceremony.defaultModel;
267
- const solverMaxIter = ceremony.stages?.solver?.maxIterations ?? 3;
268
- const solverThreshold = ceremony.stages?.solver?.acceptanceThreshold ?? 95;
269
253
 
270
254
  return [
271
255
  {
@@ -296,15 +280,51 @@ function buildSprintPlanningPhases(ceremony) {
296
280
  { name: 'project/doc.md', direction: 'in', note: 'scope text extracted from doc.md' },
297
281
  ],
298
282
  },
283
+ {
284
+ type: 'generate',
285
+ label: 'Detect semantic duplicates among new epics and against existing on-disk epics — merge overlapping items automatically',
286
+ model: ceremony.stages?.decomposition?.model ?? fallbackModel,
287
+ stageKey: 'decomposition',
288
+ sharedWith: 'Decomposer',
289
+ agent: 'duplicate-detector',
290
+ },
291
+ {
292
+ type: 'process',
293
+ label: 'Review each Epic\'s stories and split any that mix too many concerns (one LLM call per Epic in parallel)',
294
+ model: ceremony.stages?.decomposition?.model ?? fallbackModel,
295
+ stageKey: 'decomposition',
296
+ sharedWith: 'Decomposer',
297
+ agent: 'story-scope-reviewer',
298
+ },
299
+ ],
300
+ },
301
+ {
302
+ id: 'context-generation',
303
+ label: 'Context Generation',
304
+ color: 'violet',
305
+ steps: [
306
+ {
307
+ type: 'generate',
308
+ label: 'Write + independently review each Epic/Story context.md (Write → Review → Refine, up to 3 rounds per item)',
309
+ model: ceremony.stages?.['context-generation']?.model ?? fallbackModel,
310
+ stageKey: 'context-generation',
311
+ agents: [
312
+ { slug: 'context-writer-epic', note: 'writes epic context.md' },
313
+ { slug: 'context-reviewer-epic', note: 'audits epic context against source JSON' },
314
+ { slug: 'context-writer-story', note: 'writes story context.md' },
315
+ { slug: 'context-reviewer-story', note: 'audits story context against source JSON' },
316
+ ],
317
+ files: [
318
+ { name: '{epic}/context.md', direction: 'out' },
319
+ { name: '{story}/context.md', direction: 'out' },
320
+ ],
321
+ },
299
322
  ],
300
323
  },
301
324
  {
302
325
  id: 'validation',
303
- label: 'Multi-Agent Validation (Iterative)',
326
+ label: 'Micro-Check Validation (3-Tier)',
304
327
  color: 'amber',
305
- // Per-validator iteration loop: each validator runs, if issues found a paired
306
- // solver improves the epic/story, then the same validator re-validates.
307
- // Validators run sequentially so each one sees improvements from previous pairs.
308
328
  steps: [
309
329
  {
310
330
  type: 'generate',
@@ -322,74 +342,49 @@ function buildSprintPlanningPhases(ceremony) {
322
342
  agent: 'agent-selector',
323
343
  },
324
344
  {
325
- type: 'loop-group',
326
- loopParamType: 'sprintSolver',
327
- loop: {
328
- max: solverMaxIter,
329
- threshold: solverThreshold,
330
- },
331
- steps: [
332
- {
333
- type: 'validate',
334
- label: 'Validate each Epic with domain expert validators (sequential)',
335
- model: ceremony.stages?.validation?.model ?? fallbackModel,
336
- stageKey: 'validation',
337
- agents: [
338
- { slug: 'validator-epic-solution-architect', note: 'always runs' },
339
- { slug: 'validator-epic-developer', note: 'always runs' },
340
- { slug: 'validator-epic-security', note: 'always runs' },
341
- { slug: 'validator-epic-backend', note: '+ domain validators selected per project' },
342
- ],
343
- },
344
- {
345
- type: 'refine',
346
- label: 'Solve issues — improve Epic description, features, dependencies',
347
- model: ceremony.stages?.solver?.model ?? fallbackModel,
348
- stageKey: 'solver',
349
- agents: [
350
- { slug: 'solver-epic-solution-architect', note: 'paired with validator-epic-solution-architect' },
351
- { slug: 'solver-epic-developer', note: 'paired with validator-epic-developer' },
352
- { slug: 'solver-epic-security', note: 'paired with validator-epic-security' },
353
- { slug: 'solver-epic-backend', note: 'paired with each domain validator' },
354
- ],
355
- },
345
+ type: 'validate',
346
+ label: 'Tier 1: Run domain checks per perspective — each check is 1-2 YES/NO LLM calls, run in parallel',
347
+ model: ceremony.stages?.validation?.model ?? fallbackModel,
348
+ stageKey: 'validation',
349
+ sharedWith: 'Validation',
350
+ params: [
351
+ { key: 'concurrency', label: 'Parallel checks', value: ceremony.stages?.validation?.concurrency ?? 5, min: 1, max: 20 },
352
+ { key: 'batchSize', label: 'Checks per batch', value: ceremony.stages?.validation?.batchSize ?? 8, min: 1, max: 20 },
356
353
  ],
354
+ checks: DOMAIN_CHECK_PERSPECTIVES.flatMap(p => [
355
+ { scope: 'epic', perspective: p, label: `${p} (Epic)` },
356
+ { scope: 'story', perspective: p, label: `${p} (Story)` },
357
+ ]),
357
358
  },
358
359
  {
359
- type: 'loop-group',
360
- loopParamType: 'sprintSolver',
361
- loopParamReadOnly: true,
362
- loop: {
363
- max: solverMaxIter,
364
- threshold: solverThreshold,
365
- },
366
- steps: [
367
- {
368
- type: 'validate',
369
- label: 'Validate each Story with domain expert validators (sequential)',
370
- model: ceremony.stages?.validation?.model ?? fallbackModel,
371
- stageKey: 'validation',
372
- agents: [
373
- { slug: 'validator-story-developer', note: 'always runs' },
374
- { slug: 'validator-story-qa', note: 'always runs' },
375
- { slug: 'validator-story-test-architect', note: 'always runs' },
376
- { slug: 'validator-story-backend', note: '+ domain validators selected per project' },
377
- ],
378
- },
379
- {
380
- type: 'refine',
381
- label: 'Solve issues — improve Story description, acceptance criteria, dependencies',
382
- model: ceremony.stages?.solver?.model ?? fallbackModel,
383
- stageKey: 'solver',
384
- agents: [
385
- { slug: 'solver-story-developer', note: 'paired with validator-story-developer' },
386
- { slug: 'solver-story-qa', note: 'paired with validator-story-qa' },
387
- { slug: 'solver-story-test-architect', note: 'paired with validator-story-test-architect' },
388
- { slug: 'solver-story-backend', note: 'paired with each domain validator' },
389
- ],
390
- },
360
+ type: 'cross',
361
+ label: 'Tier 2: Cross-reference consistency checks — verify perspectives agree (e.g., security \u2194 API, database \u2194 architecture). Runs after Tier 1 using evidence from domain checks.',
362
+ model: ceremony.stages?.validation?.model ?? fallbackModel,
363
+ stageKey: 'validation',
364
+ sharedWith: 'Validation',
365
+ checks: [
366
+ { scope: 'cross-refs', perspective: 'epic', label: 'Epic Cross-Refs' },
367
+ { scope: 'cross-refs', perspective: 'story', label: 'Story Cross-Refs' },
368
+ ],
369
+ },
370
+ {
371
+ type: 'refine',
372
+ label: 'Tier 3: Deterministic scoring + auto-fix critical/major failures (atomic per-check fixes with regression revert)',
373
+ model: ceremony.stages?.validation?.model ?? fallbackModel,
374
+ stageKey: 'validation',
375
+ sharedWith: 'Validation',
376
+ params: [
377
+ { key: 'maxFixAttempts', label: 'Max fix attempts', value: ceremony.stages?.validation?.maxFixAttempts ?? 3, min: 0, max: 10 },
391
378
  ],
392
379
  },
380
+ {
381
+ type: 'process',
382
+ label: 'If story still below threshold with 15+ ACs and scope issues detected: split into 2-3 focused stories, replace in epic, and re-validate each split story',
383
+ model: ceremony.stages?.validation?.model ?? fallbackModel,
384
+ stageKey: 'validation',
385
+ sharedWith: 'Validation',
386
+ agent: 'story-splitter',
387
+ },
393
388
  ],
394
389
  },
395
390
  {
@@ -397,27 +392,29 @@ function buildSprintPlanningPhases(ceremony) {
397
392
  label: 'Documentation & Output',
398
393
  color: 'emerald',
399
394
  steps: [
400
- { type: 'process', label: 'Renumber hierarchy IDs' },
395
+ { type: 'process', label: 'Renumber hierarchy IDs + write context.md files with final IDs' },
401
396
  {
402
397
  type: 'generate',
403
- label: 'Distribute documentation — extract Epic-specific content from project/doc.md into each Epic\'s doc.md (moves content, doesn\'t copy)',
404
- model: ceremony.stages?.['doc-distribution']?.model ?? fallbackModel,
405
- stageKey: 'doc-distribution',
406
- agent: 'doc-distributor',
398
+ label: 'Generate narrative doc.md for each Epic from its canonical context.md',
399
+ model: ceremony.stages?.['doc-generation']?.model ?? fallbackModel,
400
+ stageKey: 'doc-generation',
401
+ agent: 'doc-writer-epic',
407
402
  files: [
408
- { name: 'project/doc.md', direction: 'in', note: 'source — progressively lightened as epics extract their content' },
409
- { name: '{epic}/doc.md', direction: 'out', note: 'receives content extracted from project doc' },
403
+ { name: 'project/doc.md', direction: 'in', note: 'project context' },
404
+ { name: '{epic}/context.md', direction: 'in', note: 'canonical spec single source of truth' },
405
+ { name: '{epic}/doc.md', direction: 'out', note: 'narrative documentation' },
410
406
  ],
411
407
  },
412
408
  {
413
409
  type: 'generate',
414
- label: 'Distribute documentation — extract Story-specific content from each Epic\'s doc.md into each Story\'s doc.md',
415
- model: ceremony.stages?.['doc-distribution']?.model ?? fallbackModel,
416
- stageKey: 'doc-distribution',
417
- agent: 'doc-distributor',
410
+ label: 'Generate narrative doc.md for each Story from its canonical context.md',
411
+ model: ceremony.stages?.['doc-generation']?.model ?? fallbackModel,
412
+ stageKey: 'doc-generation',
413
+ agent: 'doc-writer-story',
418
414
  files: [
419
- { name: '{epic}/doc.md', direction: 'in', note: 'source progressively lightened as stories extract their content' },
420
- { name: '{story}/doc.md', direction: 'out', note: 'receives content extracted from epic doc' },
415
+ { name: '{epic}/context.md', direction: 'in', note: 'parent epic context' },
416
+ { name: '{story}/context.md', direction: 'in', note: 'canonical spec single source of truth' },
417
+ { name: '{story}/doc.md', direction: 'out', note: 'narrative documentation' },
421
418
  ],
422
419
  },
423
420
  {
@@ -442,12 +439,113 @@ function buildSprintPlanningPhases(ceremony) {
442
439
  },
443
440
  ];
444
441
  }
445
- function buildSeedPhases(_c) { return null; }
442
+ function buildSeedPhases(c) {
443
+ return [
444
+ {
445
+ id: 'decompose',
446
+ label: 'Decompose Story',
447
+ color: 'blue',
448
+ steps: [
449
+ {
450
+ type: 'read',
451
+ label: 'Read story, epic, and project context',
452
+ },
453
+ {
454
+ type: 'generate',
455
+ label: 'Decompose story into tasks and subtasks',
456
+ model: c?.stages?.decomposition?.model,
457
+ stageKey: 'decomposition',
458
+ agent: 'task-subtask-decomposer',
459
+ },
460
+ {
461
+ type: 'process',
462
+ label: 'Validate task/subtask structure and IDs (deterministic)',
463
+ },
464
+ ],
465
+ },
466
+ {
467
+ id: 'context-gen',
468
+ label: 'Task Documentation',
469
+ color: 'green',
470
+ steps: [
471
+ {
472
+ type: 'generate',
473
+ label: 'Generate context.md for each task and subtask',
474
+ model: c?.stages?.['context-generation']?.model,
475
+ stageKey: 'context-generation',
476
+ },
477
+ {
478
+ type: 'output',
479
+ label: 'Write work.json, context.md, and doc.md files',
480
+ },
481
+ ],
482
+ },
483
+ ];
484
+ }
485
+
486
+ function buildRunPhases(c) {
487
+ return [
488
+ {
489
+ id: 'implement',
490
+ label: 'Code Generation',
491
+ color: 'blue',
492
+ steps: [
493
+ {
494
+ type: 'read',
495
+ label: 'Create git worktree and read documentation chain',
496
+ },
497
+ {
498
+ type: 'generate',
499
+ label: 'AI generates code following traceability rules',
500
+ model: c?.stages?.['code-generation']?.model,
501
+ stageKey: 'code-generation',
502
+ agent: 'code-implementer',
503
+ },
504
+ ],
505
+ },
506
+ {
507
+ id: 'validate',
508
+ label: 'Code Validation',
509
+ color: 'amber',
510
+ steps: [
511
+ {
512
+ type: 'validate',
513
+ label: 'Verify code against quality and traceability checks',
514
+ model: c?.stages?.['code-validation']?.model,
515
+ stageKey: 'code-validation',
516
+ agent: 'code-validator',
517
+ },
518
+ {
519
+ type: 'generate',
520
+ label: 'Fix violations and regenerate (if needed, up to 3 iterations)',
521
+ model: c?.stages?.['code-generation']?.model,
522
+ stageKey: 'code-generation',
523
+ },
524
+ ],
525
+ },
526
+ {
527
+ id: 'test-merge',
528
+ label: 'Test & Merge',
529
+ color: 'green',
530
+ steps: [
531
+ {
532
+ type: 'validate',
533
+ label: 'Run tests in worktree',
534
+ },
535
+ {
536
+ type: 'output',
537
+ label: 'Commit, merge to main, update function registry',
538
+ },
539
+ ],
540
+ },
541
+ ];
542
+ }
446
543
 
447
544
  const CEREMONY_WORKFLOWS = {
448
545
  'sponsor-call': buildSponsorCallPhases,
449
546
  'sprint-planning': (c) => buildSprintPlanningPhases(c),
450
- 'seed': (_c) => buildSeedPhases(_c),
547
+ 'seed': (c) => buildSeedPhases(c),
548
+ 'run': (c) => buildRunPhases(c),
451
549
  };
452
550
 
453
551
  // ── Helpers ───────────────────────────────────────────────────────────────────
@@ -521,6 +619,33 @@ function AgentLinks({ step, onOpenAgent }) {
521
619
  );
522
620
  }
523
621
 
622
+ // ── Check links ──────────────────────────────────────────────────────────────
623
+ // Renders clickable check-definition badges inside a scrollable container.
624
+
625
+ function CheckLinks({ step, onOpenCheck }) {
626
+ if (!step.checks || step.checks.length === 0) return null;
627
+
628
+ return (
629
+ <div className="mt-1.5">
630
+ <span className="text-[10px] text-slate-400 font-medium">Check definitions</span>
631
+ <div className="mt-1 max-h-28 overflow-y-auto border border-slate-100 rounded-md px-1.5 py-1 flex flex-wrap gap-1">
632
+ {step.checks.map((c) => (
633
+ <button
634
+ key={`${c.scope}/${c.perspective}`}
635
+ type="button"
636
+ onClick={() => onOpenCheck({ scope: c.scope, perspective: c.perspective })}
637
+ className="inline-flex items-center gap-1 text-[10px] font-medium text-amber-700 hover:text-amber-900 bg-amber-50 hover:bg-amber-100 border border-amber-200 hover:border-amber-300 px-1.5 py-0.5 rounded transition-colors whitespace-nowrap"
638
+ title={`Edit ${c.scope}/${c.perspective}.json`}
639
+ >
640
+ {c.label}
641
+ <Pencil className="w-2.5 h-2.5 flex-shrink-0" />
642
+ </button>
643
+ ))}
644
+ </div>
645
+ </div>
646
+ );
647
+ }
648
+
524
649
  // ── File tags ─────────────────────────────────────────────────────────────────
525
650
  // Renders small ← filename (input) / → filename (output) badges on step cards.
526
651
  // Steps can carry a `files` array: [{ name, direction: 'in'|'out', note? }]
@@ -566,7 +691,7 @@ function StepBadge({ type }) {
566
691
 
567
692
  // ── Plain step card ───────────────────────────────────────────────────────────
568
693
 
569
- function StepCard({ step, models, editable, onStageModelChange, onValidationModelChange, onOpenAgent }) {
694
+ function StepCard({ step, models, editable, onStageModelChange, onValidationModelChange, onStageParamChange, onOpenAgent, onOpenCheck }) {
570
695
  const showModel = !['input', 'output', 'read', 'process'].includes(step.type);
571
696
  const canEdit = editable && !step.sharedWith && (step.stageKey || step.validationKey);
572
697
 
@@ -604,14 +729,39 @@ function StepCard({ step, models, editable, onStageModelChange, onValidationMode
604
729
 
605
730
  <div className="pl-1">
606
731
  <AgentLinks step={step} onOpenAgent={onOpenAgent} />
732
+ {onOpenCheck && <CheckLinks step={step} onOpenCheck={onOpenCheck} />}
607
733
  </div>
734
+
735
+ {/* Inline params (e.g. concurrency, maxFixAttempts) */}
736
+ {step.params && step.params.length > 0 && (
737
+ <div className="mt-2 pl-1 flex items-center gap-3 flex-wrap">
738
+ {step.params.map((p) => (
739
+ <label key={p.key} className="flex items-center gap-1.5 text-[11px] text-slate-600">
740
+ <span className="font-medium">{p.label}:</span>
741
+ {editable && step.stageKey && onStageParamChange ? (
742
+ <input
743
+ type="number"
744
+ min={p.min}
745
+ max={p.max}
746
+ value={p.value}
747
+ onChange={(e) => onStageParamChange(step.stageKey, p.key, Number(e.target.value))}
748
+ onClick={(e) => e.stopPropagation()}
749
+ className="w-12 text-xs border border-slate-300 rounded px-1.5 py-0.5 bg-white text-slate-800 text-center focus:outline-none focus:ring-1 focus:ring-blue-400"
750
+ />
751
+ ) : (
752
+ <span className="font-mono">{p.value}</span>
753
+ )}
754
+ </label>
755
+ ))}
756
+ </div>
757
+ )}
608
758
  </div>
609
759
  );
610
760
  }
611
761
 
612
762
  // ── Loop group card ───────────────────────────────────────────────────────────
613
763
 
614
- function LoopGroupCard({ group, models, editable, onStageModelChange, onValidationModelChange, onLoopParamChange, onOpenAgent }) {
764
+ function LoopGroupCard({ group, models, editable, onStageModelChange, onValidationModelChange, onStageParamChange, onLoopParamChange, onOpenAgent, onOpenCheck }) {
615
765
  const { loop, steps } = group;
616
766
  const isIndigo = steps.some((s) => s.type === 'cross');
617
767
  const c = isIndigo ? LOOP_C.indigo : LOOP_C.amber;
@@ -677,7 +827,9 @@ function LoopGroupCard({ group, models, editable, onStageModelChange, onValidati
677
827
  editable={editable}
678
828
  onStageModelChange={onStageModelChange}
679
829
  onValidationModelChange={onValidationModelChange}
830
+ onStageParamChange={onStageParamChange}
680
831
  onOpenAgent={onOpenAgent}
832
+ onOpenCheck={onOpenCheck}
681
833
  />
682
834
  {i < steps.length - 1 && (
683
835
  <div className="flex items-center gap-2 my-1.5 ml-3">
@@ -729,10 +881,13 @@ function Connector() {
729
881
 
730
882
  export function CeremonyWorkflowModal({
731
883
  ceremony,
884
+ allCeremonies,
885
+ apiKeys,
732
886
  models = [],
733
887
  missionGenValidation = null,
734
888
  onClose,
735
889
  onSave,
890
+ onCeremoniesUpdated,
736
891
  readOnly = false,
737
892
  }) {
738
893
  const [draft, setDraft] = useState(() => JSON.parse(JSON.stringify(ceremony || {})));
@@ -742,6 +897,7 @@ export function CeremonyWorkflowModal({
742
897
  const [saving, setSaving] = useState(false);
743
898
  const [saveError, setSaveError] = useState(null);
744
899
  const [openAgentSlug, setOpenAgentSlug] = useState(null);
900
+ const [openCheck, setOpenCheck] = useState(null); // { scope, perspective } | null
745
901
 
746
902
  // Phases rebuild from draft every render — always reflect current edits
747
903
  const buildPhases = ceremony?.name ? CEREMONY_WORKFLOWS[ceremony.name] : null;
@@ -792,19 +948,24 @@ export function CeremonyWorkflowModal({
792
948
  }
793
949
  };
794
950
 
951
+ const updateStageParam = (stageKey, paramKey, value) => {
952
+ setDraft((prev) => ({
953
+ ...prev,
954
+ stages: {
955
+ ...prev.stages,
956
+ [stageKey]: {
957
+ ...prev.stages?.[stageKey],
958
+ [paramKey]: value,
959
+ },
960
+ },
961
+ }));
962
+ };
963
+
795
964
  const updateLoopParam = (loopParamType, field, value) => {
796
965
  if (loopParamType === 'missionGen') {
797
966
  setMissionGenDraft((prev) => ({ ...prev, [field]: value }));
798
967
  } else if (loopParamType === 'docContext') {
799
968
  setDraft((prev) => ({ ...prev, validation: { ...prev.validation, [field]: value } }));
800
- } else if (loopParamType === 'sprintSolver') {
801
- setDraft((prev) => ({
802
- ...prev,
803
- stages: {
804
- ...prev.stages,
805
- solver: { ...(prev.stages?.solver || {}), [field]: value },
806
- },
807
- }));
808
969
  }
809
970
  };
810
971
 
@@ -851,13 +1012,27 @@ export function CeremonyWorkflowModal({
851
1012
  {ceremony?.displayName || ceremony?.name || 'Unknown ceremony'}
852
1013
  </p>
853
1014
  </div>
854
- <button
855
- type="button"
856
- onClick={isEditable ? handleCancel : onClose}
857
- className="text-slate-400 hover:text-slate-600 transition-colors"
858
- >
859
- <X className="w-4 h-4" />
860
- </button>
1015
+ <div className="flex items-center gap-2">
1016
+ {isEditable && allCeremonies && (
1017
+ <ProviderSwitcherButton
1018
+ ceremonyName={ceremony?.name}
1019
+ ceremonies={allCeremonies.map((c) => c.name === ceremony?.name ? draft : c)}
1020
+ apiKeys={apiKeys}
1021
+ onApplied={(updated) => {
1022
+ const updatedCeremony = updated.find((c) => c.name === ceremony?.name);
1023
+ if (updatedCeremony) setDraft(JSON.parse(JSON.stringify(updatedCeremony)));
1024
+ onCeremoniesUpdated?.(updated);
1025
+ }}
1026
+ />
1027
+ )}
1028
+ <button
1029
+ type="button"
1030
+ onClick={isEditable ? handleCancel : onClose}
1031
+ className="text-slate-400 hover:text-slate-600 transition-colors"
1032
+ >
1033
+ <X className="w-4 h-4" />
1034
+ </button>
1035
+ </div>
861
1036
  </div>
862
1037
 
863
1038
  {/* Scrollable body */}
@@ -879,8 +1054,10 @@ export function CeremonyWorkflowModal({
879
1054
  editable={isEditable}
880
1055
  onStageModelChange={updateStageModel}
881
1056
  onValidationModelChange={updateValidationModel}
1057
+ onStageParamChange={updateStageParam}
882
1058
  onLoopParamChange={updateLoopParam}
883
1059
  onOpenAgent={setOpenAgentSlug}
1060
+ onOpenCheck={setOpenCheck}
884
1061
  />
885
1062
  ) : (
886
1063
  <StepCard
@@ -889,7 +1066,9 @@ export function CeremonyWorkflowModal({
889
1066
  editable={isEditable}
890
1067
  onStageModelChange={updateStageModel}
891
1068
  onValidationModelChange={updateValidationModel}
1069
+ onStageParamChange={updateStageParam}
892
1070
  onOpenAgent={setOpenAgentSlug}
1071
+ onOpenCheck={setOpenCheck}
893
1072
  />
894
1073
  )}
895
1074
  {si < phase.steps.length - 1 && <Connector />}
@@ -941,6 +1120,14 @@ export function CeremonyWorkflowModal({
941
1120
  onClose={() => setOpenAgentSlug(null)}
942
1121
  />
943
1122
  )}
1123
+
1124
+ {openCheck && (
1125
+ <CheckEditorPopup
1126
+ scope={openCheck.scope}
1127
+ perspective={openCheck.perspective}
1128
+ onClose={() => setOpenCheck(null)}
1129
+ />
1130
+ )}
944
1131
  </div>
945
1132
  );
946
1133
  }