@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
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TaskRunnerService — Manages seed and run-task processes independently from CeremonyService.
|
|
3
|
+
*
|
|
4
|
+
* Supports multiple concurrent runs (each tracked by processId).
|
|
5
|
+
* Uses the same fork → IPC → WebSocket pattern as CeremonyService.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { fork } from 'child_process';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = path.dirname(__filename);
|
|
14
|
+
|
|
15
|
+
let _nextId = 1;
|
|
16
|
+
|
|
17
|
+
export class TaskRunnerService {
|
|
18
|
+
constructor(projectRoot) {
|
|
19
|
+
this.projectRoot = projectRoot;
|
|
20
|
+
this._runs = new Map(); // processId → { type, itemId, child, status, progress }
|
|
21
|
+
this.websocket = null;
|
|
22
|
+
this._reloadCallback = null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
setWebSocket(ws) { this.websocket = ws; }
|
|
26
|
+
setReloadCallback(fn) { this._reloadCallback = fn; }
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Get the status of a specific run.
|
|
30
|
+
*/
|
|
31
|
+
getRunStatus(processId) {
|
|
32
|
+
const run = this._runs.get(processId);
|
|
33
|
+
if (!run) return null;
|
|
34
|
+
return {
|
|
35
|
+
processId,
|
|
36
|
+
type: run.type,
|
|
37
|
+
itemId: run.itemId,
|
|
38
|
+
status: run.status,
|
|
39
|
+
progress: run.progress,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Get all active runs for a given item.
|
|
45
|
+
*/
|
|
46
|
+
getRunsForItem(itemId) {
|
|
47
|
+
const runs = [];
|
|
48
|
+
for (const [processId, run] of this._runs) {
|
|
49
|
+
if (run.itemId === itemId) {
|
|
50
|
+
runs.push({ processId, type: run.type, status: run.status });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return runs;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* List all active/recent runs.
|
|
58
|
+
*/
|
|
59
|
+
listRuns() {
|
|
60
|
+
return [...this._runs.entries()].map(([processId, run]) => ({
|
|
61
|
+
processId,
|
|
62
|
+
type: run.type,
|
|
63
|
+
itemId: run.itemId,
|
|
64
|
+
status: run.status,
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Check if a specific item has an active run.
|
|
70
|
+
*/
|
|
71
|
+
isRunning(itemId) {
|
|
72
|
+
for (const run of this._runs.values()) {
|
|
73
|
+
if (run.itemId === itemId && run.status === 'running') return true;
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Fork a seed worker for a story.
|
|
80
|
+
* @param {string} storyId
|
|
81
|
+
* @returns {string} processId
|
|
82
|
+
*/
|
|
83
|
+
runSeed(storyId) {
|
|
84
|
+
if (this.isRunning(storyId)) {
|
|
85
|
+
throw new Error(`Seed already running for ${storyId}`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const processId = `seed-${_nextId++}`;
|
|
89
|
+
const workerPath = path.join(__dirname, '../workers/seed-worker.js');
|
|
90
|
+
|
|
91
|
+
const child = fork(workerPath, [], {
|
|
92
|
+
stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
|
|
93
|
+
cwd: this.projectRoot,
|
|
94
|
+
env: { ...process.env },
|
|
95
|
+
});
|
|
96
|
+
child.stdout?.on('data', d => process.stdout.write(d));
|
|
97
|
+
child.stderr?.on('data', d => process.stderr.write(d));
|
|
98
|
+
|
|
99
|
+
const run = {
|
|
100
|
+
type: 'seed',
|
|
101
|
+
itemId: storyId,
|
|
102
|
+
child,
|
|
103
|
+
status: 'running',
|
|
104
|
+
progress: [],
|
|
105
|
+
};
|
|
106
|
+
this._runs.set(processId, run);
|
|
107
|
+
|
|
108
|
+
child.send({ type: 'init', storyId });
|
|
109
|
+
|
|
110
|
+
child.on('message', (msg) => this._handleMessage(processId, msg));
|
|
111
|
+
child.on('exit', (code) => this._handleExit(processId, code));
|
|
112
|
+
|
|
113
|
+
return processId;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Fork a run-task worker for a task.
|
|
118
|
+
* @param {string} taskId
|
|
119
|
+
* @returns {string} processId
|
|
120
|
+
*/
|
|
121
|
+
runTask(taskId) {
|
|
122
|
+
if (this.isRunning(taskId)) {
|
|
123
|
+
throw new Error(`Run already active for ${taskId}`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const processId = `run-${_nextId++}`;
|
|
127
|
+
const workerPath = path.join(__dirname, '../workers/run-task-worker.js');
|
|
128
|
+
|
|
129
|
+
const child = fork(workerPath, [], {
|
|
130
|
+
stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
|
|
131
|
+
cwd: this.projectRoot,
|
|
132
|
+
env: { ...process.env },
|
|
133
|
+
});
|
|
134
|
+
child.stdout?.on('data', d => process.stdout.write(d));
|
|
135
|
+
child.stderr?.on('data', d => process.stderr.write(d));
|
|
136
|
+
|
|
137
|
+
const run = {
|
|
138
|
+
type: 'run-task',
|
|
139
|
+
itemId: taskId,
|
|
140
|
+
child,
|
|
141
|
+
status: 'running',
|
|
142
|
+
progress: [],
|
|
143
|
+
};
|
|
144
|
+
this._runs.set(processId, run);
|
|
145
|
+
|
|
146
|
+
child.send({ type: 'init', taskId });
|
|
147
|
+
|
|
148
|
+
child.on('message', (msg) => this._handleMessage(processId, msg));
|
|
149
|
+
child.on('exit', (code) => this._handleExit(processId, code));
|
|
150
|
+
|
|
151
|
+
return processId;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Cancel a running process.
|
|
156
|
+
*/
|
|
157
|
+
cancel(processId) {
|
|
158
|
+
const run = this._runs.get(processId);
|
|
159
|
+
if (!run || run.status !== 'running') return false;
|
|
160
|
+
|
|
161
|
+
try { run.child.send({ type: 'cancel' }); } catch {}
|
|
162
|
+
run.status = 'cancelling';
|
|
163
|
+
|
|
164
|
+
// Safety net: SIGTERM after 10s, SIGKILL after 13s
|
|
165
|
+
const killTimer = setTimeout(() => {
|
|
166
|
+
if (run.status === 'cancelling') {
|
|
167
|
+
try { run.child.kill('SIGTERM'); } catch {}
|
|
168
|
+
setTimeout(() => {
|
|
169
|
+
if (run.status === 'cancelling') {
|
|
170
|
+
try { run.child.kill('SIGKILL'); } catch {}
|
|
171
|
+
}
|
|
172
|
+
}, 3000);
|
|
173
|
+
}
|
|
174
|
+
}, 10000);
|
|
175
|
+
run._killTimer = killTimer;
|
|
176
|
+
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Handle IPC messages from workers.
|
|
182
|
+
*/
|
|
183
|
+
_handleMessage(processId, msg) {
|
|
184
|
+
const run = this._runs.get(processId);
|
|
185
|
+
if (!run) return;
|
|
186
|
+
|
|
187
|
+
switch (msg.type) {
|
|
188
|
+
case 'progress':
|
|
189
|
+
run.progress.push(msg.message);
|
|
190
|
+
this.websocket?.broadcast({
|
|
191
|
+
type: `${run.type}:progress`,
|
|
192
|
+
processId,
|
|
193
|
+
itemId: run.itemId,
|
|
194
|
+
message: msg.message,
|
|
195
|
+
});
|
|
196
|
+
break;
|
|
197
|
+
|
|
198
|
+
case 'item-written':
|
|
199
|
+
this._reloadCallback?.();
|
|
200
|
+
this.websocket?.broadcastRefresh();
|
|
201
|
+
break;
|
|
202
|
+
|
|
203
|
+
case 'complete':
|
|
204
|
+
run.status = 'complete';
|
|
205
|
+
if (run._killTimer) clearTimeout(run._killTimer);
|
|
206
|
+
this._reloadCallback?.();
|
|
207
|
+
this.websocket?.broadcastRefresh();
|
|
208
|
+
this.websocket?.broadcast({
|
|
209
|
+
type: `${run.type}:complete`,
|
|
210
|
+
processId,
|
|
211
|
+
itemId: run.itemId,
|
|
212
|
+
result: msg.result,
|
|
213
|
+
});
|
|
214
|
+
break;
|
|
215
|
+
|
|
216
|
+
case 'cancelled':
|
|
217
|
+
run.status = 'cancelled';
|
|
218
|
+
if (run._killTimer) clearTimeout(run._killTimer);
|
|
219
|
+
this.websocket?.broadcast({
|
|
220
|
+
type: `${run.type}:cancelled`,
|
|
221
|
+
processId,
|
|
222
|
+
itemId: run.itemId,
|
|
223
|
+
});
|
|
224
|
+
break;
|
|
225
|
+
|
|
226
|
+
case 'error':
|
|
227
|
+
run.status = 'error';
|
|
228
|
+
if (run._killTimer) clearTimeout(run._killTimer);
|
|
229
|
+
this.websocket?.broadcast({
|
|
230
|
+
type: `${run.type}:error`,
|
|
231
|
+
processId,
|
|
232
|
+
itemId: run.itemId,
|
|
233
|
+
error: msg.error?.message || 'Unknown error',
|
|
234
|
+
});
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Handle worker exit.
|
|
241
|
+
*/
|
|
242
|
+
_handleExit(processId, code) {
|
|
243
|
+
const run = this._runs.get(processId);
|
|
244
|
+
if (!run) return;
|
|
245
|
+
|
|
246
|
+
if (run._killTimer) clearTimeout(run._killTimer);
|
|
247
|
+
|
|
248
|
+
if (run.status === 'running' || run.status === 'cancelling') {
|
|
249
|
+
run.status = 'error';
|
|
250
|
+
this.websocket?.broadcast({
|
|
251
|
+
type: `${run.type}:error`,
|
|
252
|
+
processId,
|
|
253
|
+
itemId: run.itemId,
|
|
254
|
+
error: `Worker exited unexpectedly (code ${code})`,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Clean up old runs after 5 minutes
|
|
259
|
+
setTimeout(() => this._runs.delete(processId), 5 * 60 * 1000);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run Task Worker
|
|
3
|
+
* Forked by TaskRunnerService.runTask().
|
|
4
|
+
* Creates a git worktree, implements code via LLM, runs tests, commits, merges.
|
|
5
|
+
*
|
|
6
|
+
* Parent → Worker:
|
|
7
|
+
* { type: 'init', taskId }
|
|
8
|
+
* { type: 'cancel' }
|
|
9
|
+
*
|
|
10
|
+
* Worker → Parent:
|
|
11
|
+
* { type: 'progress', message }
|
|
12
|
+
* { type: 'complete', result: { success, taskId } }
|
|
13
|
+
* { type: 'cancelled' }
|
|
14
|
+
* { type: 'error', error }
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { CommandLogger } from '../../../cli/command-logger.js';
|
|
18
|
+
import { readFileSync, writeFileSync, existsSync } from 'fs';
|
|
19
|
+
import { join } from 'path';
|
|
20
|
+
|
|
21
|
+
let _cancelled = false;
|
|
22
|
+
|
|
23
|
+
process.on('disconnect', () => {
|
|
24
|
+
_cancelled = true;
|
|
25
|
+
setTimeout(() => process.exit(1), 5000).unref();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
process.on('message', async (msg) => {
|
|
29
|
+
if (msg.type === 'init') {
|
|
30
|
+
run(msg.taskId);
|
|
31
|
+
} else if (msg.type === 'cancel') {
|
|
32
|
+
_cancelled = true;
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Update work.json status on disk.
|
|
38
|
+
*/
|
|
39
|
+
function updateStatus(taskId, status) {
|
|
40
|
+
const projectRoot = process.cwd();
|
|
41
|
+
// Find the work.json by walking the hierarchy
|
|
42
|
+
// Task ID: context-0001-0001-0001 → path: .avc/project/context-0001/context-0001-0001/context-0001-0001-0001/work.json
|
|
43
|
+
const idParts = taskId.replace('context-', '').split('-');
|
|
44
|
+
let dir = join(projectRoot, '.avc', 'project');
|
|
45
|
+
let current = 'context';
|
|
46
|
+
for (const part of idParts) {
|
|
47
|
+
current += `-${part}`;
|
|
48
|
+
dir = join(dir, current);
|
|
49
|
+
}
|
|
50
|
+
const workJsonPath = join(dir, 'work.json');
|
|
51
|
+
|
|
52
|
+
if (existsSync(workJsonPath)) {
|
|
53
|
+
try {
|
|
54
|
+
const workJson = JSON.parse(readFileSync(workJsonPath, 'utf8'));
|
|
55
|
+
workJson.status = status;
|
|
56
|
+
workJson.updated = new Date().toISOString();
|
|
57
|
+
writeFileSync(workJsonPath, JSON.stringify(workJson, null, 2), 'utf8');
|
|
58
|
+
} catch {}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function run(taskId) {
|
|
63
|
+
const logger = new CommandLogger('run-task', process.cwd());
|
|
64
|
+
logger.start();
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const { WorktreeRunner } = await import('../../../cli/worktree-runner.js');
|
|
68
|
+
|
|
69
|
+
// Set status to implementing
|
|
70
|
+
updateStatus(taskId, 'implementing');
|
|
71
|
+
try { process.send({ type: 'progress', message: `Starting implementation of ${taskId}` }); } catch {}
|
|
72
|
+
|
|
73
|
+
const runner = new WorktreeRunner(taskId, process.cwd());
|
|
74
|
+
|
|
75
|
+
const progressCallback = (message) => {
|
|
76
|
+
if (_cancelled) return;
|
|
77
|
+
try { process.send({ type: 'progress', message }); } catch {}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const cancelledCheck = () => _cancelled;
|
|
81
|
+
|
|
82
|
+
const result = await runner.execute(progressCallback, cancelledCheck);
|
|
83
|
+
|
|
84
|
+
if (_cancelled) {
|
|
85
|
+
updateStatus(taskId, 'planned'); // Reset on cancel
|
|
86
|
+
try { process.send({ type: 'cancelled' }); } catch {}
|
|
87
|
+
} else if (result.success) {
|
|
88
|
+
updateStatus(taskId, 'completed');
|
|
89
|
+
try {
|
|
90
|
+
process.send({
|
|
91
|
+
type: 'complete',
|
|
92
|
+
result: { success: true, taskId },
|
|
93
|
+
});
|
|
94
|
+
} catch {}
|
|
95
|
+
} else {
|
|
96
|
+
updateStatus(taskId, 'failed');
|
|
97
|
+
try {
|
|
98
|
+
process.send({
|
|
99
|
+
type: 'error',
|
|
100
|
+
error: { message: result.error || 'Implementation failed' },
|
|
101
|
+
});
|
|
102
|
+
} catch {}
|
|
103
|
+
}
|
|
104
|
+
} catch (error) {
|
|
105
|
+
if (error.message === 'CANCELLED') {
|
|
106
|
+
updateStatus(taskId, 'planned');
|
|
107
|
+
try { process.send({ type: 'cancelled' }); } catch {}
|
|
108
|
+
} else {
|
|
109
|
+
updateStatus(taskId, 'failed');
|
|
110
|
+
try {
|
|
111
|
+
process.send({
|
|
112
|
+
type: 'error',
|
|
113
|
+
error: { message: error.message, stack: error.stack },
|
|
114
|
+
});
|
|
115
|
+
} catch {}
|
|
116
|
+
}
|
|
117
|
+
} finally {
|
|
118
|
+
logger.stop();
|
|
119
|
+
setTimeout(() => process.exit(0), 500).unref();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seed Worker
|
|
3
|
+
* Forked by TaskRunnerService.runSeed().
|
|
4
|
+
* Communicates with parent via IPC (process.send / process.on('message')).
|
|
5
|
+
*
|
|
6
|
+
* Parent → Worker:
|
|
7
|
+
* { type: 'init', storyId }
|
|
8
|
+
* { type: 'cancel' }
|
|
9
|
+
*
|
|
10
|
+
* Worker → Parent:
|
|
11
|
+
* { type: 'progress', message }
|
|
12
|
+
* { type: 'item-written', itemId, itemType }
|
|
13
|
+
* { type: 'complete', result: { taskCount, subtaskCount, taskIds } }
|
|
14
|
+
* { type: 'cancelled' }
|
|
15
|
+
* { type: 'error', error }
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { CommandLogger } from '../../../cli/command-logger.js';
|
|
19
|
+
|
|
20
|
+
let _cancelled = false;
|
|
21
|
+
|
|
22
|
+
process.on('disconnect', () => {
|
|
23
|
+
_cancelled = true;
|
|
24
|
+
setTimeout(() => process.exit(1), 5000).unref();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
process.on('message', async (msg) => {
|
|
28
|
+
if (msg.type === 'init') {
|
|
29
|
+
run(msg.storyId);
|
|
30
|
+
} else if (msg.type === 'cancel') {
|
|
31
|
+
_cancelled = true;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
async function run(storyId) {
|
|
36
|
+
const logger = new CommandLogger('seed', process.cwd());
|
|
37
|
+
logger.start();
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
// Dynamic import to avoid loading CLI modules at fork time
|
|
41
|
+
const { SeedProcessor } = await import('../../../cli/seed-processor.js');
|
|
42
|
+
|
|
43
|
+
const processor = new SeedProcessor(storyId);
|
|
44
|
+
|
|
45
|
+
const progressCallback = (message) => {
|
|
46
|
+
if (_cancelled) return;
|
|
47
|
+
try { process.send({ type: 'progress', message }); } catch {}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const itemWrittenCallback = ({ itemId, itemType }) => {
|
|
51
|
+
if (_cancelled) return;
|
|
52
|
+
try { process.send({ type: 'item-written', itemId, itemType }); } catch {}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const cancelledCheck = () => _cancelled;
|
|
56
|
+
|
|
57
|
+
const result = await processor.executeWithCallback(
|
|
58
|
+
progressCallback,
|
|
59
|
+
itemWrittenCallback,
|
|
60
|
+
cancelledCheck
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
if (_cancelled) {
|
|
64
|
+
try { process.send({ type: 'cancelled' }); } catch {}
|
|
65
|
+
} else {
|
|
66
|
+
try {
|
|
67
|
+
process.send({
|
|
68
|
+
type: 'complete',
|
|
69
|
+
result: {
|
|
70
|
+
storyId,
|
|
71
|
+
taskCount: result.taskCount,
|
|
72
|
+
subtaskCount: result.subtaskCount,
|
|
73
|
+
taskIds: result.taskIds,
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
} catch {}
|
|
77
|
+
}
|
|
78
|
+
} catch (error) {
|
|
79
|
+
if (error.message === 'CEREMONY_CANCELLED') {
|
|
80
|
+
try { process.send({ type: 'cancelled' }); } catch {}
|
|
81
|
+
} else {
|
|
82
|
+
try {
|
|
83
|
+
process.send({
|
|
84
|
+
type: 'error',
|
|
85
|
+
error: { message: error.message, stack: error.stack },
|
|
86
|
+
});
|
|
87
|
+
} catch {}
|
|
88
|
+
}
|
|
89
|
+
} finally {
|
|
90
|
+
logger.stop();
|
|
91
|
+
// Give parent time to receive the final message
|
|
92
|
+
setTimeout(() => process.exit(0), 500).unref();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -70,15 +70,23 @@ async function run() {
|
|
|
70
70
|
costLimitReachedCallback,
|
|
71
71
|
});
|
|
72
72
|
logger.stop();
|
|
73
|
-
|
|
73
|
+
// sponsorCallWithAnswers returns { error: true, message } on validation failure instead of throwing
|
|
74
|
+
if (result?.error === true) {
|
|
75
|
+
process.send({ type: 'error', error: result.message || 'Ceremony failed' });
|
|
76
|
+
} else {
|
|
77
|
+
process.send({ type: 'complete', result });
|
|
78
|
+
}
|
|
74
79
|
process.exit(0);
|
|
75
80
|
} catch (err) {
|
|
76
81
|
logger.stop();
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
82
|
+
const msg = err.message === 'CEREMONY_CANCELLED'
|
|
83
|
+
? { type: 'cancelled' }
|
|
84
|
+
: { type: 'error', error: err.message };
|
|
85
|
+
// Guard against ERR_IPC_CHANNEL_CLOSED if the parent already disconnected.
|
|
86
|
+
try {
|
|
87
|
+
process.send(msg, () => process.exit(0));
|
|
88
|
+
} catch (_) {
|
|
89
|
+
process.exit(0);
|
|
81
90
|
}
|
|
82
|
-
process.exit(0);
|
|
83
91
|
}
|
|
84
92
|
}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* { type: 'paused' }
|
|
18
18
|
* { type: 'resumed' }
|
|
19
19
|
* { type: 'decomposition-complete', hierarchy }
|
|
20
|
+
* { type: 'hierarchy-written', epicCount, storyCount }
|
|
20
21
|
* { type: 'complete', result }
|
|
21
22
|
* { type: 'cancelled' }
|
|
22
23
|
* { type: 'error', error }
|
|
@@ -24,6 +25,33 @@
|
|
|
24
25
|
|
|
25
26
|
import { ProjectInitiator } from '../../../cli/init.js';
|
|
26
27
|
import { CommandLogger } from '../../../cli/command-logger.js';
|
|
28
|
+
import { readFileSync } from 'fs';
|
|
29
|
+
import { join } from 'path';
|
|
30
|
+
|
|
31
|
+
function _isQuotaOrRateLimit(msg) {
|
|
32
|
+
const m = (msg || '').toLowerCase();
|
|
33
|
+
return m.includes('429') || m.includes('quota') || m.includes('rate limit') ||
|
|
34
|
+
m.includes('resource exhausted') || m.includes('resource_exhausted') ||
|
|
35
|
+
m.includes('too many requests') ||
|
|
36
|
+
// Anthropic credit-balance exhausted (400 invalid_request_error)
|
|
37
|
+
m.includes('credit balance is too low') || m.includes('credit balance') ||
|
|
38
|
+
m.includes('billing') || m.includes('insufficient_quota') ||
|
|
39
|
+
// Transient connection errors — surface as resumable to allow provider switch
|
|
40
|
+
m.includes('connection error') || m.includes('econnreset') ||
|
|
41
|
+
m.includes('econnrefused') || m.includes('network error') || m.includes('fetch failed');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function _getCurrentStageInfo(stageName) {
|
|
45
|
+
try {
|
|
46
|
+
const cfg = JSON.parse(readFileSync(join(process.cwd(), '.avc', 'avc.json'), 'utf8'));
|
|
47
|
+
const ceremony = cfg.settings?.ceremonies?.find(c => c.name === 'sprint-planning');
|
|
48
|
+
const stage = ceremony?.stages?.[stageName];
|
|
49
|
+
return {
|
|
50
|
+
provider: stage?.provider || ceremony?.provider || 'unknown',
|
|
51
|
+
model: stage?.model || ceremony?.defaultModel || 'unknown',
|
|
52
|
+
};
|
|
53
|
+
} catch { return { provider: 'unknown', model: 'unknown' }; }
|
|
54
|
+
}
|
|
27
55
|
|
|
28
56
|
let _paused = false;
|
|
29
57
|
let _cancelled = false;
|
|
@@ -31,6 +59,8 @@ let _costThreshold = null;
|
|
|
31
59
|
let _waitingCostLimit = false;
|
|
32
60
|
let _waitingSelection = false;
|
|
33
61
|
let _selectionResult = null;
|
|
62
|
+
let _waitingQuota = false;
|
|
63
|
+
let _quotaResolution = null;
|
|
34
64
|
|
|
35
65
|
// Parent server stopped — exit rather than running as an orphan.
|
|
36
66
|
process.on('disconnect', () => {
|
|
@@ -42,7 +72,7 @@ process.on('disconnect', () => {
|
|
|
42
72
|
process.on('message', async (msg) => {
|
|
43
73
|
if (msg.type === 'init') {
|
|
44
74
|
_costThreshold = msg.costThreshold ?? null;
|
|
45
|
-
run();
|
|
75
|
+
run(msg.resumeFrom || null);
|
|
46
76
|
} else if (msg.type === 'pause') {
|
|
47
77
|
_paused = true;
|
|
48
78
|
process.send({ type: 'paused' });
|
|
@@ -53,13 +83,18 @@ process.on('message', async (msg) => {
|
|
|
53
83
|
_cancelled = true;
|
|
54
84
|
} else if (msg.type === 'cost-limit-continue') {
|
|
55
85
|
_waitingCostLimit = false;
|
|
86
|
+
} else if (msg.type === 'quota-continue') {
|
|
87
|
+
_quotaResolution = msg.newProvider
|
|
88
|
+
? { newProvider: msg.newProvider, newModel: msg.newModel }
|
|
89
|
+
: null;
|
|
90
|
+
_waitingQuota = false;
|
|
56
91
|
} else if (msg.type === 'selection-confirmed') {
|
|
57
92
|
_selectionResult = { selectedEpicIds: msg.selectedEpicIds, selectedStoryIds: msg.selectedStoryIds };
|
|
58
93
|
_waitingSelection = false;
|
|
59
94
|
}
|
|
60
95
|
});
|
|
61
96
|
|
|
62
|
-
async function run() {
|
|
97
|
+
async function run(resumeFrom = null) {
|
|
63
98
|
const logger = new CommandLogger('sprint-planning', process.cwd());
|
|
64
99
|
logger.start();
|
|
65
100
|
try {
|
|
@@ -96,11 +131,54 @@ async function run() {
|
|
|
96
131
|
return _selectionResult;
|
|
97
132
|
};
|
|
98
133
|
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
})
|
|
134
|
+
const hierarchyWrittenCallback = async ({ epicCount, storyCount }) => {
|
|
135
|
+
process.send({ type: 'hierarchy-written', epicCount, storyCount });
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const itemWrittenCallback = async ({ itemId, itemType }) => {
|
|
139
|
+
process.send({ type: 'item-written', itemId, itemType });
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const quotaExceededCallback = async ({ validatorName, errMsg, provider, model }) => {
|
|
143
|
+
_waitingQuota = true;
|
|
144
|
+
_quotaResolution = null;
|
|
145
|
+
process.send({ type: 'quota-limit', validatorName, errMsg, provider, model });
|
|
146
|
+
while (_waitingQuota) {
|
|
147
|
+
await new Promise(r => setTimeout(r, 200));
|
|
148
|
+
if (_cancelled) throw new Error('CEREMONY_CANCELLED');
|
|
149
|
+
}
|
|
150
|
+
return _quotaResolution; // null = retry same; { newProvider, newModel } = switch
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
// Outer retry loop: catches quota errors from pre-validator stages (decomposition, etc.)
|
|
154
|
+
// The processor is reconstructed on each retry so it picks up any avc.json model changes.
|
|
155
|
+
let result;
|
|
156
|
+
while (true) {
|
|
157
|
+
try {
|
|
158
|
+
result = await initiator.sprintPlanningWithCallback(progressCallback, {
|
|
159
|
+
costThreshold: _costThreshold,
|
|
160
|
+
costLimitReachedCallback,
|
|
161
|
+
selectionCallback,
|
|
162
|
+
hierarchyWrittenCallback,
|
|
163
|
+
itemWrittenCallback,
|
|
164
|
+
quotaExceededCallback,
|
|
165
|
+
resumeFrom,
|
|
166
|
+
});
|
|
167
|
+
break; // success — exit retry loop
|
|
168
|
+
} catch (err) {
|
|
169
|
+
if (err.message === 'CEREMONY_CANCELLED') throw err;
|
|
170
|
+
const errMsg = err.message || '';
|
|
171
|
+
if (_isQuotaOrRateLimit(errMsg)) {
|
|
172
|
+
// Quota error from a stage not covered by the validator callback (e.g. decomposition).
|
|
173
|
+
// Pause and wait for user to add credits or switch model via Configure Models.
|
|
174
|
+
const { provider, model } = _getCurrentStageInfo('decomposition');
|
|
175
|
+
await quotaExceededCallback({ validatorName: 'decomposition', errMsg: errMsg.split('\n')[0], provider, model });
|
|
176
|
+
// Retry — processor reconstructs and re-reads avc.json (picks up any model changes).
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
throw err; // non-quota error: propagate to outer catch
|
|
180
|
+
}
|
|
181
|
+
}
|
|
104
182
|
logger.stop();
|
|
105
183
|
process.send({ type: 'complete', result });
|
|
106
184
|
|
|
@@ -120,11 +198,15 @@ async function run() {
|
|
|
120
198
|
process.exit(0);
|
|
121
199
|
} catch (err) {
|
|
122
200
|
logger.stop();
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
201
|
+
const msg = err.message === 'CEREMONY_CANCELLED'
|
|
202
|
+
? { type: 'cancelled' }
|
|
203
|
+
: { type: 'error', error: err.message };
|
|
204
|
+
// Use callback to ensure the IPC message is flushed before exiting.
|
|
205
|
+
// Guard against ERR_IPC_CHANNEL_CLOSED if the parent already disconnected.
|
|
206
|
+
try {
|
|
207
|
+
process.send(msg, () => process.exit(0));
|
|
208
|
+
} catch (_) {
|
|
209
|
+
process.exit(0);
|
|
127
210
|
}
|
|
128
|
-
process.exit(0);
|
|
129
211
|
}
|
|
130
212
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agile-vibe-coding/avc",
|
|
3
|
-
"version": "0.2
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Agile Vibe Coding (AVC) - Framework for managing AI agent-based software development projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "cli/index.js",
|
|
@@ -44,8 +44,7 @@
|
|
|
44
44
|
],
|
|
45
45
|
"author": "Nacho Coll",
|
|
46
46
|
"license": "PolyForm-Noncommercial-1.0.0",
|
|
47
|
-
|
|
48
|
-
"repository": {
|
|
47
|
+
"repository": {
|
|
49
48
|
"type": "git",
|
|
50
49
|
"url": "git+https://github.com/NachoColl/agilevibecoding.git",
|
|
51
50
|
"directory": "src"
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"agentName": "solver-epic-api",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"description": "Output schema for API Designer epic solver",
|
|
5
|
-
"requiredFields": ["id", "name", "domain", "description", "features", "dependencies", "improvementNotes"],
|
|
6
|
-
"fieldValidation": {
|
|
7
|
-
"id": { "type": "string" },
|
|
8
|
-
"name": { "type": "string" },
|
|
9
|
-
"domain": { "type": "string" },
|
|
10
|
-
"description": { "type": "string" },
|
|
11
|
-
"features": { "type": "array", "minLength": 1 },
|
|
12
|
-
"dependencies": { "type": "array" },
|
|
13
|
-
"improvementNotes": { "type": "string" }
|
|
14
|
-
}
|
|
15
|
-
}
|