@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.
- package/README.md +475 -3
- package/cli/agents/agent-selector.md +23 -0
- package/cli/agents/code-implementer.md +117 -0
- package/cli/agents/code-validator.md +80 -0
- package/cli/agents/context-reviewer-epic.md +101 -0
- package/cli/agents/context-reviewer-story.md +92 -0
- package/cli/agents/context-writer-epic.md +145 -0
- package/cli/agents/context-writer-story.md +111 -0
- package/cli/agents/doc-writer-epic.md +42 -0
- package/cli/agents/doc-writer-story.md +43 -0
- package/cli/agents/duplicate-detector.md +110 -0
- package/cli/agents/epic-story-decomposer.md +318 -39
- package/cli/agents/mission-scope-generator.md +68 -4
- package/cli/agents/mission-scope-validator.md +40 -6
- package/cli/agents/project-context-extractor.md +21 -6
- package/cli/agents/scaffolding-generator.md +99 -0
- package/cli/agents/seed-validator.md +71 -0
- package/cli/agents/story-scope-reviewer.md +147 -0
- package/cli/agents/story-splitter.md +83 -0
- package/cli/agents/validator-documentation.json +31 -0
- package/cli/agents/validator-documentation.md +3 -1
- package/cli/api-reference-tool.js +368 -0
- package/cli/checks/catalog.json +76 -0
- package/cli/checks/code/quality.json +26 -0
- package/cli/checks/code/testing.json +14 -0
- package/cli/checks/code/traceability.json +26 -0
- package/cli/checks/cross-refs/epic.json +171 -0
- package/cli/checks/cross-refs/story.json +149 -0
- package/cli/checks/epic/api.json +114 -0
- package/cli/checks/epic/backend.json +126 -0
- package/cli/checks/epic/cloud.json +126 -0
- package/cli/checks/epic/data.json +102 -0
- package/cli/checks/epic/database.json +114 -0
- package/cli/checks/epic/developer.json +182 -0
- package/cli/checks/epic/devops.json +174 -0
- package/cli/checks/epic/frontend.json +162 -0
- package/cli/checks/epic/mobile.json +102 -0
- package/cli/checks/epic/qa.json +90 -0
- package/cli/checks/epic/security.json +184 -0
- package/cli/checks/epic/solution-architect.json +192 -0
- package/cli/checks/epic/test-architect.json +90 -0
- package/cli/checks/epic/ui.json +102 -0
- package/cli/checks/epic/ux.json +90 -0
- package/cli/checks/fixes/epic-fix-template.md +10 -0
- package/cli/checks/fixes/story-fix-template.md +10 -0
- package/cli/checks/story/api.json +186 -0
- package/cli/checks/story/backend.json +102 -0
- package/cli/checks/story/cloud.json +102 -0
- package/cli/checks/story/data.json +210 -0
- package/cli/checks/story/database.json +102 -0
- package/cli/checks/story/developer.json +168 -0
- package/cli/checks/story/devops.json +102 -0
- package/cli/checks/story/frontend.json +174 -0
- package/cli/checks/story/mobile.json +102 -0
- package/cli/checks/story/qa.json +210 -0
- package/cli/checks/story/security.json +198 -0
- package/cli/checks/story/solution-architect.json +230 -0
- package/cli/checks/story/test-architect.json +210 -0
- package/cli/checks/story/ui.json +102 -0
- package/cli/checks/story/ux.json +102 -0
- package/cli/coding-order.js +401 -0
- package/cli/dependency-checker.js +72 -0
- package/cli/epic-story-validator.js +284 -799
- package/cli/index.js +0 -0
- package/cli/init-model-config.js +17 -10
- package/cli/init.js +514 -92
- package/cli/kanban-server-manager.js +1 -2
- package/cli/llm-claude.js +98 -31
- package/cli/llm-gemini.js +29 -5
- package/cli/llm-local.js +493 -0
- package/cli/llm-openai.js +262 -41
- package/cli/llm-provider.js +147 -8
- package/cli/llm-token-limits.js +113 -4
- package/cli/llm-verifier.js +209 -1
- package/cli/llm-xiaomi.js +143 -0
- package/cli/message-constants.js +3 -12
- package/cli/messaging-api.js +6 -12
- package/cli/micro-check-fixer.js +335 -0
- package/cli/micro-check-runner.js +449 -0
- package/cli/micro-check-scorer.js +148 -0
- package/cli/micro-check-validator.js +538 -0
- package/cli/model-pricing.js +23 -0
- package/cli/model-selector.js +3 -2
- package/cli/prompt-logger.js +57 -0
- package/cli/repl-ink.js +106 -346
- package/cli/repl-old.js +1 -2
- package/cli/seed-processor.js +194 -24
- package/cli/sprint-planning-processor.js +2638 -289
- package/cli/template-processor.js +50 -3
- package/cli/token-tracker.js +50 -23
- package/cli/tools/generate-story-validators.js +1 -1
- package/cli/validation-router.js +70 -8
- package/cli/worktree-runner.js +654 -0
- package/kanban/client/dist/assets/index-D_KC5EQT.css +1 -0
- package/kanban/client/dist/assets/index-DjY5zqW7.js +351 -0
- package/kanban/client/dist/index.html +2 -2
- package/kanban/client/src/App.jsx +43 -14
- package/kanban/client/src/components/ceremony/AskArchPopup.jsx +7 -3
- package/kanban/client/src/components/ceremony/AskModelPopup.jsx +23 -10
- package/kanban/client/src/components/ceremony/CeremonyWorkflowModal.jsx +320 -133
- package/kanban/client/src/components/ceremony/ProviderSwitcherButton.jsx +290 -0
- package/kanban/client/src/components/ceremony/SponsorCallModal.jsx +80 -13
- package/kanban/client/src/components/ceremony/SprintPlanningModal.jsx +156 -22
- package/kanban/client/src/components/ceremony/steps/ArchitectureStep.jsx +11 -11
- package/kanban/client/src/components/ceremony/steps/CompleteStep.jsx +3 -21
- package/kanban/client/src/components/ceremony/steps/ReviewAnswersStep.jsx +214 -10
- package/kanban/client/src/components/ceremony/steps/RunningStep.jsx +23 -2
- package/kanban/client/src/components/kanban/CardDetailModal.jsx +97 -10
- package/kanban/client/src/components/kanban/GroupingSelector.jsx +7 -1
- package/kanban/client/src/components/kanban/KanbanCard.jsx +23 -14
- package/kanban/client/src/components/kanban/RefineWorkItemPopup.jsx +9 -14
- package/kanban/client/src/components/kanban/RunButton.jsx +162 -0
- package/kanban/client/src/components/kanban/SeedButton.jsx +176 -0
- package/kanban/client/src/components/settings/AgentsTab.jsx +103 -75
- package/kanban/client/src/components/settings/ApiKeysTab.jsx +31 -2
- package/kanban/client/src/components/settings/CeremonyModelsTab.jsx +9 -2
- package/kanban/client/src/components/settings/CheckEditorPopup.jsx +507 -0
- package/kanban/client/src/components/settings/CostThresholdsTab.jsx +3 -2
- package/kanban/client/src/components/settings/ModelPricingTab.jsx +72 -7
- package/kanban/client/src/components/settings/OpenAIAuthSection.jsx +412 -0
- package/kanban/client/src/components/settings/SettingsModal.jsx +4 -4
- package/kanban/client/src/components/stats/CostModal.jsx +34 -3
- package/kanban/client/src/hooks/useGrouping.js +59 -0
- package/kanban/client/src/lib/api.js +118 -4
- package/kanban/client/src/lib/status-grouping.js +10 -0
- package/kanban/client/src/store/kanbanStore.js +8 -0
- package/kanban/server/index.js +23 -2
- package/kanban/server/routes/ceremony.js +153 -4
- package/kanban/server/routes/costs.js +9 -3
- package/kanban/server/routes/openai-oauth.js +366 -0
- package/kanban/server/routes/settings.js +447 -14
- package/kanban/server/routes/websocket.js +7 -2
- package/kanban/server/routes/work-items.js +141 -1
- package/kanban/server/services/CeremonyService.js +275 -24
- package/kanban/server/services/TaskRunnerService.js +261 -0
- package/kanban/server/workers/run-task-worker.js +121 -0
- package/kanban/server/workers/seed-worker.js +94 -0
- package/kanban/server/workers/sponsor-call-worker.js +14 -6
- package/kanban/server/workers/sprint-planning-worker.js +94 -12
- package/package.json +2 -3
- package/cli/agents/solver-epic-api.json +0 -15
- package/cli/agents/solver-epic-api.md +0 -39
- package/cli/agents/solver-epic-backend.json +0 -15
- package/cli/agents/solver-epic-backend.md +0 -39
- package/cli/agents/solver-epic-cloud.json +0 -15
- package/cli/agents/solver-epic-cloud.md +0 -39
- package/cli/agents/solver-epic-data.json +0 -15
- package/cli/agents/solver-epic-data.md +0 -39
- package/cli/agents/solver-epic-database.json +0 -15
- package/cli/agents/solver-epic-database.md +0 -39
- package/cli/agents/solver-epic-developer.json +0 -15
- package/cli/agents/solver-epic-developer.md +0 -39
- package/cli/agents/solver-epic-devops.json +0 -15
- package/cli/agents/solver-epic-devops.md +0 -39
- package/cli/agents/solver-epic-frontend.json +0 -15
- package/cli/agents/solver-epic-frontend.md +0 -39
- package/cli/agents/solver-epic-mobile.json +0 -15
- package/cli/agents/solver-epic-mobile.md +0 -39
- package/cli/agents/solver-epic-qa.json +0 -15
- package/cli/agents/solver-epic-qa.md +0 -39
- package/cli/agents/solver-epic-security.json +0 -15
- package/cli/agents/solver-epic-security.md +0 -39
- package/cli/agents/solver-epic-solution-architect.json +0 -15
- package/cli/agents/solver-epic-solution-architect.md +0 -39
- package/cli/agents/solver-epic-test-architect.json +0 -15
- package/cli/agents/solver-epic-test-architect.md +0 -39
- package/cli/agents/solver-epic-ui.json +0 -15
- package/cli/agents/solver-epic-ui.md +0 -39
- package/cli/agents/solver-epic-ux.json +0 -15
- package/cli/agents/solver-epic-ux.md +0 -39
- package/cli/agents/solver-story-api.json +0 -15
- package/cli/agents/solver-story-api.md +0 -39
- package/cli/agents/solver-story-backend.json +0 -15
- package/cli/agents/solver-story-backend.md +0 -39
- package/cli/agents/solver-story-cloud.json +0 -15
- package/cli/agents/solver-story-cloud.md +0 -39
- package/cli/agents/solver-story-data.json +0 -15
- package/cli/agents/solver-story-data.md +0 -39
- package/cli/agents/solver-story-database.json +0 -15
- package/cli/agents/solver-story-database.md +0 -39
- package/cli/agents/solver-story-developer.json +0 -15
- package/cli/agents/solver-story-developer.md +0 -39
- package/cli/agents/solver-story-devops.json +0 -15
- package/cli/agents/solver-story-devops.md +0 -39
- package/cli/agents/solver-story-frontend.json +0 -15
- package/cli/agents/solver-story-frontend.md +0 -39
- package/cli/agents/solver-story-mobile.json +0 -15
- package/cli/agents/solver-story-mobile.md +0 -39
- package/cli/agents/solver-story-qa.json +0 -15
- package/cli/agents/solver-story-qa.md +0 -39
- package/cli/agents/solver-story-security.json +0 -15
- package/cli/agents/solver-story-security.md +0 -39
- package/cli/agents/solver-story-solution-architect.json +0 -15
- package/cli/agents/solver-story-solution-architect.md +0 -39
- package/cli/agents/solver-story-test-architect.json +0 -15
- package/cli/agents/solver-story-test-architect.md +0 -39
- package/cli/agents/solver-story-ui.json +0 -15
- package/cli/agents/solver-story-ui.md +0 -39
- package/cli/agents/solver-story-ux.json +0 -15
- package/cli/agents/solver-story-ux.md +0 -39
- package/cli/agents/validator-epic-api.json +0 -93
- package/cli/agents/validator-epic-api.md +0 -137
- package/cli/agents/validator-epic-backend.json +0 -93
- package/cli/agents/validator-epic-backend.md +0 -130
- package/cli/agents/validator-epic-cloud.json +0 -93
- package/cli/agents/validator-epic-cloud.md +0 -137
- package/cli/agents/validator-epic-data.json +0 -93
- package/cli/agents/validator-epic-data.md +0 -130
- package/cli/agents/validator-epic-database.json +0 -93
- package/cli/agents/validator-epic-database.md +0 -137
- package/cli/agents/validator-epic-developer.json +0 -74
- package/cli/agents/validator-epic-developer.md +0 -153
- package/cli/agents/validator-epic-devops.json +0 -74
- package/cli/agents/validator-epic-devops.md +0 -153
- package/cli/agents/validator-epic-frontend.json +0 -74
- package/cli/agents/validator-epic-frontend.md +0 -153
- package/cli/agents/validator-epic-mobile.json +0 -93
- package/cli/agents/validator-epic-mobile.md +0 -130
- package/cli/agents/validator-epic-qa.json +0 -93
- package/cli/agents/validator-epic-qa.md +0 -130
- package/cli/agents/validator-epic-security.json +0 -74
- package/cli/agents/validator-epic-security.md +0 -154
- package/cli/agents/validator-epic-solution-architect.json +0 -74
- package/cli/agents/validator-epic-solution-architect.md +0 -156
- package/cli/agents/validator-epic-test-architect.json +0 -93
- package/cli/agents/validator-epic-test-architect.md +0 -130
- package/cli/agents/validator-epic-ui.json +0 -93
- package/cli/agents/validator-epic-ui.md +0 -130
- package/cli/agents/validator-epic-ux.json +0 -93
- package/cli/agents/validator-epic-ux.md +0 -130
- package/cli/agents/validator-story-api.json +0 -104
- package/cli/agents/validator-story-api.md +0 -152
- package/cli/agents/validator-story-backend.json +0 -104
- package/cli/agents/validator-story-backend.md +0 -152
- package/cli/agents/validator-story-cloud.json +0 -104
- package/cli/agents/validator-story-cloud.md +0 -152
- package/cli/agents/validator-story-data.json +0 -104
- package/cli/agents/validator-story-data.md +0 -152
- package/cli/agents/validator-story-database.json +0 -104
- package/cli/agents/validator-story-database.md +0 -152
- package/cli/agents/validator-story-developer.json +0 -104
- package/cli/agents/validator-story-developer.md +0 -152
- package/cli/agents/validator-story-devops.json +0 -104
- package/cli/agents/validator-story-devops.md +0 -152
- package/cli/agents/validator-story-frontend.json +0 -104
- package/cli/agents/validator-story-frontend.md +0 -152
- package/cli/agents/validator-story-mobile.json +0 -104
- package/cli/agents/validator-story-mobile.md +0 -152
- package/cli/agents/validator-story-qa.json +0 -104
- package/cli/agents/validator-story-qa.md +0 -152
- package/cli/agents/validator-story-security.json +0 -104
- package/cli/agents/validator-story-security.md +0 -152
- package/cli/agents/validator-story-solution-architect.json +0 -104
- package/cli/agents/validator-story-solution-architect.md +0 -152
- package/cli/agents/validator-story-test-architect.json +0 -104
- package/cli/agents/validator-story-test-architect.md +0 -152
- package/cli/agents/validator-story-ui.json +0 -104
- package/cli/agents/validator-story-ui.md +0 -152
- package/cli/agents/validator-story-ux.json +0 -104
- package/cli/agents/validator-story-ux.md +0 -152
- package/kanban/client/dist/assets/index-CiD8PS2e.js +0 -306
- 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
|
-
|
|
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: '
|
|
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:
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
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:
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
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: '
|
|
404
|
-
model: ceremony.stages?.['doc-
|
|
405
|
-
stageKey: 'doc-
|
|
406
|
-
agent: 'doc-
|
|
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: '
|
|
409
|
-
{ name: '{epic}/
|
|
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: '
|
|
415
|
-
model: ceremony.stages?.['doc-
|
|
416
|
-
stageKey: 'doc-
|
|
417
|
-
agent: 'doc-
|
|
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}/
|
|
420
|
-
{ name: '{story}/
|
|
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(
|
|
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': (
|
|
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
|
-
<
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
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
|
}
|