@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
package/cli/repl-ink.js
CHANGED
|
@@ -612,24 +612,14 @@ const CommandSelector = ({ onSelect, onCancel, filter }) => {
|
|
|
612
612
|
name: 'Project Setup',
|
|
613
613
|
commands: [
|
|
614
614
|
{ label: '/init Initialize an AVC project', value: '/init', aliases: ['/i'] },
|
|
615
|
-
{ label: '/documentation Build and serve documentation', value: '/documentation', aliases: ['/d'] },
|
|
616
615
|
{ label: '/kanban Launch kanban board server', value: '/kanban', aliases: ['/k'] },
|
|
617
616
|
{ label: '/remove Remove AVC project structure', value: '/remove', aliases: ['/rm'] }
|
|
618
617
|
]
|
|
619
618
|
},
|
|
620
|
-
{
|
|
621
|
-
name: 'Ceremonies',
|
|
622
|
-
commands: [
|
|
623
|
-
{ label: '/seed <story-id> Create Tasks and Subtasks', value: '/seed', aliases: [] }
|
|
624
|
-
]
|
|
625
|
-
},
|
|
626
619
|
{
|
|
627
620
|
name: 'Monitoring',
|
|
628
621
|
commands: [
|
|
629
|
-
{ label: '/processes View background processes', value: '/processes', aliases: ['/p'] }
|
|
630
|
-
{ label: '/status Show current project status', value: '/status', aliases: ['/s'] },
|
|
631
|
-
{ label: '/models Configure LLM models', value: '/models', aliases: ['/m'] },
|
|
632
|
-
{ label: '/tokens Show token usage statistics', value: '/tokens', aliases: ['/tk'] }
|
|
622
|
+
{ label: '/processes View background processes', value: '/processes', aliases: ['/p'] }
|
|
633
623
|
]
|
|
634
624
|
},
|
|
635
625
|
{
|
|
@@ -1755,6 +1745,10 @@ const App = () => {
|
|
|
1755
1745
|
// Cancel questionnaire confirmation state
|
|
1756
1746
|
const [cancelConfirmActive, setCancelConfirmActive] = useState(false);
|
|
1757
1747
|
|
|
1748
|
+
// Init confirmation state
|
|
1749
|
+
const [initConfirmActive, setInitConfirmActive] = useState(false);
|
|
1750
|
+
const [initConfirmDir, setInitConfirmDir] = useState('');
|
|
1751
|
+
|
|
1758
1752
|
// Remove confirmation state
|
|
1759
1753
|
const [removeConfirmActive, setRemoveConfirmActive] = useState(false);
|
|
1760
1754
|
const [removeConfirmInput, setRemoveConfirmInput] = useState('');
|
|
@@ -2099,12 +2093,7 @@ const App = () => {
|
|
|
2099
2093
|
// Available commands for Tab completion (including aliases)
|
|
2100
2094
|
const allCommands = [
|
|
2101
2095
|
'/init', '/i',
|
|
2102
|
-
'/seed',
|
|
2103
|
-
'/status', '/s',
|
|
2104
|
-
'/models', '/m',
|
|
2105
|
-
'/tokens', '/tk',
|
|
2106
2096
|
'/remove', '/rm',
|
|
2107
|
-
'/documentation', '/d',
|
|
2108
2097
|
'/kanban', '/k',
|
|
2109
2098
|
'/processes', '/p',
|
|
2110
2099
|
'/help', '/h',
|
|
@@ -2177,10 +2166,7 @@ const App = () => {
|
|
|
2177
2166
|
'/q': '/exit',
|
|
2178
2167
|
'/quit': '/exit',
|
|
2179
2168
|
'/i': '/init',
|
|
2180
|
-
'/s': '/status',
|
|
2181
|
-
'/m': '/models',
|
|
2182
2169
|
'/rm': '/remove',
|
|
2183
|
-
'/d': '/documentation',
|
|
2184
2170
|
'/p': '/processes'
|
|
2185
2171
|
};
|
|
2186
2172
|
return aliases[cmd.toLowerCase()] || cmd;
|
|
@@ -2286,6 +2272,21 @@ const App = () => {
|
|
|
2286
2272
|
outputBuffer.append(`${green(`Stopped ${stopped} process(es)`)}\n`);
|
|
2287
2273
|
}
|
|
2288
2274
|
|
|
2275
|
+
// Kill any stale kanban/docs servers on their ports that aren't tracked
|
|
2276
|
+
// by this session's process manager (e.g. from a previous crashed session)
|
|
2277
|
+
try {
|
|
2278
|
+
const exitKanbanMgr = new KanbanServerManager();
|
|
2279
|
+
const exitKanbanPort = exitKanbanMgr.getPort();
|
|
2280
|
+
const exitKanbanInUse = await exitKanbanMgr.isPortInUse(exitKanbanPort);
|
|
2281
|
+
if (exitKanbanInUse) {
|
|
2282
|
+
const stale = await exitKanbanMgr.findProcessUsingPort(exitKanbanPort);
|
|
2283
|
+
if (stale) {
|
|
2284
|
+
await exitKanbanMgr.killProcess(stale.pid);
|
|
2285
|
+
outputBuffer.append(`${gray(`Killed stale kanban server (PID ${stale.pid})`)}\n`);
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
} catch (_) {}
|
|
2289
|
+
|
|
2289
2290
|
outputBuffer.append(`${boldCyan('Thanks for using AVC!')}\n`);
|
|
2290
2291
|
setTimeout(() => {
|
|
2291
2292
|
exit();
|
|
@@ -2303,54 +2304,6 @@ const App = () => {
|
|
|
2303
2304
|
break;
|
|
2304
2305
|
}
|
|
2305
2306
|
|
|
2306
|
-
case '/seed': {
|
|
2307
|
-
// Parse story ID from command
|
|
2308
|
-
const storyIdMatch = input.match(/^\/seed\s+(\S+)/);
|
|
2309
|
-
if (!storyIdMatch) {
|
|
2310
|
-
fileLog('ERROR', '/seed called without story ID', { input });
|
|
2311
|
-
outputBuffer.append('Story ID required', 'ERROR');
|
|
2312
|
-
outputBuffer.append('Usage: /seed <story-id>\nExample: /seed context-0001-0001');
|
|
2313
|
-
break;
|
|
2314
|
-
}
|
|
2315
|
-
const storyId = storyIdMatch[1];
|
|
2316
|
-
const t0 = Date.now();
|
|
2317
|
-
fileLog('INFO', '/seed handler called', { storyId, cwd: process.cwd() });
|
|
2318
|
-
sendProgress(`Seeding story ${storyId}...`);
|
|
2319
|
-
await runSeed(storyId);
|
|
2320
|
-
fileLog('INFO', '/seed complete', { storyId, duration: `${Date.now() - t0}ms` });
|
|
2321
|
-
break;
|
|
2322
|
-
}
|
|
2323
|
-
|
|
2324
|
-
case '/status':
|
|
2325
|
-
case '/s': {
|
|
2326
|
-
const t0 = Date.now();
|
|
2327
|
-
fileLog('INFO', '/status handler called', { cwd: process.cwd(), avcExists });
|
|
2328
|
-
sendProgress('Checking project status...');
|
|
2329
|
-
await runStatus();
|
|
2330
|
-
fileLog('INFO', '/status complete', { duration: `${Date.now() - t0}ms` });
|
|
2331
|
-
break;
|
|
2332
|
-
}
|
|
2333
|
-
|
|
2334
|
-
case '/models':
|
|
2335
|
-
case '/m': {
|
|
2336
|
-
const t0 = Date.now();
|
|
2337
|
-
fileLog('INFO', '/models handler called', { cwd: process.cwd(), avcExists });
|
|
2338
|
-
sendProgress('Loading model configuration...');
|
|
2339
|
-
await runModels();
|
|
2340
|
-
fileLog('INFO', '/models complete', { duration: `${Date.now() - t0}ms` });
|
|
2341
|
-
break;
|
|
2342
|
-
}
|
|
2343
|
-
|
|
2344
|
-
case '/tokens':
|
|
2345
|
-
case '/tk': {
|
|
2346
|
-
const t0 = Date.now();
|
|
2347
|
-
fileLog('INFO', '/tokens handler called', { cwd: process.cwd(), avcExists });
|
|
2348
|
-
sendProgress('Analyzing token usage...');
|
|
2349
|
-
await runTokens();
|
|
2350
|
-
fileLog('INFO', '/tokens complete', { duration: `${Date.now() - t0}ms` });
|
|
2351
|
-
break;
|
|
2352
|
-
}
|
|
2353
|
-
|
|
2354
2307
|
case '/remove':
|
|
2355
2308
|
case '/rm': {
|
|
2356
2309
|
const t0 = Date.now();
|
|
@@ -2361,16 +2314,6 @@ const App = () => {
|
|
|
2361
2314
|
break;
|
|
2362
2315
|
}
|
|
2363
2316
|
|
|
2364
|
-
case '/documentation':
|
|
2365
|
-
case '/d': {
|
|
2366
|
-
const t0 = Date.now();
|
|
2367
|
-
fileLog('INFO', '/documentation handler called', { cwd: process.cwd(), avcExists });
|
|
2368
|
-
sendProgress('Building documentation...');
|
|
2369
|
-
await runBuildDocumentation();
|
|
2370
|
-
fileLog('INFO', '/documentation complete', { duration: `${Date.now() - t0}ms` });
|
|
2371
|
-
break;
|
|
2372
|
-
}
|
|
2373
|
-
|
|
2374
2317
|
case '/kanban':
|
|
2375
2318
|
case '/k': {
|
|
2376
2319
|
const t0 = Date.now();
|
|
@@ -2464,35 +2407,20 @@ const App = () => {
|
|
|
2464
2407
|
|
|
2465
2408
|
const showHelp = () => {
|
|
2466
2409
|
const groups = [
|
|
2467
|
-
{
|
|
2468
|
-
title: 'Ceremonies',
|
|
2469
|
-
cmds: [
|
|
2470
|
-
['/seed <story-id>', 'Generate tasks for a story'],
|
|
2471
|
-
]
|
|
2472
|
-
},
|
|
2473
2410
|
{
|
|
2474
2411
|
title: 'Project',
|
|
2475
2412
|
cmds: [
|
|
2476
2413
|
['/init (/i)', 'Create AVC project structure and config files'],
|
|
2477
|
-
['/
|
|
2414
|
+
['/kanban (/k)', 'Launch kanban board (ceremonies, settings, status)'],
|
|
2478
2415
|
['/remove (/rm)', 'Remove AVC project structure'],
|
|
2479
2416
|
]
|
|
2480
2417
|
},
|
|
2481
2418
|
{
|
|
2482
2419
|
title: 'Services',
|
|
2483
2420
|
cmds: [
|
|
2484
|
-
['/documentation (/d)', 'Build and serve project documentation'],
|
|
2485
|
-
['/kanban (/k)', 'Launch kanban board visualization'],
|
|
2486
2421
|
['/processes (/p)', 'View and manage background processes'],
|
|
2487
2422
|
]
|
|
2488
2423
|
},
|
|
2489
|
-
{
|
|
2490
|
-
title: 'Config',
|
|
2491
|
-
cmds: [
|
|
2492
|
-
['/models (/m)', 'Configure LLM models for ceremonies'],
|
|
2493
|
-
['/tokens', 'Show token usage statistics'],
|
|
2494
|
-
]
|
|
2495
|
-
},
|
|
2496
2424
|
{
|
|
2497
2425
|
title: 'Utilities',
|
|
2498
2426
|
cmds: [
|
|
@@ -2526,7 +2454,6 @@ const App = () => {
|
|
|
2526
2454
|
const version = getVersion();
|
|
2527
2455
|
outputBuffer.append(`${boldCyan('AVC')} ${bold(version)}\n`);
|
|
2528
2456
|
outputBuffer.append(`${gray('Node')} ${process.version}\n`);
|
|
2529
|
-
outputBuffer.append(`${gray('Docs')} ${cyan('https://agilevibecoding.org')}\n`);
|
|
2530
2457
|
};
|
|
2531
2458
|
|
|
2532
2459
|
const runInit = async () => {
|
|
@@ -2604,24 +2531,6 @@ const App = () => {
|
|
|
2604
2531
|
}
|
|
2605
2532
|
};
|
|
2606
2533
|
|
|
2607
|
-
const runSeed = async (storyId) => {
|
|
2608
|
-
const initiator = new ProjectInitiator();
|
|
2609
|
-
|
|
2610
|
-
startCommand('seed');
|
|
2611
|
-
|
|
2612
|
-
try {
|
|
2613
|
-
if (!initiator.isAvcProject()) {
|
|
2614
|
-
sendError(getProjectNotInitializedMessage());
|
|
2615
|
-
sendOutput('');
|
|
2616
|
-
return;
|
|
2617
|
-
}
|
|
2618
|
-
await initiator.seed(storyId);
|
|
2619
|
-
sendInfo('Docs: https://agilevibecoding.org/ceremonies/seed');
|
|
2620
|
-
} finally {
|
|
2621
|
-
endCommand();
|
|
2622
|
-
}
|
|
2623
|
-
};
|
|
2624
|
-
|
|
2625
2534
|
const runSponsorCall = async () => {
|
|
2626
2535
|
// Start new execution context - cancels previous run and clears output
|
|
2627
2536
|
startCommand('sponsor-call');
|
|
@@ -3495,56 +3404,6 @@ const App = () => {
|
|
|
3495
3404
|
}
|
|
3496
3405
|
};
|
|
3497
3406
|
|
|
3498
|
-
const runStatus = async () => {
|
|
3499
|
-
const initiator = new ProjectInitiator();
|
|
3500
|
-
|
|
3501
|
-
startCommand('status');
|
|
3502
|
-
|
|
3503
|
-
try {
|
|
3504
|
-
initiator.status();
|
|
3505
|
-
} finally {
|
|
3506
|
-
endCommand();
|
|
3507
|
-
}
|
|
3508
|
-
};
|
|
3509
|
-
|
|
3510
|
-
const runModels = async () => {
|
|
3511
|
-
const initiator = new ProjectInitiator();
|
|
3512
|
-
|
|
3513
|
-
startCommand('models');
|
|
3514
|
-
|
|
3515
|
-
let result;
|
|
3516
|
-
try {
|
|
3517
|
-
result = await initiator.models();
|
|
3518
|
-
} finally {
|
|
3519
|
-
endCommand();
|
|
3520
|
-
}
|
|
3521
|
-
|
|
3522
|
-
// Check if models() returned configuration data
|
|
3523
|
-
if (result && result.shouldConfigure) {
|
|
3524
|
-
setModelConfigurator(result.configurator);
|
|
3525
|
-
setModelConfigActive(true);
|
|
3526
|
-
setModelConfigMode('prompt');
|
|
3527
|
-
}
|
|
3528
|
-
};
|
|
3529
|
-
|
|
3530
|
-
const runTokens = async () => {
|
|
3531
|
-
const initiator = new ProjectInitiator();
|
|
3532
|
-
|
|
3533
|
-
startCommand('tokens');
|
|
3534
|
-
|
|
3535
|
-
try {
|
|
3536
|
-
if (!initiator.isAvcProject()) {
|
|
3537
|
-
sendError(getProjectNotInitializedMessage());
|
|
3538
|
-
sendOutput('');
|
|
3539
|
-
return;
|
|
3540
|
-
}
|
|
3541
|
-
|
|
3542
|
-
await initiator.showTokenStats();
|
|
3543
|
-
} finally {
|
|
3544
|
-
endCommand();
|
|
3545
|
-
}
|
|
3546
|
-
};
|
|
3547
|
-
|
|
3548
3407
|
const runRemove = async () => {
|
|
3549
3408
|
const initiator = new ProjectInitiator();
|
|
3550
3409
|
fileLog('INFO', 'runRemove: checking for AVC project', { cwd: process.cwd() });
|
|
@@ -3628,183 +3487,6 @@ const App = () => {
|
|
|
3628
3487
|
}, 100);
|
|
3629
3488
|
};
|
|
3630
3489
|
|
|
3631
|
-
const runBuildDocumentation = async () => {
|
|
3632
|
-
startCommand('documentation');
|
|
3633
|
-
try {
|
|
3634
|
-
const ts0 = Date.now();
|
|
3635
|
-
const builder = new DocumentationBuilder();
|
|
3636
|
-
const manager = getProcessManager();
|
|
3637
|
-
|
|
3638
|
-
fileLog('INFO', 'runBuildDocumentation started', { cwd: process.cwd() });
|
|
3639
|
-
|
|
3640
|
-
// Check if project is initialized
|
|
3641
|
-
const hasDocumentation = builder.hasDocumentation();
|
|
3642
|
-
fileLog('INFO', 'documentation check', { hasDocumentation });
|
|
3643
|
-
|
|
3644
|
-
if (!hasDocumentation) {
|
|
3645
|
-
fileLog('WARNING', 'documentation not found, aborting');
|
|
3646
|
-
sendError('Documentation not found ā run /init first to create documentation structure');
|
|
3647
|
-
return;
|
|
3648
|
-
}
|
|
3649
|
-
|
|
3650
|
-
const port = builder.getPort();
|
|
3651
|
-
fileLog('INFO', 'documentation port determined', { port });
|
|
3652
|
-
|
|
3653
|
-
// Check if documentation server is already running (managed process)
|
|
3654
|
-
const runningProcesses = manager.getRunningProcesses();
|
|
3655
|
-
const existingDocServer = runningProcesses.find(p => p.name === 'Documentation Server');
|
|
3656
|
-
fileLog('INFO', 'managed process check', {
|
|
3657
|
-
runningProcessCount: runningProcesses.length,
|
|
3658
|
-
existingDocServer: existingDocServer ? { id: existingDocServer.id, name: existingDocServer.name } : null
|
|
3659
|
-
});
|
|
3660
|
-
|
|
3661
|
-
if (existingDocServer) {
|
|
3662
|
-
// We have a managed process - check if it's actually running
|
|
3663
|
-
const portInUse = await builder.isPortInUse(port);
|
|
3664
|
-
fileLog('INFO', 'managed process port check', { portInUse });
|
|
3665
|
-
|
|
3666
|
-
if (portInUse) {
|
|
3667
|
-
// Managed process exists and port is in use - restart it
|
|
3668
|
-
fileLog('INFO', 'managed process running, restarting', { processId: existingDocServer.id });
|
|
3669
|
-
sendInfo('Documentation server already running ā restarting');
|
|
3670
|
-
manager.stopProcess(existingDocServer.id);
|
|
3671
|
-
|
|
3672
|
-
// Clean up stopped/finished processes
|
|
3673
|
-
manager.cleanupFinished();
|
|
3674
|
-
|
|
3675
|
-
// Wait a bit for the port to be released
|
|
3676
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
3677
|
-
} else {
|
|
3678
|
-
// Managed process exists but port is not in use - it died, clean up
|
|
3679
|
-
fileLog('WARNING', 'managed process died (port not in use), cleaning up', { processId: existingDocServer.id });
|
|
3680
|
-
sendWarning('Previous documentation server stopped ā starting new one');
|
|
3681
|
-
manager.stopProcess(existingDocServer.id);
|
|
3682
|
-
|
|
3683
|
-
// Clean up stopped/finished processes
|
|
3684
|
-
manager.cleanupFinished();
|
|
3685
|
-
}
|
|
3686
|
-
} else {
|
|
3687
|
-
// No managed process - check if port is in use by external process
|
|
3688
|
-
const portInUse = await builder.isPortInUse(port);
|
|
3689
|
-
fileLog('INFO', 'no managed process, external port check', { portInUse });
|
|
3690
|
-
|
|
3691
|
-
if (portInUse) {
|
|
3692
|
-
// Port is in use by external process - find and kill it
|
|
3693
|
-
const processInfo = await builder.findProcessUsingPort(port);
|
|
3694
|
-
fileLog('INFO', 'process found on port', { processInfo });
|
|
3695
|
-
|
|
3696
|
-
if (processInfo) {
|
|
3697
|
-
// Found the process using the port - check if it's AVC documentation
|
|
3698
|
-
const isOurDocs = await builder.isDocumentationServer(port);
|
|
3699
|
-
fileLog('INFO', 'is-our-docs check', { isOurDocs, pid: processInfo.pid, command: processInfo.command });
|
|
3700
|
-
|
|
3701
|
-
if (isOurDocs) {
|
|
3702
|
-
// It's confirmed to be AVC documentation server - safe to kill
|
|
3703
|
-
sendInfo(`AVC documentation server already running (external process ā PID ${processInfo.pid})`);
|
|
3704
|
-
sendInfo('Killing external process and restarting...');
|
|
3705
|
-
|
|
3706
|
-
// Try to kill the process
|
|
3707
|
-
const killed = await builder.killProcess(processInfo.pid);
|
|
3708
|
-
fileLog(killed ? 'INFO' : 'ERROR', 'kill external docs process', { pid: processInfo.pid, killed });
|
|
3709
|
-
|
|
3710
|
-
if (!killed) {
|
|
3711
|
-
// Failed to kill (permission denied, etc.)
|
|
3712
|
-
fileLog('ERROR', 'failed to kill process, aborting', { pid: processInfo.pid });
|
|
3713
|
-
sendError(`Failed to kill process ${processInfo.pid} ā permission denied or process protected`);
|
|
3714
|
-
sendOutput('Please manually stop the process or change the port.');
|
|
3715
|
-
sendOutput('To change the port, edit .avc/avc.json:');
|
|
3716
|
-
sendOutput(' { "settings": { "documentation": { "port": 5173 } } }');
|
|
3717
|
-
return;
|
|
3718
|
-
}
|
|
3719
|
-
|
|
3720
|
-
sendSuccess('External process killed');
|
|
3721
|
-
|
|
3722
|
-
// Remove from process manager if it was a managed process
|
|
3723
|
-
manager.removeProcessByPid(processInfo.pid);
|
|
3724
|
-
|
|
3725
|
-
// Wait for port to be released
|
|
3726
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
3727
|
-
} else {
|
|
3728
|
-
// It's NOT AVC documentation - ask user if they want to kill it anyway
|
|
3729
|
-
fileLog('WARNING', 'port in use by non-AVC process, prompting user for confirmation', { pid: processInfo.pid, command: processInfo.command, port });
|
|
3730
|
-
setProcessToKill({
|
|
3731
|
-
pid: processInfo.pid,
|
|
3732
|
-
command: processInfo.command,
|
|
3733
|
-
port: port
|
|
3734
|
-
});
|
|
3735
|
-
setKillConfirmActive(true);
|
|
3736
|
-
setMode('kill-confirm');
|
|
3737
|
-
return;
|
|
3738
|
-
}
|
|
3739
|
-
} else {
|
|
3740
|
-
// Port is in use but couldn't find the process (rare case)
|
|
3741
|
-
fileLog('ERROR', 'port in use but process unidentifiable', { port });
|
|
3742
|
-
sendError(`Port ${port} is in use but process could not be identified`);
|
|
3743
|
-
sendOutput('To change the port, edit .avc/avc.json:');
|
|
3744
|
-
sendOutput(' { "settings": { "documentation": { "port": 5173 } } }');
|
|
3745
|
-
return;
|
|
3746
|
-
}
|
|
3747
|
-
}
|
|
3748
|
-
}
|
|
3749
|
-
|
|
3750
|
-
// Sync sprint planning docs before starting VitePress
|
|
3751
|
-
const syncer = new DocsSyncProcessor(process.cwd());
|
|
3752
|
-
try {
|
|
3753
|
-
const hierarchy = syncer.readHierarchy();
|
|
3754
|
-
if (hierarchy.length > 0) {
|
|
3755
|
-
fileLog('INFO', 'syncing project docs before VitePress start', { epicCount: hierarchy.length });
|
|
3756
|
-
const stats = await syncer.sync();
|
|
3757
|
-
sendSuccess(`Synced ${stats.epics} epics, ${stats.stories} stories (${stats.copied} files updated)`);
|
|
3758
|
-
fileLog('INFO', 'docs sync complete', stats);
|
|
3759
|
-
} else {
|
|
3760
|
-
sendInfo('No sprint planning results yet ā serving project brief only');
|
|
3761
|
-
fileLog('INFO', 'no epics found, skipping docs sync');
|
|
3762
|
-
}
|
|
3763
|
-
} catch (syncErr) {
|
|
3764
|
-
fileLog('WARNING', 'docs sync failed (non-fatal)', { error: syncErr.message });
|
|
3765
|
-
}
|
|
3766
|
-
|
|
3767
|
-
// Start dev server in background (builds on-demand, hot-reloads on .md changes)
|
|
3768
|
-
fileLog('INFO', 'starting documentation dev server', { port, docsDir: builder.docsDir });
|
|
3769
|
-
const processId = manager.startProcess({
|
|
3770
|
-
name: 'Documentation Server',
|
|
3771
|
-
command: 'npx',
|
|
3772
|
-
args: ['vitepress', 'dev', '--port', String(port)],
|
|
3773
|
-
cwd: builder.docsDir
|
|
3774
|
-
});
|
|
3775
|
-
|
|
3776
|
-
// Register chokidar watcher to keep docs in sync while server runs
|
|
3777
|
-
let docsWatcher = null;
|
|
3778
|
-
try {
|
|
3779
|
-
docsWatcher = syncer.watch();
|
|
3780
|
-
fileLog('INFO', 'docs file watcher registered');
|
|
3781
|
-
} catch (watchErr) {
|
|
3782
|
-
fileLog('WARNING', 'failed to register docs watcher (non-fatal)', { error: watchErr.message });
|
|
3783
|
-
}
|
|
3784
|
-
|
|
3785
|
-
// Close watcher when documentation server stops
|
|
3786
|
-
if (docsWatcher) {
|
|
3787
|
-
const closeWatcher = () => { docsWatcher.close(); };
|
|
3788
|
-
manager.once('process-stopped', (proc) => {
|
|
3789
|
-
if (proc && proc.id === processId) closeWatcher();
|
|
3790
|
-
});
|
|
3791
|
-
manager.once('process-exited', (proc) => {
|
|
3792
|
-
if (proc && proc.id === processId) closeWatcher();
|
|
3793
|
-
});
|
|
3794
|
-
}
|
|
3795
|
-
|
|
3796
|
-
fileLog('INFO', 'runBuildDocumentation complete', { processId, port, totalDuration: `${Date.now() - ts0}ms` });
|
|
3797
|
-
sendSuccess('Documentation server started');
|
|
3798
|
-
sendIndented(`${gray('URL')} http://localhost:${port}`, 1);
|
|
3799
|
-
sendIndented(`${gray('PID')} ${processId}`, 1);
|
|
3800
|
-
sendInfo('Stop with /processes ā select Documentation Server ā S');
|
|
3801
|
-
sendInfo('File changes in .avc/project/ will auto-sync to documentation.');
|
|
3802
|
-
sendOutput('');
|
|
3803
|
-
} finally {
|
|
3804
|
-
endCommand();
|
|
3805
|
-
}
|
|
3806
|
-
};
|
|
3807
|
-
|
|
3808
3490
|
/**
|
|
3809
3491
|
* Fork the Kanban server via IPC and set up ceremony worker relay.
|
|
3810
3492
|
* Returns { id, child } from BackgroundProcessManager.forkProcess().
|
|
@@ -3828,7 +3510,7 @@ const App = () => {
|
|
|
3828
3510
|
(msg) => {
|
|
3829
3511
|
// āā ceremony:fork ā CLI forks the worker on behalf of Kanban āāāāāāāāāā
|
|
3830
3512
|
if (msg.type === 'ceremony:fork') {
|
|
3831
|
-
const { ceremonyType, processId, requirements, costThreshold } = msg;
|
|
3513
|
+
const { ceremonyType, processId, requirements, costThreshold, resumeFrom } = msg;
|
|
3832
3514
|
const workerFile = ceremonyType === 'sprint-planning'
|
|
3833
3515
|
? 'sprint-planning-worker.js'
|
|
3834
3516
|
: 'sponsor-call-worker.js';
|
|
@@ -3862,6 +3544,7 @@ const App = () => {
|
|
|
3862
3544
|
type: 'init',
|
|
3863
3545
|
...(requirements != null ? { requirements } : {}),
|
|
3864
3546
|
...(costThreshold != null ? { costThreshold } : {}),
|
|
3547
|
+
...(resumeFrom != null ? { resumeFrom } : {}),
|
|
3865
3548
|
});
|
|
3866
3549
|
|
|
3867
3550
|
// Notify Kanban that the worker is live
|
|
@@ -4097,8 +3780,16 @@ const App = () => {
|
|
|
4097
3780
|
setMode('selector');
|
|
4098
3781
|
setInput(''); // Clear input when entering selector
|
|
4099
3782
|
} else {
|
|
4100
|
-
|
|
4101
|
-
|
|
3783
|
+
const resolved = resolveAlias(input.trim());
|
|
3784
|
+
// /init: show directory confirmation before creating files (only when not yet initialized)
|
|
3785
|
+
if (resolved === '/init' && !existsSync(path.join(process.cwd(), '.avc'))) {
|
|
3786
|
+
setInitConfirmDir(process.cwd());
|
|
3787
|
+
setInitConfirmActive(true);
|
|
3788
|
+
setInput('');
|
|
3789
|
+
} else {
|
|
3790
|
+
// Execute the typed command or selected command
|
|
3791
|
+
executeCommand(input);
|
|
3792
|
+
}
|
|
4102
3793
|
}
|
|
4103
3794
|
} else {
|
|
4104
3795
|
// Execute command
|
|
@@ -4132,7 +3823,7 @@ const App = () => {
|
|
|
4132
3823
|
setMode('selector');
|
|
4133
3824
|
}
|
|
4134
3825
|
}
|
|
4135
|
-
}, { isActive: mode === 'prompt' && !questionnaireActive && !showPreview && !modelConfigActive && !removeConfirmActive && !deploymentStrategySelectorActive && !architectureSelectorActive && !cloudProviderSelectorActive && !databaseChoiceActive && isStableRender });
|
|
3826
|
+
}, { isActive: mode === 'prompt' && !questionnaireActive && !showPreview && !modelConfigActive && !removeConfirmActive && !initConfirmActive && !deploymentStrategySelectorActive && !architectureSelectorActive && !cloudProviderSelectorActive && !databaseChoiceActive && isStableRender });
|
|
4136
3827
|
|
|
4137
3828
|
// Handle keyboard input in selector mode
|
|
4138
3829
|
useInput((inputChar, key) => {
|
|
@@ -5147,6 +4838,23 @@ const App = () => {
|
|
|
5147
4838
|
}
|
|
5148
4839
|
}, { isActive: cancelExecutionActive });
|
|
5149
4840
|
|
|
4841
|
+
// Init confirmation input handler
|
|
4842
|
+
useInput((inputChar, key) => {
|
|
4843
|
+
if (!initConfirmActive) return;
|
|
4844
|
+
|
|
4845
|
+
if (key.return || inputChar === 'y' || inputChar === 'Y') {
|
|
4846
|
+
setInitConfirmActive(false);
|
|
4847
|
+
executeCommand('/init');
|
|
4848
|
+
return;
|
|
4849
|
+
}
|
|
4850
|
+
|
|
4851
|
+
if (key.escape || inputChar === 'n' || inputChar === 'N') {
|
|
4852
|
+
setInitConfirmActive(false);
|
|
4853
|
+
outputBuffer.append('Init cancelled.\n');
|
|
4854
|
+
return;
|
|
4855
|
+
}
|
|
4856
|
+
}, { isActive: initConfirmActive });
|
|
4857
|
+
|
|
5150
4858
|
// Remove confirmation input handler
|
|
5151
4859
|
useInput((inputChar, key) => {
|
|
5152
4860
|
if (!removeConfirmActive) return;
|
|
@@ -5787,6 +5495,23 @@ const App = () => {
|
|
|
5787
5495
|
});
|
|
5788
5496
|
}
|
|
5789
5497
|
|
|
5498
|
+
// Show init confirmation if active
|
|
5499
|
+
if (initConfirmActive) {
|
|
5500
|
+
return React.createElement(Box, { flexDirection: 'column' },
|
|
5501
|
+
React.createElement(Text, null, ''),
|
|
5502
|
+
React.createElement(Text, null, 'Initialize AVC project in:'),
|
|
5503
|
+
React.createElement(Text, { bold: true }, initConfirmDir),
|
|
5504
|
+
React.createElement(Text, null, ''),
|
|
5505
|
+
React.createElement(Text, null, ''),
|
|
5506
|
+
React.createElement(Text, null,
|
|
5507
|
+
React.createElement(Text, { color: 'green' }, 'Y'),
|
|
5508
|
+
React.createElement(Text, null, ' to confirm '),
|
|
5509
|
+
React.createElement(Text, { color: 'red' }, 'N'),
|
|
5510
|
+
React.createElement(Text, null, ' to cancel'),
|
|
5511
|
+
),
|
|
5512
|
+
);
|
|
5513
|
+
}
|
|
5514
|
+
|
|
5790
5515
|
// Show remove confirmation if active
|
|
5791
5516
|
if (removeConfirmActive) {
|
|
5792
5517
|
return React.createElement(RemoveConfirmation, {
|
|
@@ -5912,7 +5637,15 @@ const App = () => {
|
|
|
5912
5637
|
filter: input,
|
|
5913
5638
|
onSelect: (item) => {
|
|
5914
5639
|
if (item && item.value) {
|
|
5915
|
-
|
|
5640
|
+
// /init: show directory confirmation before creating files
|
|
5641
|
+
if (item.value === '/init' && !existsSync(path.join(process.cwd(), '.avc'))) {
|
|
5642
|
+
setMode('prompt');
|
|
5643
|
+
setInput('');
|
|
5644
|
+
setInitConfirmDir(process.cwd());
|
|
5645
|
+
setInitConfirmActive(true);
|
|
5646
|
+
} else {
|
|
5647
|
+
executeCommand(item.value);
|
|
5648
|
+
}
|
|
5916
5649
|
} else {
|
|
5917
5650
|
// Invalid item, return to prompt
|
|
5918
5651
|
setMode('prompt');
|
|
@@ -5986,7 +5719,7 @@ const App = () => {
|
|
|
5986
5719
|
};
|
|
5987
5720
|
|
|
5988
5721
|
const renderPrompt = () => {
|
|
5989
|
-
if (mode !== 'prompt' || questionnaireActive || showPreview || removeConfirmActive || killConfirmActive || kanbanPortConflictActive || processViewerActive || cancelConfirmActive || isExecuting || modelConfigActive || architectureSelectorActive || cloudProviderSelectorActive || databaseChoiceActive || databaseQuestionsActive || deploymentStrategySelectorActive) return null;
|
|
5722
|
+
if (mode !== 'prompt' || questionnaireActive || showPreview || removeConfirmActive || initConfirmActive || killConfirmActive || kanbanPortConflictActive || processViewerActive || cancelConfirmActive || isExecuting || modelConfigActive || architectureSelectorActive || cloudProviderSelectorActive || databaseChoiceActive || databaseQuestionsActive || deploymentStrategySelectorActive) return null;
|
|
5990
5723
|
|
|
5991
5724
|
// Show loading indicator while app is initializing
|
|
5992
5725
|
if (!isStableRender) {
|
|
@@ -6014,7 +5747,7 @@ const App = () => {
|
|
|
6014
5747
|
renderSelector(),
|
|
6015
5748
|
renderModelConfig(),
|
|
6016
5749
|
renderPrompt(),
|
|
6017
|
-
!questionnaireActive && !showPreview && !removeConfirmActive && !killConfirmActive && !kanbanPortConflictActive && !processViewerActive && !cancelConfirmActive && !modelConfigActive && mode !== 'executing' && React.createElement(BottomRightStatus, { backgroundProcesses })
|
|
5750
|
+
!questionnaireActive && !showPreview && !removeConfirmActive && !initConfirmActive && !killConfirmActive && !kanbanPortConflictActive && !processViewerActive && !cancelConfirmActive && !modelConfigActive && mode !== 'executing' && React.createElement(BottomRightStatus, { backgroundProcesses })
|
|
6018
5751
|
);
|
|
6019
5752
|
};
|
|
6020
5753
|
|
|
@@ -6050,6 +5783,18 @@ export function startRepl() {
|
|
|
6050
5783
|
console.log(` Stopped ${stopped} process(es)\n`);
|
|
6051
5784
|
}
|
|
6052
5785
|
|
|
5786
|
+
// Kill stale kanban server on port (not tracked by this session's manager)
|
|
5787
|
+
try {
|
|
5788
|
+
const mgr = new KanbanServerManager();
|
|
5789
|
+
const port = mgr.getPort();
|
|
5790
|
+
const { stdout } = execSync(`lsof -i :${port} -t -sTCP:LISTEN 2>/dev/null`, { encoding: 'utf8' });
|
|
5791
|
+
const pid = parseInt(stdout.trim());
|
|
5792
|
+
if (pid && !isNaN(pid)) {
|
|
5793
|
+
execSync(`kill -9 ${pid} 2>/dev/null`);
|
|
5794
|
+
console.log(`Killed stale kanban server (PID ${pid})`);
|
|
5795
|
+
}
|
|
5796
|
+
} catch (_) {}
|
|
5797
|
+
|
|
6053
5798
|
console.log('Thanks for using AVC!\n');
|
|
6054
5799
|
process.exit(0);
|
|
6055
5800
|
};
|
|
@@ -6064,6 +5809,19 @@ export function startRepl() {
|
|
|
6064
5809
|
cleanupAndExit('SIGTERM');
|
|
6065
5810
|
});
|
|
6066
5811
|
|
|
5812
|
+
// Helper: synchronously kill any process listening on the kanban port
|
|
5813
|
+
const killStaleKanban = () => {
|
|
5814
|
+
try {
|
|
5815
|
+
const mgr = new KanbanServerManager();
|
|
5816
|
+
const port = mgr.getPort();
|
|
5817
|
+
const { stdout } = execSync(`lsof -i :${port} -t -sTCP:LISTEN 2>/dev/null`, { encoding: 'utf8' });
|
|
5818
|
+
const pid = parseInt(stdout.trim());
|
|
5819
|
+
if (pid && !isNaN(pid)) {
|
|
5820
|
+
execSync(`kill -9 ${pid} 2>/dev/null`);
|
|
5821
|
+
}
|
|
5822
|
+
} catch (_) {}
|
|
5823
|
+
};
|
|
5824
|
+
|
|
6067
5825
|
// Handle uncaught exceptions
|
|
6068
5826
|
process.on('uncaughtException', (error) => {
|
|
6069
5827
|
console.error('\n\nUncaught exception:', error.message);
|
|
@@ -6074,6 +5832,7 @@ export function startRepl() {
|
|
|
6074
5832
|
console.log('\nStopping background processes...');
|
|
6075
5833
|
manager.stopAll();
|
|
6076
5834
|
}
|
|
5835
|
+
killStaleKanban();
|
|
6077
5836
|
|
|
6078
5837
|
process.exit(1);
|
|
6079
5838
|
});
|
|
@@ -6088,6 +5847,7 @@ export function startRepl() {
|
|
|
6088
5847
|
console.log('\nStopping background processes...');
|
|
6089
5848
|
manager.stopAll();
|
|
6090
5849
|
}
|
|
5850
|
+
killStaleKanban();
|
|
6091
5851
|
|
|
6092
5852
|
process.exit(1);
|
|
6093
5853
|
});
|
package/cli/repl-old.js
CHANGED
|
@@ -51,8 +51,7 @@ export class AvcRepl {
|
|
|
51
51
|
|
|
52
52
|
showVersion() {
|
|
53
53
|
console.log(`\nšÆ AVC Framework v${this.version}`);
|
|
54
|
-
console.log('Agile Vibe Coding - AI-powered development framework');
|
|
55
|
-
console.log('https://agilevibecoding.org\n');
|
|
54
|
+
console.log('Agile Vibe Coding - AI-powered development framework\n');
|
|
56
55
|
}
|
|
57
56
|
|
|
58
57
|
async handleCommand(command) {
|