@compilr-dev/cli 0.4.0 → 0.5.0
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 +30 -12
- package/dist/agent.d.ts +74 -1
- package/dist/agent.js +259 -76
- package/dist/anchors/index.d.ts +9 -0
- package/dist/anchors/index.js +9 -0
- package/dist/anchors/project-anchors.d.ts +79 -0
- package/dist/anchors/project-anchors.js +202 -0
- package/dist/commands/handler-types.d.ts +68 -0
- package/dist/commands/handler-types.js +8 -0
- package/dist/commands/handlers/agent-commands.d.ts +13 -0
- package/dist/commands/handlers/agent-commands.js +305 -0
- package/dist/commands/handlers/design-commands.d.ts +15 -0
- package/dist/commands/handlers/design-commands.js +334 -0
- package/dist/commands/handlers/index.d.ts +20 -0
- package/dist/commands/handlers/index.js +43 -0
- package/dist/commands/handlers/overlay-commands.d.ts +21 -0
- package/dist/commands/handlers/overlay-commands.js +287 -0
- package/dist/commands/handlers/project-commands.d.ts +11 -0
- package/dist/commands/handlers/project-commands.js +167 -0
- package/dist/commands/handlers/simple-commands.d.ts +19 -0
- package/dist/commands/handlers/simple-commands.js +144 -0
- package/dist/commands/index.d.ts +2 -1
- package/dist/commands/registry.d.ts +50 -0
- package/dist/commands/registry.js +75 -0
- package/dist/commands-v2/handlers/context.d.ts +13 -0
- package/dist/commands-v2/handlers/context.js +348 -0
- package/dist/commands-v2/handlers/core.d.ts +13 -0
- package/dist/commands-v2/handlers/core.js +165 -0
- package/dist/commands-v2/handlers/debug.d.ts +11 -0
- package/dist/commands-v2/handlers/debug.js +159 -0
- package/dist/commands-v2/handlers/index.d.ts +12 -0
- package/dist/commands-v2/handlers/index.js +24 -0
- package/dist/commands-v2/handlers/project.d.ts +22 -0
- package/dist/commands-v2/handlers/project.js +814 -0
- package/dist/commands-v2/handlers/settings.d.ts +15 -0
- package/dist/commands-v2/handlers/settings.js +235 -0
- package/dist/commands-v2/index.d.ts +13 -0
- package/dist/commands-v2/index.js +15 -0
- package/dist/commands-v2/registry.d.ts +37 -0
- package/dist/commands-v2/registry.js +80 -0
- package/dist/commands-v2/types.d.ts +75 -0
- package/dist/commands-v2/types.js +7 -0
- package/dist/commands.js +110 -7
- package/dist/index.js +288 -29
- package/dist/input-handlers/index.d.ts +7 -0
- package/dist/input-handlers/index.js +7 -0
- package/dist/input-handlers/memory-handler.d.ts +26 -0
- package/dist/input-handlers/memory-handler.js +68 -0
- package/dist/repl-helpers.d.ts +63 -0
- package/dist/repl-helpers.js +318 -0
- package/dist/repl-v2.d.ts +155 -0
- package/dist/repl-v2.js +774 -0
- package/dist/repl.d.ts +32 -4
- package/dist/repl.js +250 -977
- package/dist/settings/index.d.ts +23 -0
- package/dist/settings/index.js +48 -0
- package/dist/settings/paths.d.ts +110 -0
- package/dist/settings/paths.js +264 -0
- package/dist/templates/compilr-md.js +7 -4
- package/dist/templates/index.js +3 -4
- package/dist/themes/colors.js +3 -1
- package/dist/themes/registry.d.ts +5 -36
- package/dist/themes/registry.js +11 -95
- package/dist/themes/types.d.ts +3 -38
- package/dist/themes/types.js +2 -2
- package/dist/tools/anchor-tools.d.ts +31 -0
- package/dist/tools/anchor-tools.js +255 -0
- package/dist/tools/backlog-wrappers.d.ts +54 -0
- package/dist/tools/backlog-wrappers.js +338 -0
- package/dist/tools/backlog.js +1 -1
- package/dist/tools/db-tools.d.ts +65 -0
- package/dist/tools/db-tools.js +19 -0
- package/dist/tools/document-db.d.ts +43 -0
- package/dist/tools/document-db.js +220 -0
- package/dist/tools/project-db.d.ts +102 -0
- package/dist/tools/project-db.js +370 -0
- package/dist/tools/workitem-db.d.ts +103 -0
- package/dist/tools/workitem-db.js +549 -0
- package/dist/tools.js +13 -3
- package/dist/ui/agents-overlay-v2.d.ts +43 -0
- package/dist/ui/agents-overlay-v2.js +809 -0
- package/dist/ui/agents-overlay.d.ts +5 -5
- package/dist/ui/agents-overlay.js +782 -420
- package/dist/ui/anchors-overlay.d.ts +12 -0
- package/dist/ui/anchors-overlay.js +775 -0
- package/dist/ui/arch-type-overlay.d.ts +1 -6
- package/dist/ui/arch-type-overlay.js +175 -203
- package/dist/ui/ask-user-overlay-v2.d.ts +26 -0
- package/dist/ui/ask-user-overlay-v2.js +555 -0
- package/dist/ui/ask-user-overlay.d.ts +2 -2
- package/dist/ui/ask-user-overlay.js +443 -535
- package/dist/ui/ask-user-simple-overlay-v2.d.ts +25 -0
- package/dist/ui/ask-user-simple-overlay-v2.js +215 -0
- package/dist/ui/ask-user-simple-overlay.d.ts +2 -2
- package/dist/ui/ask-user-simple-overlay.js +182 -209
- package/dist/ui/backlog-overlay.d.ts +16 -1
- package/dist/ui/backlog-overlay.js +525 -659
- package/dist/ui/base/index.d.ts +26 -0
- package/dist/ui/base/index.js +33 -0
- package/dist/ui/base/inline-overlay-utils.d.ts +217 -0
- package/dist/ui/base/inline-overlay-utils.js +320 -0
- package/dist/ui/base/inline-overlay.d.ts +159 -0
- package/dist/ui/base/inline-overlay.js +257 -0
- package/dist/ui/base/key-utils.d.ts +15 -0
- package/dist/ui/base/key-utils.js +30 -0
- package/dist/ui/base/overlay-base-v2.d.ts +193 -0
- package/dist/ui/base/overlay-base-v2.js +246 -0
- package/dist/ui/base/overlay-base.d.ts +156 -0
- package/dist/ui/base/overlay-base.js +238 -0
- package/dist/ui/base/overlay-lifecycle.d.ts +65 -0
- package/dist/ui/base/overlay-lifecycle.js +159 -0
- package/dist/ui/base/overlay-types.d.ts +185 -0
- package/dist/ui/base/overlay-types.js +7 -0
- package/dist/ui/base/render-utils.d.ts +8 -0
- package/dist/ui/base/render-utils.js +11 -0
- package/dist/ui/base/screen-stack.d.ts +148 -0
- package/dist/ui/base/screen-stack.js +184 -0
- package/dist/ui/base/tabbed-list-overlay-v2.d.ts +103 -0
- package/dist/ui/base/tabbed-list-overlay-v2.js +317 -0
- package/dist/ui/base/tabbed-list-overlay.d.ts +153 -0
- package/dist/ui/base/tabbed-list-overlay.js +369 -0
- package/dist/ui/commands-overlay-v2.d.ts +33 -0
- package/dist/ui/commands-overlay-v2.js +441 -0
- package/dist/ui/commands-overlay.d.ts +7 -2
- package/dist/ui/commands-overlay.js +384 -355
- package/dist/ui/config-overlay.d.ts +5 -4
- package/dist/ui/config-overlay.js +243 -513
- package/dist/ui/conversation.d.ts +75 -4
- package/dist/ui/conversation.js +374 -161
- package/dist/ui/docs-overlay.d.ts +17 -0
- package/dist/ui/docs-overlay.js +303 -0
- package/dist/ui/ephemeral.d.ts +1 -1
- package/dist/ui/ephemeral.js +1 -1
- package/dist/ui/features/index.d.ts +34 -0
- package/dist/ui/features/index.js +34 -0
- package/dist/ui/features/input-feature.d.ts +85 -0
- package/dist/ui/features/input-feature.js +238 -0
- package/dist/ui/features/list-feature.d.ts +155 -0
- package/dist/ui/features/list-feature.js +244 -0
- package/dist/ui/features/pagination-feature.d.ts +154 -0
- package/dist/ui/features/pagination-feature.js +238 -0
- package/dist/ui/features/search-feature.d.ts +148 -0
- package/dist/ui/features/search-feature.js +185 -0
- package/dist/ui/features/tab-feature.d.ts +194 -0
- package/dist/ui/features/tab-feature.js +307 -0
- package/dist/ui/footer-v2.d.ts +222 -0
- package/dist/ui/footer-v2.js +1349 -0
- package/dist/ui/footer.d.ts +107 -0
- package/dist/ui/footer.js +359 -67
- package/dist/ui/guardrail-overlay.d.ts +29 -0
- package/dist/ui/guardrail-overlay.js +145 -0
- package/dist/ui/help-overlay-v2.d.ts +34 -0
- package/dist/ui/help-overlay-v2.js +309 -0
- package/dist/ui/help-overlay.d.ts +16 -0
- package/dist/ui/help-overlay.js +316 -0
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +1 -3
- package/dist/ui/init-overlay-v2.d.ts +34 -0
- package/dist/ui/init-overlay-v2.js +600 -0
- package/dist/ui/init-overlay.d.ts +12 -2
- package/dist/ui/init-overlay.js +349 -270
- package/dist/ui/input-prompt-v2.d.ts +1 -0
- package/dist/ui/input-prompt-v2.js +14 -6
- package/dist/ui/input-prompt.d.ts +116 -33
- package/dist/ui/input-prompt.js +536 -337
- package/dist/ui/iteration-limit-overlay-v2.d.ts +21 -0
- package/dist/ui/iteration-limit-overlay-v2.js +114 -0
- package/dist/ui/iteration-limit-overlay.d.ts +2 -2
- package/dist/ui/iteration-limit-overlay.js +92 -128
- package/dist/ui/keys-overlay-v2.d.ts +41 -0
- package/dist/ui/keys-overlay-v2.js +248 -0
- package/dist/ui/keys-overlay.d.ts +1 -0
- package/dist/ui/keys-overlay.js +203 -141
- package/dist/ui/line-utils.d.ts +88 -0
- package/dist/ui/line-utils.js +150 -0
- package/dist/ui/live-region.d.ts +161 -0
- package/dist/ui/live-region.js +387 -0
- package/dist/ui/mascot/expressions.d.ts +32 -0
- package/dist/ui/mascot/expressions.js +213 -0
- package/dist/ui/mascot/index.d.ts +8 -0
- package/dist/ui/mascot/index.js +8 -0
- package/dist/ui/mascot/renderer.d.ts +19 -0
- package/dist/ui/mascot/renderer.js +97 -0
- package/dist/ui/mascot-overlay-v2.d.ts +41 -0
- package/dist/ui/mascot-overlay-v2.js +138 -0
- package/dist/ui/mascot-overlay.d.ts +21 -0
- package/dist/ui/mascot-overlay.js +146 -0
- package/dist/ui/model-overlay-v2.d.ts +49 -0
- package/dist/ui/model-overlay-v2.js +118 -0
- package/dist/ui/model-overlay.d.ts +27 -0
- package/dist/ui/model-overlay.js +221 -0
- package/dist/ui/model-warning-overlay.js +3 -5
- package/dist/ui/new-overlay.d.ts +34 -0
- package/dist/ui/new-overlay.js +604 -0
- package/dist/ui/overlay/impl/agents-overlay-v2.d.ts +45 -0
- package/dist/ui/overlay/impl/agents-overlay-v2.js +825 -0
- package/dist/ui/overlay/impl/anchors-overlay-v2.d.ts +47 -0
- package/dist/ui/overlay/impl/anchors-overlay-v2.js +783 -0
- package/dist/ui/overlay/impl/arch-type-overlay-v2.d.ts +37 -0
- package/dist/ui/overlay/impl/arch-type-overlay-v2.js +240 -0
- package/dist/ui/overlay/impl/ask-user-overlay-v2.d.ts +72 -0
- package/dist/ui/overlay/impl/ask-user-overlay-v2.js +584 -0
- package/dist/ui/overlay/impl/ask-user-simple-overlay-v2.d.ts +46 -0
- package/dist/ui/overlay/impl/ask-user-simple-overlay-v2.js +204 -0
- package/dist/ui/overlay/impl/backlog-overlay-v2.d.ts +49 -0
- package/dist/ui/overlay/impl/backlog-overlay-v2.js +642 -0
- package/dist/ui/overlay/impl/commands-overlay-v2.d.ts +33 -0
- package/dist/ui/overlay/impl/commands-overlay-v2.js +441 -0
- package/dist/ui/overlay/impl/config-overlay-v2.d.ts +100 -0
- package/dist/ui/overlay/impl/config-overlay-v2.js +654 -0
- package/dist/ui/overlay/impl/dashboard-overlay-v2.d.ts +55 -0
- package/dist/ui/overlay/impl/dashboard-overlay-v2.js +359 -0
- package/dist/ui/overlay/impl/docs-overlay-v2.d.ts +45 -0
- package/dist/ui/overlay/impl/docs-overlay-v2.js +114 -0
- package/dist/ui/overlay/impl/document-detail-overlay-v2.d.ts +77 -0
- package/dist/ui/overlay/impl/document-detail-overlay-v2.js +1071 -0
- package/dist/ui/overlay/impl/guardrail-overlay-v2.d.ts +43 -0
- package/dist/ui/overlay/impl/guardrail-overlay-v2.js +114 -0
- package/dist/ui/overlay/impl/help-overlay-v2.d.ts +34 -0
- package/dist/ui/overlay/impl/help-overlay-v2.js +309 -0
- package/dist/ui/overlay/impl/init-overlay-v2.d.ts +77 -0
- package/dist/ui/overlay/impl/init-overlay-v2.js +593 -0
- package/dist/ui/overlay/impl/init-setup-overlay-v2.d.ts +25 -0
- package/dist/ui/overlay/impl/init-setup-overlay-v2.js +97 -0
- package/dist/ui/overlay/impl/iteration-limit-overlay-v2.d.ts +35 -0
- package/dist/ui/overlay/impl/iteration-limit-overlay-v2.js +105 -0
- package/dist/ui/overlay/impl/keys-overlay-v2.d.ts +41 -0
- package/dist/ui/overlay/impl/keys-overlay-v2.js +248 -0
- package/dist/ui/overlay/impl/mascot-overlay-v2.d.ts +41 -0
- package/dist/ui/overlay/impl/mascot-overlay-v2.js +138 -0
- package/dist/ui/overlay/impl/model-overlay-v2.d.ts +49 -0
- package/dist/ui/overlay/impl/model-overlay-v2.js +118 -0
- package/dist/ui/overlay/impl/model-warning-overlay-v2.d.ts +46 -0
- package/dist/ui/overlay/impl/model-warning-overlay-v2.js +132 -0
- package/dist/ui/overlay/impl/new-overlay-v2.d.ts +77 -0
- package/dist/ui/overlay/impl/new-overlay-v2.js +593 -0
- package/dist/ui/overlay/impl/permission-overlay-v2.d.ts +36 -0
- package/dist/ui/overlay/impl/permission-overlay-v2.js +380 -0
- package/dist/ui/overlay/impl/projects-overlay-v2.d.ts +36 -0
- package/dist/ui/overlay/impl/projects-overlay-v2.js +499 -0
- package/dist/ui/overlay/impl/theme-overlay-v2.d.ts +42 -0
- package/dist/ui/overlay/impl/theme-overlay-v2.js +135 -0
- package/dist/ui/overlay/impl/tools-overlay-v2.d.ts +47 -0
- package/dist/ui/overlay/impl/tools-overlay-v2.js +218 -0
- package/dist/ui/overlay/impl/tutorial-overlay-v2.d.ts +31 -0
- package/dist/ui/overlay/impl/tutorial-overlay-v2.js +1035 -0
- package/dist/ui/overlay/impl/workflow-overlay-v2.d.ts +80 -0
- package/dist/ui/overlay/impl/workflow-overlay-v2.js +637 -0
- package/dist/ui/overlay/index.d.ts +33 -0
- package/dist/ui/overlay/index.js +35 -0
- package/dist/ui/overlay/key-utils.d.ts +6 -0
- package/dist/ui/overlay/key-utils.js +6 -0
- package/dist/ui/overlay/overlay-types.d.ts +128 -0
- package/dist/ui/overlay/overlay-types.js +22 -0
- package/dist/ui/overlay/types.d.ts +135 -0
- package/dist/ui/overlay/types.js +22 -0
- package/dist/ui/overlays/help-overlay-v2.d.ts +28 -0
- package/dist/ui/overlays/help-overlay-v2.js +198 -0
- package/dist/ui/overlays/index.d.ts +11 -0
- package/dist/ui/overlays/index.js +11 -0
- package/dist/ui/overlays.d.ts +0 -4
- package/dist/ui/overlays.js +0 -444
- package/dist/ui/permission-overlay-v2.d.ts +36 -0
- package/dist/ui/permission-overlay-v2.js +380 -0
- package/dist/ui/permission-overlay.d.ts +1 -1
- package/dist/ui/permission-overlay.js +186 -298
- package/dist/ui/projects-overlay.d.ts +19 -0
- package/dist/ui/projects-overlay.js +484 -0
- package/dist/ui/providers/types.d.ts +178 -0
- package/dist/ui/providers/types.js +9 -0
- package/dist/ui/render-modes.d.ts +36 -0
- package/dist/ui/render-modes.js +44 -0
- package/dist/ui/startup-menu.d.ts +36 -0
- package/dist/ui/startup-menu.js +236 -0
- package/dist/ui/subagent-renderer.d.ts +117 -0
- package/dist/ui/subagent-renderer.js +334 -0
- package/dist/ui/terminal-codes.d.ts +94 -0
- package/dist/ui/terminal-codes.js +124 -0
- package/dist/ui/terminal-renderer.d.ts +221 -0
- package/dist/ui/terminal-renderer.js +751 -0
- package/dist/ui/terminal-ui.d.ts +463 -0
- package/dist/ui/terminal-ui.js +2296 -0
- package/dist/ui/terminal.d.ts +20 -0
- package/dist/ui/terminal.js +72 -0
- package/dist/ui/theme-overlay-v2.d.ts +42 -0
- package/dist/ui/theme-overlay-v2.js +135 -0
- package/dist/ui/theme-overlay.d.ts +24 -0
- package/dist/ui/theme-overlay.js +127 -0
- package/dist/ui/todo-zone.js +53 -25
- package/dist/ui/tool-formatters.d.ts +16 -0
- package/dist/ui/tool-formatters.js +516 -0
- package/dist/ui/tools-overlay-v2.d.ts +47 -0
- package/dist/ui/tools-overlay-v2.js +218 -0
- package/dist/ui/tools-overlay.d.ts +10 -2
- package/dist/ui/tools-overlay.js +172 -220
- package/dist/ui/tutorial-overlay-v2.d.ts +31 -0
- package/dist/ui/tutorial-overlay-v2.js +1035 -0
- package/dist/ui/tutorial-overlay.d.ts +1 -0
- package/dist/ui/tutorial-overlay.js +400 -302
- package/dist/ui/workflow-overlay.d.ts +22 -0
- package/dist/ui/workflow-overlay.js +636 -0
- package/dist/utils/debug-log.d.ts +28 -0
- package/dist/utils/debug-log.js +57 -0
- package/dist/utils/model-tiers.js +1 -1
- package/dist/utils/path-safety.d.ts +56 -0
- package/dist/utils/path-safety.js +239 -0
- package/dist/workflow/guided-mode-injector.d.ts +42 -0
- package/dist/workflow/guided-mode-injector.js +191 -0
- package/dist/workflow/index.d.ts +8 -0
- package/dist/workflow/index.js +8 -0
- package/dist/workflow/step-criteria.d.ts +62 -0
- package/dist/workflow/step-criteria.js +150 -0
- package/dist/workflow/step-tracker.d.ts +92 -0
- package/dist/workflow/step-tracker.js +141 -0
- package/package.json +12 -5
|
@@ -0,0 +1,814 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project Commands for REPL V2
|
|
3
|
+
*
|
|
4
|
+
* Commands for project management: init, backlog, workflow, anchors, design, sketch, refine
|
|
5
|
+
*/
|
|
6
|
+
import { executeCommand } from '../registry.js';
|
|
7
|
+
import { BacklogOverlayV2, WorkflowOverlayV2, DocsOverlayV2, DocumentDetailOverlayV2, AnchorsOverlayV2, ProjectsOverlayV2, NewProjectOverlayV2, InitSetupOverlayV2, ArchTypeOverlayV2, ModelWarningOverlayV2 } from '../../ui/overlay/index.js';
|
|
8
|
+
import { projectRepository, workItemRepository } from '../../db/repositories/index.js';
|
|
9
|
+
import { setCurrentProject, getCurrentProject } from '../../tools/project-db.js';
|
|
10
|
+
import { getSkillPrompt } from '../../repl-helpers.js';
|
|
11
|
+
import { getModelTier, modelMeetsTier } from '../../utils/model-tiers.js';
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// Helper Functions
|
|
14
|
+
// =============================================================================
|
|
15
|
+
/**
|
|
16
|
+
* Sync the footer project name with the current project.
|
|
17
|
+
* Call after any overlay that might change the current project.
|
|
18
|
+
*/
|
|
19
|
+
function syncFooterWithCurrentProject(ctx) {
|
|
20
|
+
const current = getCurrentProject();
|
|
21
|
+
ctx.ui.setProjectName(current?.displayName ?? null);
|
|
22
|
+
}
|
|
23
|
+
// =============================================================================
|
|
24
|
+
// New Command
|
|
25
|
+
// =============================================================================
|
|
26
|
+
export const newCommand = {
|
|
27
|
+
name: 'new',
|
|
28
|
+
description: 'Create a new project',
|
|
29
|
+
async execute(_args, ctx) {
|
|
30
|
+
const newProjectOverlay = new NewProjectOverlayV2();
|
|
31
|
+
const result = await ctx.ui.showOverlay(newProjectOverlay);
|
|
32
|
+
// User cancelled
|
|
33
|
+
if (!result?.created) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
// Project was created - show success messages
|
|
37
|
+
ctx.ui.print({ type: 'success', message: `Project created: ${result.projectPath ?? ''}` });
|
|
38
|
+
if (result.docsPath) {
|
|
39
|
+
ctx.ui.print({ type: 'success', message: `Docs repo created: ${result.docsPath}` });
|
|
40
|
+
}
|
|
41
|
+
// Register project in database if tracking is enabled
|
|
42
|
+
if (result.trackInDatabase && result.projectName && result.projectPath) {
|
|
43
|
+
try {
|
|
44
|
+
const project = projectRepository.create({
|
|
45
|
+
name: result.projectName,
|
|
46
|
+
display_name: result.projectName.replace(/-/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase()),
|
|
47
|
+
description: result.description,
|
|
48
|
+
path: result.projectPath,
|
|
49
|
+
type: 'general',
|
|
50
|
+
workflow_mode: result.workflowMode ?? 'flexible',
|
|
51
|
+
});
|
|
52
|
+
setCurrentProject({ id: project.id, name: project.name, displayName: project.displayName, path: project.path });
|
|
53
|
+
ctx.ui.setProjectName(project.displayName);
|
|
54
|
+
ctx.ui.print({ type: 'success', message: `Project tracked in database (${result.workflowMode ?? 'flexible'} mode)` });
|
|
55
|
+
ctx.ui.print({ type: 'success', message: `"${project.displayName}" is now the current project` });
|
|
56
|
+
}
|
|
57
|
+
catch (dbError) {
|
|
58
|
+
ctx.ui.print({ type: 'warning', message: `Could not register in database: ${dbError.message}` });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Show next steps
|
|
62
|
+
ctx.ui.print({ type: 'info', message: '' });
|
|
63
|
+
ctx.ui.print({ type: 'info', message: 'Next steps:' });
|
|
64
|
+
ctx.ui.print({ type: 'info', message: ` cd ${result.projectPath?.split('/').pop() ?? 'project'}` });
|
|
65
|
+
ctx.ui.print({ type: 'info', message: ' npm install' });
|
|
66
|
+
ctx.ui.print({ type: 'info', message: ' npm run dev' });
|
|
67
|
+
ctx.ui.print({ type: 'info', message: '' });
|
|
68
|
+
// Hint for agent interaction
|
|
69
|
+
const compilrMdPath = result.docsPath
|
|
70
|
+
? `${result.docsPath}/COMPILR.md`
|
|
71
|
+
: `${result.projectPath ?? '.'}/COMPILR.md`;
|
|
72
|
+
ctx.ui.print({ type: 'info', message: `Tip: Ask the agent to read ${compilrMdPath} to get started!` });
|
|
73
|
+
ctx.ui.print({ type: 'info', message: 'When ready to define requirements, type /design' });
|
|
74
|
+
return true;
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
// =============================================================================
|
|
78
|
+
// Init Command (Setup Status Placeholder)
|
|
79
|
+
// =============================================================================
|
|
80
|
+
export const initCommand = {
|
|
81
|
+
name: 'init',
|
|
82
|
+
description: 'View CLI setup status',
|
|
83
|
+
async execute(_args, ctx) {
|
|
84
|
+
const initSetupOverlay = new InitSetupOverlayV2();
|
|
85
|
+
await ctx.ui.showOverlay(initSetupOverlay);
|
|
86
|
+
return true;
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
// =============================================================================
|
|
90
|
+
// Backlog Command
|
|
91
|
+
// =============================================================================
|
|
92
|
+
export const backlogCommand = {
|
|
93
|
+
name: 'backlog',
|
|
94
|
+
description: 'View and manage project backlog',
|
|
95
|
+
async execute(_args, ctx) {
|
|
96
|
+
const backlogOverlay = new BacklogOverlayV2();
|
|
97
|
+
const result = await ctx.ui.showOverlay(backlogOverlay);
|
|
98
|
+
if (result?.modified) {
|
|
99
|
+
ctx.ui.print({ type: 'success', message: 'Backlog updated.' });
|
|
100
|
+
}
|
|
101
|
+
return true;
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
// =============================================================================
|
|
105
|
+
// Workflow Command
|
|
106
|
+
// =============================================================================
|
|
107
|
+
export const workflowCommand = {
|
|
108
|
+
name: 'workflow',
|
|
109
|
+
description: 'View project workflow dashboard',
|
|
110
|
+
async execute(_args, ctx) {
|
|
111
|
+
const workflowOverlay = new WorkflowOverlayV2();
|
|
112
|
+
const result = await ctx.ui.showOverlay(workflowOverlay);
|
|
113
|
+
// Handle workflow result - execute command if returned
|
|
114
|
+
if (result?.command) {
|
|
115
|
+
// Strip leading slash and execute the command
|
|
116
|
+
const cmd = result.command.replace(/^\//, '');
|
|
117
|
+
await executeCommand(cmd, '', ctx);
|
|
118
|
+
}
|
|
119
|
+
// Sync footer with current project (may have changed during overlay)
|
|
120
|
+
syncFooterWithCurrentProject(ctx);
|
|
121
|
+
return true;
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
// =============================================================================
|
|
125
|
+
// Anchors Command
|
|
126
|
+
// =============================================================================
|
|
127
|
+
export const anchorsCommand = {
|
|
128
|
+
name: 'anchors',
|
|
129
|
+
description: 'View and manage anchors (persistent context)',
|
|
130
|
+
async execute(_args, ctx) {
|
|
131
|
+
const anchorsOverlay = new AnchorsOverlayV2();
|
|
132
|
+
const result = await ctx.ui.showOverlay(anchorsOverlay);
|
|
133
|
+
if (result?.modified) {
|
|
134
|
+
ctx.ui.print({ type: 'success', message: 'Anchors updated.' });
|
|
135
|
+
}
|
|
136
|
+
return true;
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
// =============================================================================
|
|
140
|
+
// Design Command
|
|
141
|
+
// =============================================================================
|
|
142
|
+
export const designCommand = {
|
|
143
|
+
name: 'design',
|
|
144
|
+
description: 'Agent-driven requirements gathering',
|
|
145
|
+
async execute(_args, ctx) {
|
|
146
|
+
// Check if a project is set
|
|
147
|
+
const currentProject = getCurrentProject();
|
|
148
|
+
if (!currentProject) {
|
|
149
|
+
ctx.ui.print({ type: 'error', message: 'No project selected. Run /new or /projects first.' });
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
// Check model tier - /design works best with large models
|
|
153
|
+
const currentModel = ctx.model ?? 'unknown';
|
|
154
|
+
if (!modelMeetsTier(currentModel, '/design')) {
|
|
155
|
+
const modelTier = getModelTier(currentModel);
|
|
156
|
+
const warningOverlay = new ModelWarningOverlayV2({
|
|
157
|
+
command: '/design',
|
|
158
|
+
currentModel,
|
|
159
|
+
currentTier: modelTier.tier,
|
|
160
|
+
suggestedModel: modelTier.suggestedUpgrade,
|
|
161
|
+
alternativeCommand: '/sketch',
|
|
162
|
+
});
|
|
163
|
+
const choice = await ctx.ui.showOverlay(warningOverlay);
|
|
164
|
+
switch (choice) {
|
|
165
|
+
case 'cancel':
|
|
166
|
+
return true;
|
|
167
|
+
case 'alternative':
|
|
168
|
+
// Run /sketch instead
|
|
169
|
+
await executeCommand('sketch', '', ctx);
|
|
170
|
+
return true;
|
|
171
|
+
case 'switch':
|
|
172
|
+
// TODO: Hot-switch model when setModel is available in ctx
|
|
173
|
+
ctx.ui.print({ type: 'info', message: `Continuing with ${currentModel} (model switching not yet available in V2)` });
|
|
174
|
+
break;
|
|
175
|
+
case 'continue':
|
|
176
|
+
// Proceed with current model
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// Get design skill prompt
|
|
181
|
+
const designPrompt = getSkillPrompt('design');
|
|
182
|
+
if (!designPrompt) {
|
|
183
|
+
ctx.ui.print({ type: 'error', message: 'Design skill not found.' });
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
186
|
+
// Build full message for agent with project context
|
|
187
|
+
const fullMessage = `I want to design my project and create the backlog.
|
|
188
|
+
|
|
189
|
+
## PROJECT CONTEXT (IMPORTANT)
|
|
190
|
+
- Project Name: ${currentProject.name} (ID: ${String(currentProject.id)})
|
|
191
|
+
- This is a NEW project being designed from scratch
|
|
192
|
+
- Do NOT scan the filesystem - the current directory is NOT the project
|
|
193
|
+
- Do NOT use detect_project, glob, read_file, or ls tools
|
|
194
|
+
- Focus ONLY on gathering requirements via ask_user questions
|
|
195
|
+
|
|
196
|
+
## DOCUMENT STORAGE (CRITICAL)
|
|
197
|
+
Save all documents and backlog items using the database - do NOT write files directly.
|
|
198
|
+
- For backlog items: \`workitem_add({ type: "feature", title: "...", description: "...", priority: "high" })\`
|
|
199
|
+
- For documents: \`project_document_add({ doc_type: "prd", title: "...", content: "..." })\`
|
|
200
|
+
- The database is the source of truth for all project documents
|
|
201
|
+
- Do NOT use write_file or edit tools for documentation
|
|
202
|
+
|
|
203
|
+
${designPrompt}
|
|
204
|
+
|
|
205
|
+
Please start by using todo_write to track the design phases, then begin with Phase 1: Vision. Use the ask_user tool to gather information efficiently.`;
|
|
206
|
+
// Queue message for agent
|
|
207
|
+
ctx.queueAgentMessage({
|
|
208
|
+
message: fullMessage,
|
|
209
|
+
displayMessage: 'Start the design process for my project.',
|
|
210
|
+
});
|
|
211
|
+
return true;
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
// =============================================================================
|
|
215
|
+
// Sketch Command
|
|
216
|
+
// =============================================================================
|
|
217
|
+
export const sketchCommand = {
|
|
218
|
+
name: 'sketch',
|
|
219
|
+
description: 'Quick 6-question project outline',
|
|
220
|
+
execute(_args, ctx) {
|
|
221
|
+
// Check if a project is set
|
|
222
|
+
const currentProject = getCurrentProject();
|
|
223
|
+
if (!currentProject) {
|
|
224
|
+
ctx.ui.print({ type: 'error', message: 'No project selected. Run /new or /projects first.' });
|
|
225
|
+
return Promise.resolve(true);
|
|
226
|
+
}
|
|
227
|
+
// Get sketch skill prompt
|
|
228
|
+
const sketchPrompt = getSkillPrompt('sketch');
|
|
229
|
+
if (!sketchPrompt) {
|
|
230
|
+
ctx.ui.print({ type: 'error', message: 'Sketch skill not found.' });
|
|
231
|
+
return Promise.resolve(true);
|
|
232
|
+
}
|
|
233
|
+
// Build full message for agent with project context
|
|
234
|
+
const fullMessage = `I want to quickly outline my project.
|
|
235
|
+
|
|
236
|
+
## PROJECT CONTEXT (IMPORTANT)
|
|
237
|
+
- Project Name: ${currentProject.name} (ID: ${String(currentProject.id)})
|
|
238
|
+
- This is a NEW project being designed from scratch
|
|
239
|
+
- Do NOT scan the filesystem - the current directory is NOT the project
|
|
240
|
+
- Do NOT use detect_project, glob, read_file, or ls tools
|
|
241
|
+
- Focus ONLY on gathering requirements via ask_user questions
|
|
242
|
+
|
|
243
|
+
## DOCUMENT STORAGE (CRITICAL)
|
|
244
|
+
Save all documents and backlog items using the database - do NOT write files directly.
|
|
245
|
+
- For backlog items: \`workitem_add({ type: "feature", title: "...", description: "..." })\`
|
|
246
|
+
- For documents: \`project_document_add({ doc_type: "prd", title: "...", content: "..." })\`
|
|
247
|
+
- Do NOT use write_file or edit tools for documentation
|
|
248
|
+
|
|
249
|
+
${sketchPrompt}
|
|
250
|
+
|
|
251
|
+
Please start by asking me about the type of application I'm building using the ask_user_simple tool.`;
|
|
252
|
+
// Queue message for agent
|
|
253
|
+
ctx.queueAgentMessage({
|
|
254
|
+
message: fullMessage,
|
|
255
|
+
displayMessage: 'Quick project outline.',
|
|
256
|
+
});
|
|
257
|
+
return Promise.resolve(true);
|
|
258
|
+
},
|
|
259
|
+
};
|
|
260
|
+
// =============================================================================
|
|
261
|
+
// Refine Command
|
|
262
|
+
// =============================================================================
|
|
263
|
+
export const refineCommand = {
|
|
264
|
+
name: 'refine',
|
|
265
|
+
description: 'Iterative refinement of requirements',
|
|
266
|
+
async execute(args, ctx) {
|
|
267
|
+
// Check if a project is set
|
|
268
|
+
const currentProject = getCurrentProject();
|
|
269
|
+
if (!currentProject) {
|
|
270
|
+
ctx.ui.print({ type: 'error', message: 'No project selected. Run /new or /projects first.' });
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
// Check if project has work items in database
|
|
274
|
+
const counts = workItemRepository.getStatusCounts(currentProject.id);
|
|
275
|
+
const totalItems = counts.backlog + counts.in_progress + counts.completed + counts.skipped;
|
|
276
|
+
if (totalItems === 0) {
|
|
277
|
+
ctx.ui.print({ type: 'error', message: 'No backlog items found. Run /design first to create initial requirements.' });
|
|
278
|
+
return true;
|
|
279
|
+
}
|
|
280
|
+
// Check if a specific item ID was provided (e.g., /refine REQ-001)
|
|
281
|
+
const itemId = args.trim().toUpperCase();
|
|
282
|
+
const isFocusedRefine = itemId && /^[A-Z]+-\d{3}$/.test(itemId);
|
|
283
|
+
// For full refine mode (no item ID), check model tier and warn
|
|
284
|
+
if (!isFocusedRefine) {
|
|
285
|
+
const currentModel = ctx.model ?? 'unknown';
|
|
286
|
+
if (!modelMeetsTier(currentModel, '/refine')) {
|
|
287
|
+
const modelTier = getModelTier(currentModel);
|
|
288
|
+
const warningOverlay = new ModelWarningOverlayV2({
|
|
289
|
+
command: '/refine',
|
|
290
|
+
currentModel,
|
|
291
|
+
currentTier: modelTier.tier,
|
|
292
|
+
suggestedModel: modelTier.suggestedUpgrade,
|
|
293
|
+
alternativeCommand: '/refine <ITEM-ID>',
|
|
294
|
+
});
|
|
295
|
+
const choice = await ctx.ui.showOverlay(warningOverlay);
|
|
296
|
+
switch (choice) {
|
|
297
|
+
case 'cancel':
|
|
298
|
+
return true;
|
|
299
|
+
case 'alternative':
|
|
300
|
+
ctx.ui.print({ type: 'info', message: 'Tip: Use /refine <ITEM-ID> for focused refinement with smaller models.' });
|
|
301
|
+
ctx.ui.print({ type: 'info', message: ' Example: /refine REQ-001' });
|
|
302
|
+
return true;
|
|
303
|
+
case 'switch':
|
|
304
|
+
// TODO: Hot-switch model when setModel is available in ctx
|
|
305
|
+
ctx.ui.print({ type: 'info', message: `Continuing with ${currentModel} (model switching not yet available in V2)` });
|
|
306
|
+
break;
|
|
307
|
+
case 'continue':
|
|
308
|
+
break;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
// Get appropriate skill prompt
|
|
313
|
+
const skillName = isFocusedRefine ? 'refine-item' : 'refine';
|
|
314
|
+
const refinePrompt = getSkillPrompt(skillName);
|
|
315
|
+
if (!refinePrompt) {
|
|
316
|
+
ctx.ui.print({ type: 'error', message: `${skillName} skill not found.` });
|
|
317
|
+
return true;
|
|
318
|
+
}
|
|
319
|
+
// Build message based on mode
|
|
320
|
+
const userIntent = isFocusedRefine
|
|
321
|
+
? `I want to refine backlog item ${itemId}.`
|
|
322
|
+
: 'I want to refine my project requirements.';
|
|
323
|
+
const agentInstructions = isFocusedRefine
|
|
324
|
+
? `Please use workitem_query to find item "${itemId}", then guide me through refining it using workitem_update.`
|
|
325
|
+
: 'Please start by using workitem_query with limit:10 to get an overview, then ask me what I\'d like to focus on using ask_user_simple.';
|
|
326
|
+
const fullMessage = `${userIntent}
|
|
327
|
+
|
|
328
|
+
## PROJECT CONTEXT (IMPORTANT)
|
|
329
|
+
- Project Name: ${currentProject.name} (ID: ${String(currentProject.id)})
|
|
330
|
+
- Do NOT scan the filesystem - the current directory is NOT the project
|
|
331
|
+
- Do NOT use detect_project, glob, read_file, or ls tools
|
|
332
|
+
- Use ONLY database tools to access project data
|
|
333
|
+
|
|
334
|
+
## DOCUMENT STORAGE (CRITICAL)
|
|
335
|
+
Use database tools for all updates - do NOT write files directly.
|
|
336
|
+
- Use \`workitem_query\` to read items
|
|
337
|
+
- Use \`workitem_update\` to modify items
|
|
338
|
+
- Do NOT use write_file or edit tools
|
|
339
|
+
|
|
340
|
+
${refinePrompt}
|
|
341
|
+
|
|
342
|
+
${agentInstructions}`;
|
|
343
|
+
// Queue message for agent
|
|
344
|
+
ctx.queueAgentMessage({
|
|
345
|
+
message: fullMessage,
|
|
346
|
+
displayMessage: userIntent,
|
|
347
|
+
});
|
|
348
|
+
return true;
|
|
349
|
+
},
|
|
350
|
+
};
|
|
351
|
+
// =============================================================================
|
|
352
|
+
// Build Command
|
|
353
|
+
// =============================================================================
|
|
354
|
+
export const buildCommand = {
|
|
355
|
+
name: 'build',
|
|
356
|
+
description: 'Build a backlog item',
|
|
357
|
+
async execute(args, ctx) {
|
|
358
|
+
const argTrimmed = args.trim();
|
|
359
|
+
// Handle `/build scaffold` - redirect to scaffold command
|
|
360
|
+
if (argTrimmed.toLowerCase() === 'scaffold') {
|
|
361
|
+
await executeCommand('scaffold', '', ctx);
|
|
362
|
+
return true;
|
|
363
|
+
}
|
|
364
|
+
// Check if a project is set
|
|
365
|
+
const currentProject = getCurrentProject();
|
|
366
|
+
if (!currentProject) {
|
|
367
|
+
ctx.ui.print({ type: 'error', message: 'No project selected. Run /new or /projects first.' });
|
|
368
|
+
return true;
|
|
369
|
+
}
|
|
370
|
+
// Check if project has a path set (REQUIRED for building)
|
|
371
|
+
if (!currentProject.path) {
|
|
372
|
+
ctx.ui.print({ type: 'error', message: 'Project path not set. Cannot build without a target directory.' });
|
|
373
|
+
ctx.ui.print({ type: 'info', message: 'Tip: Update the project path in /projects to specify where files should be created.' });
|
|
374
|
+
return true;
|
|
375
|
+
}
|
|
376
|
+
// Warn if cwd doesn't match project path (common source of confusion)
|
|
377
|
+
const buildCwd = process.cwd();
|
|
378
|
+
if (buildCwd !== currentProject.path) {
|
|
379
|
+
ctx.ui.print({ type: 'warning', message: `Working directory differs from project path!` });
|
|
380
|
+
ctx.ui.print({ type: 'info', message: ` cwd: ${buildCwd}` });
|
|
381
|
+
ctx.ui.print({ type: 'info', message: ` project: ${currentProject.path}` });
|
|
382
|
+
ctx.ui.print({ type: 'info', message: `Files will be created/modified in the project path, not cwd.` });
|
|
383
|
+
}
|
|
384
|
+
// Parse item ID argument (e.g., "REQ-001")
|
|
385
|
+
const requestedItemId = argTrimmed.toUpperCase();
|
|
386
|
+
const isSpecificItem = requestedItemId && /^[A-Z]+-\d{3}$/.test(requestedItemId);
|
|
387
|
+
// Find the item to build
|
|
388
|
+
let selectedItem;
|
|
389
|
+
if (isSpecificItem) {
|
|
390
|
+
// Get specific item by ID
|
|
391
|
+
selectedItem = workItemRepository.getByItemId(currentProject.id, requestedItemId);
|
|
392
|
+
if (!selectedItem) {
|
|
393
|
+
ctx.ui.print({ type: 'error', message: `Work item "${requestedItemId}" not found.` });
|
|
394
|
+
return true;
|
|
395
|
+
}
|
|
396
|
+
if (selectedItem.status !== 'backlog') {
|
|
397
|
+
ctx.ui.print({ type: 'warning', message: `Work item "${requestedItemId}" is already ${selectedItem.status}. Use /backlog to view status.` });
|
|
398
|
+
return true;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
else {
|
|
402
|
+
// Auto-select highest priority backlog item
|
|
403
|
+
selectedItem = workItemRepository.getNext(currentProject.id);
|
|
404
|
+
if (!selectedItem) {
|
|
405
|
+
ctx.ui.print({ type: 'info', message: 'No backlog items found. Create items with /design or /backlog first.' });
|
|
406
|
+
ctx.ui.print({ type: 'info', message: 'Or run /build scaffold to create the project foundation.' });
|
|
407
|
+
return true;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
// Check model tier for full builds (not targeted item)
|
|
411
|
+
if (!isSpecificItem) {
|
|
412
|
+
const currentModel = ctx.model ?? 'unknown';
|
|
413
|
+
if (!modelMeetsTier(currentModel, '/build')) {
|
|
414
|
+
const modelTier = getModelTier(currentModel);
|
|
415
|
+
const warningOverlay = new ModelWarningOverlayV2({
|
|
416
|
+
command: '/build',
|
|
417
|
+
currentModel,
|
|
418
|
+
currentTier: modelTier.tier,
|
|
419
|
+
suggestedModel: modelTier.suggestedUpgrade,
|
|
420
|
+
alternativeCommand: `/build ${selectedItem.itemId}`,
|
|
421
|
+
});
|
|
422
|
+
const choice = await ctx.ui.showOverlay(warningOverlay);
|
|
423
|
+
switch (choice) {
|
|
424
|
+
case 'cancel':
|
|
425
|
+
return true;
|
|
426
|
+
case 'alternative':
|
|
427
|
+
ctx.ui.print({ type: 'info', message: `Tip: Use /build ${selectedItem.itemId} to build a specific item with smaller models.` });
|
|
428
|
+
return true;
|
|
429
|
+
case 'switch':
|
|
430
|
+
ctx.ui.print({ type: 'info', message: `Continuing with ${currentModel} (model switching not yet available in V2)` });
|
|
431
|
+
break;
|
|
432
|
+
case 'continue':
|
|
433
|
+
break;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
// Get build skill prompt and replace placeholders
|
|
438
|
+
let buildPrompt = getSkillPrompt('build');
|
|
439
|
+
if (!buildPrompt) {
|
|
440
|
+
ctx.ui.print({ type: 'error', message: 'Build skill not found.' });
|
|
441
|
+
return true;
|
|
442
|
+
}
|
|
443
|
+
// Replace {{projectPath}} and item placeholders with actual values
|
|
444
|
+
buildPrompt = buildPrompt
|
|
445
|
+
.replace(/\{\{projectPath\}\}/g, currentProject.path)
|
|
446
|
+
.replace(/\{\{item_id\}\}/g, selectedItem.itemId)
|
|
447
|
+
.replace(/\{\{item_title\}\}/g, selectedItem.title)
|
|
448
|
+
.replace(/\{\{item_type\}\}/g, selectedItem.type)
|
|
449
|
+
.replace(/\{\{item_priority\}\}/g, selectedItem.priority)
|
|
450
|
+
.replace(/\{\{item_description\}\}/g, selectedItem.description ?? 'No description provided');
|
|
451
|
+
// Build full message for agent with explicit project path context
|
|
452
|
+
const fullMessage = `I want to implement backlog item ${selectedItem.itemId}: "${selectedItem.title}".
|
|
453
|
+
|
|
454
|
+
## PROJECT CONTEXT (CRITICAL)
|
|
455
|
+
- Project Name: ${currentProject.name} (ID: ${String(currentProject.id)})
|
|
456
|
+
- **Project Directory: ${currentProject.path}**
|
|
457
|
+
- ALL files MUST be created/modified in this directory
|
|
458
|
+
|
|
459
|
+
## WORK ITEM DETAILS
|
|
460
|
+
- Item ID: ${selectedItem.itemId}
|
|
461
|
+
- Type: ${selectedItem.type}
|
|
462
|
+
- Priority: ${selectedItem.priority}
|
|
463
|
+
- Description: ${selectedItem.description ?? 'No description provided'}
|
|
464
|
+
|
|
465
|
+
## TOOL RESTRICTIONS (CRITICAL)
|
|
466
|
+
- Do NOT use detect_project or find_project_root
|
|
467
|
+
- Do NOT scan filesystem to detect project type
|
|
468
|
+
- The project path above is the ONLY source of truth for where to create/modify files
|
|
469
|
+
- Use \`project_document_get\` to read PRD and architecture docs from the database
|
|
470
|
+
- Use \`workitem_query\` to read related backlog items from the database
|
|
471
|
+
- Use \`workitem_update\` to update the item status when done
|
|
472
|
+
|
|
473
|
+
## FILE OPERATIONS (CRITICAL)
|
|
474
|
+
When creating or modifying files:
|
|
475
|
+
- Use absolute paths starting with: ${currentProject.path}/
|
|
476
|
+
- Example: write_file({ path: "${currentProject.path}/src/index.ts", ... })
|
|
477
|
+
- NEVER use relative paths
|
|
478
|
+
- IGNORE the current working directory (cwd) - it may be different from the project!
|
|
479
|
+
- The user may have started the CLI from a different folder
|
|
480
|
+
|
|
481
|
+
${buildPrompt}
|
|
482
|
+
|
|
483
|
+
Please start by:
|
|
484
|
+
1. Using todo_write to plan the implementation steps
|
|
485
|
+
2. Reading project documents from the database (project_document_list, project_document_get)
|
|
486
|
+
3. Updating the work item status to 'in_progress' using workitem_update
|
|
487
|
+
4. Implementing the feature
|
|
488
|
+
5. Updating the work item status to 'completed' when done`;
|
|
489
|
+
// Queue message for agent
|
|
490
|
+
ctx.queueAgentMessage({
|
|
491
|
+
message: fullMessage,
|
|
492
|
+
displayMessage: `Build ${selectedItem.itemId}: ${selectedItem.title}`,
|
|
493
|
+
});
|
|
494
|
+
return true;
|
|
495
|
+
},
|
|
496
|
+
};
|
|
497
|
+
// =============================================================================
|
|
498
|
+
// Note Command
|
|
499
|
+
// =============================================================================
|
|
500
|
+
export const noteCommand = {
|
|
501
|
+
name: 'note',
|
|
502
|
+
description: 'Create a session note',
|
|
503
|
+
execute(args, ctx) {
|
|
504
|
+
// Check if a project is set
|
|
505
|
+
const currentProject = getCurrentProject();
|
|
506
|
+
if (!currentProject) {
|
|
507
|
+
ctx.ui.print({ type: 'error', message: 'No project selected. Run /new or /projects first.' });
|
|
508
|
+
return Promise.resolve(true);
|
|
509
|
+
}
|
|
510
|
+
// Get session-notes skill prompt
|
|
511
|
+
const notePrompt = getSkillPrompt('session-notes');
|
|
512
|
+
if (!notePrompt) {
|
|
513
|
+
ctx.ui.print({ type: 'error', message: 'Session-notes skill not found.' });
|
|
514
|
+
return Promise.resolve(true);
|
|
515
|
+
}
|
|
516
|
+
// Check for optional title argument
|
|
517
|
+
const noteTitle = args.trim();
|
|
518
|
+
// Build title instruction based on whether title was provided
|
|
519
|
+
const titleInstruction = noteTitle
|
|
520
|
+
? `The session title is: "${noteTitle}"`
|
|
521
|
+
: 'Please ask me for a title using ask_user_simple, or generate one from the session summary.';
|
|
522
|
+
// Build full message for agent
|
|
523
|
+
const fullMessage = `I want to create a session note capturing what we've done.
|
|
524
|
+
|
|
525
|
+
## PROJECT CONTEXT
|
|
526
|
+
- Project Name: ${currentProject.name} (ID: ${String(currentProject.id)})
|
|
527
|
+
|
|
528
|
+
## DOCUMENT STORAGE (CRITICAL)
|
|
529
|
+
Save session notes using the database - do NOT write files directly.
|
|
530
|
+
- Tool: \`project_document_add({ doc_type: "session-note", title: "...", content: "..." })\`
|
|
531
|
+
- The database is the source of truth for all project documents
|
|
532
|
+
- Do NOT use write_file or edit tools for documentation
|
|
533
|
+
|
|
534
|
+
${notePrompt}
|
|
535
|
+
|
|
536
|
+
${titleInstruction}
|
|
537
|
+
|
|
538
|
+
Review the conversation context to understand what was accomplished, then create the session note.`;
|
|
539
|
+
// Queue message for agent
|
|
540
|
+
ctx.queueAgentMessage({
|
|
541
|
+
message: fullMessage,
|
|
542
|
+
displayMessage: noteTitle
|
|
543
|
+
? `Create session note: "${noteTitle}"`
|
|
544
|
+
: 'Create a session note for this session.',
|
|
545
|
+
});
|
|
546
|
+
return Promise.resolve(true);
|
|
547
|
+
},
|
|
548
|
+
};
|
|
549
|
+
// =============================================================================
|
|
550
|
+
// PRD Command
|
|
551
|
+
// =============================================================================
|
|
552
|
+
export const prdCommand = {
|
|
553
|
+
name: 'prd',
|
|
554
|
+
description: 'Update the Product Requirements Document',
|
|
555
|
+
execute(args, ctx) {
|
|
556
|
+
// Check if a project is set
|
|
557
|
+
const currentProject = getCurrentProject();
|
|
558
|
+
if (!currentProject) {
|
|
559
|
+
ctx.ui.print({ type: 'error', message: 'No project selected. Run /new or /projects first.' });
|
|
560
|
+
return Promise.resolve(true);
|
|
561
|
+
}
|
|
562
|
+
// Get PRD skill prompt
|
|
563
|
+
const prdPrompt = getSkillPrompt('prd');
|
|
564
|
+
if (!prdPrompt) {
|
|
565
|
+
ctx.ui.print({ type: 'error', message: 'PRD skill not found.' });
|
|
566
|
+
return Promise.resolve(true);
|
|
567
|
+
}
|
|
568
|
+
// Check for optional section argument
|
|
569
|
+
const section = args.trim().toLowerCase();
|
|
570
|
+
const validSections = ['vision', 'scope', 'technical', 'success'];
|
|
571
|
+
const sectionInstruction = validSections.includes(section)
|
|
572
|
+
? `The user wants to update the "${section}" section specifically.`
|
|
573
|
+
: 'Ask the user which section they want to update using ask_user_simple.';
|
|
574
|
+
// Build full message for agent with project context
|
|
575
|
+
const fullMessage = `I want to update the Product Requirements Document.
|
|
576
|
+
|
|
577
|
+
## DOCUMENT STORAGE (CRITICAL)
|
|
578
|
+
Save PRD updates using the database - do NOT write files directly.
|
|
579
|
+
- Project: ${currentProject.name} (ID: ${String(currentProject.id)})
|
|
580
|
+
- Tool: \`project_document_add({ doc_type: "prd", title: "Product Requirements Document", content: "..." })\`
|
|
581
|
+
- The database is the source of truth for all project documents
|
|
582
|
+
- Do NOT use write_file or edit tools for documentation
|
|
583
|
+
|
|
584
|
+
${prdPrompt}
|
|
585
|
+
|
|
586
|
+
${sectionInstruction}
|
|
587
|
+
|
|
588
|
+
Start by reading the existing PRD.md file to understand current state.`;
|
|
589
|
+
// Queue message for agent
|
|
590
|
+
ctx.queueAgentMessage({
|
|
591
|
+
message: fullMessage,
|
|
592
|
+
displayMessage: section
|
|
593
|
+
? `Update PRD: ${section} section`
|
|
594
|
+
: 'Update the Product Requirements Document',
|
|
595
|
+
});
|
|
596
|
+
return Promise.resolve(true);
|
|
597
|
+
},
|
|
598
|
+
};
|
|
599
|
+
// =============================================================================
|
|
600
|
+
// Scaffold Command
|
|
601
|
+
// =============================================================================
|
|
602
|
+
export const scaffoldCommand = {
|
|
603
|
+
name: 'scaffold',
|
|
604
|
+
description: 'Create project scaffold/foundation',
|
|
605
|
+
async execute(_args, ctx) {
|
|
606
|
+
// Check if a project is set
|
|
607
|
+
const currentProject = getCurrentProject();
|
|
608
|
+
if (!currentProject) {
|
|
609
|
+
ctx.ui.print({ type: 'error', message: 'No project selected. Run /new or /projects first.' });
|
|
610
|
+
return true;
|
|
611
|
+
}
|
|
612
|
+
// Check if project has a path set (REQUIRED for scaffolding)
|
|
613
|
+
if (!currentProject.path) {
|
|
614
|
+
ctx.ui.print({ type: 'error', message: 'Project path not set. Cannot scaffold without a target directory.' });
|
|
615
|
+
ctx.ui.print({ type: 'info', message: 'Tip: Update the project path in /projects to specify where files should be created.' });
|
|
616
|
+
return true;
|
|
617
|
+
}
|
|
618
|
+
// Warn if cwd doesn't match project path (common source of confusion)
|
|
619
|
+
const cwd = process.cwd();
|
|
620
|
+
if (cwd !== currentProject.path) {
|
|
621
|
+
ctx.ui.print({ type: 'warning', message: `Working directory differs from project path!` });
|
|
622
|
+
ctx.ui.print({ type: 'info', message: ` cwd: ${cwd}` });
|
|
623
|
+
ctx.ui.print({ type: 'info', message: ` project: ${currentProject.path}` });
|
|
624
|
+
ctx.ui.print({ type: 'info', message: `Files will be created in the project path, not cwd.` });
|
|
625
|
+
}
|
|
626
|
+
// Check model tier - /scaffold works best with large models
|
|
627
|
+
const currentModel = ctx.model ?? 'unknown';
|
|
628
|
+
if (!modelMeetsTier(currentModel, '/scaffold')) {
|
|
629
|
+
const modelTier = getModelTier(currentModel);
|
|
630
|
+
const warningOverlay = new ModelWarningOverlayV2({
|
|
631
|
+
command: '/scaffold',
|
|
632
|
+
currentModel,
|
|
633
|
+
currentTier: modelTier.tier,
|
|
634
|
+
suggestedModel: modelTier.suggestedUpgrade,
|
|
635
|
+
});
|
|
636
|
+
const choice = await ctx.ui.showOverlay(warningOverlay);
|
|
637
|
+
switch (choice) {
|
|
638
|
+
case 'cancel':
|
|
639
|
+
return true;
|
|
640
|
+
case 'switch':
|
|
641
|
+
ctx.ui.print({ type: 'info', message: `Continuing with ${currentModel} (model switching not yet available in V2)` });
|
|
642
|
+
break;
|
|
643
|
+
case 'continue':
|
|
644
|
+
// Proceed with current model
|
|
645
|
+
break;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
// Get scaffold skill prompt and replace path placeholder
|
|
649
|
+
let scaffoldPrompt = getSkillPrompt('scaffold');
|
|
650
|
+
if (!scaffoldPrompt) {
|
|
651
|
+
ctx.ui.print({ type: 'error', message: 'Scaffold skill not found.' });
|
|
652
|
+
return true;
|
|
653
|
+
}
|
|
654
|
+
// Replace {{projectPath}} placeholder with actual path
|
|
655
|
+
scaffoldPrompt = scaffoldPrompt.replace(/\{\{projectPath\}\}/g, currentProject.path);
|
|
656
|
+
// Build full message for agent with explicit project path context
|
|
657
|
+
const fullMessage = `I want to create the project scaffold/foundation.
|
|
658
|
+
|
|
659
|
+
## PROJECT CONTEXT (CRITICAL)
|
|
660
|
+
- Project Name: ${currentProject.name} (ID: ${String(currentProject.id)})
|
|
661
|
+
- **Project Directory: ${currentProject.path}**
|
|
662
|
+
- ALL files MUST be created in this directory
|
|
663
|
+
|
|
664
|
+
## TOOL RESTRICTIONS (CRITICAL)
|
|
665
|
+
- Do NOT use detect_project or find_project_root
|
|
666
|
+
- Do NOT scan filesystem to detect project type
|
|
667
|
+
- The project path above is the ONLY source of truth for where to create files
|
|
668
|
+
- Use \`project_document_get\` to read PRD and architecture docs from the database
|
|
669
|
+
- Use \`workitem_query\` to read backlog items from the database
|
|
670
|
+
|
|
671
|
+
## FILE CREATION (CRITICAL)
|
|
672
|
+
When creating files:
|
|
673
|
+
- Use absolute paths starting with: ${currentProject.path}/
|
|
674
|
+
- Example: write_file({ path: "${currentProject.path}/package.json", ... })
|
|
675
|
+
- NEVER use relative paths
|
|
676
|
+
- IGNORE the current working directory (cwd) - it may be different from the project!
|
|
677
|
+
- The user may have started the CLI from a different folder
|
|
678
|
+
|
|
679
|
+
${scaffoldPrompt}
|
|
680
|
+
|
|
681
|
+
Please start by reading the project documents from the database using project_document_list and project_document_get. Then create a plan with todo_write before generating files.`;
|
|
682
|
+
// Queue message for agent
|
|
683
|
+
ctx.queueAgentMessage({
|
|
684
|
+
message: fullMessage,
|
|
685
|
+
displayMessage: 'Create project scaffold.',
|
|
686
|
+
});
|
|
687
|
+
return true;
|
|
688
|
+
},
|
|
689
|
+
};
|
|
690
|
+
// =============================================================================
|
|
691
|
+
// Arch Command
|
|
692
|
+
// =============================================================================
|
|
693
|
+
export const archCommand = {
|
|
694
|
+
name: 'arch',
|
|
695
|
+
description: 'Create architecture documentation',
|
|
696
|
+
async execute(_args, ctx) {
|
|
697
|
+
// Check if a project is set (use database, not filesystem)
|
|
698
|
+
const currentProject = getCurrentProject();
|
|
699
|
+
if (!currentProject) {
|
|
700
|
+
ctx.ui.print({ type: 'error', message: 'No project selected. Run /new or /projects first.' });
|
|
701
|
+
return true;
|
|
702
|
+
}
|
|
703
|
+
// TODO: Check model tier and show warning if too small (like legacy)
|
|
704
|
+
// Show type selection overlay
|
|
705
|
+
const archOverlay = new ArchTypeOverlayV2();
|
|
706
|
+
const archChoice = await ctx.ui.showOverlay(archOverlay);
|
|
707
|
+
if (!archChoice) {
|
|
708
|
+
// User cancelled
|
|
709
|
+
return true;
|
|
710
|
+
}
|
|
711
|
+
// Get architecture skill prompt
|
|
712
|
+
const archPrompt = getSkillPrompt('architecture');
|
|
713
|
+
if (!archPrompt) {
|
|
714
|
+
ctx.ui.print({ type: 'error', message: 'Architecture skill not found.' });
|
|
715
|
+
return true;
|
|
716
|
+
}
|
|
717
|
+
// Build the document type description for display
|
|
718
|
+
const docTypeLabels = {
|
|
719
|
+
'adr': 'Architecture Decision Record',
|
|
720
|
+
'diagram': 'System Diagram',
|
|
721
|
+
'data-model': 'Data Model',
|
|
722
|
+
'api': 'API Design',
|
|
723
|
+
'custom': 'Custom Documentation',
|
|
724
|
+
};
|
|
725
|
+
const displayType = archChoice.customTopic
|
|
726
|
+
? `Custom: ${archChoice.customTopic}`
|
|
727
|
+
: docTypeLabels[archChoice.type];
|
|
728
|
+
// Replace placeholders in skill prompt
|
|
729
|
+
const finalPrompt = archPrompt
|
|
730
|
+
.replace('{{doc_type}}', archChoice.type)
|
|
731
|
+
.replace('{{#if custom_topic}}Custom Topic: {{custom_topic}}{{/if}}', archChoice.customTopic ? `Custom Topic: ${archChoice.customTopic}` : '');
|
|
732
|
+
// Build full message for agent with project context
|
|
733
|
+
const fullMessage = `I want to create architecture documentation.
|
|
734
|
+
|
|
735
|
+
## DOCUMENT STORAGE (CRITICAL)
|
|
736
|
+
Save architecture documentation using the database - do NOT write files directly.
|
|
737
|
+
- Project: ${currentProject.name} (ID: ${String(currentProject.id)})
|
|
738
|
+
- Tool: \`project_document_add({ doc_type: "architecture", title: "...", content: "..." })\`
|
|
739
|
+
- The database is the source of truth for all project documents
|
|
740
|
+
- Do NOT use write_file or edit tools for documentation
|
|
741
|
+
|
|
742
|
+
${finalPrompt}
|
|
743
|
+
|
|
744
|
+
Please start by using project_document_list to find any existing PRD, and workitem_query to understand the project backlog. Then use ask_user to gather the information needed for this ${archChoice.type} document.`;
|
|
745
|
+
// Queue message for agent
|
|
746
|
+
ctx.queueAgentMessage({
|
|
747
|
+
message: fullMessage,
|
|
748
|
+
displayMessage: `Create ${displayType} documentation.`,
|
|
749
|
+
});
|
|
750
|
+
return true;
|
|
751
|
+
},
|
|
752
|
+
};
|
|
753
|
+
// =============================================================================
|
|
754
|
+
// Docs Command
|
|
755
|
+
// =============================================================================
|
|
756
|
+
export const docsCommand = {
|
|
757
|
+
name: 'docs',
|
|
758
|
+
description: 'View project documents (PRD, architecture, design, notes)',
|
|
759
|
+
async execute(_args, ctx) {
|
|
760
|
+
// Loop: show list → detail → back to list (until user cancels list or Ctrl+C from detail)
|
|
761
|
+
let showList = true;
|
|
762
|
+
while (showList) {
|
|
763
|
+
// Show document list (inline overlay)
|
|
764
|
+
const docsOverlay = new DocsOverlayV2();
|
|
765
|
+
const listResult = await ctx.ui.showOverlay(docsOverlay);
|
|
766
|
+
// User cancelled the list (Esc/Ctrl+C) - exit
|
|
767
|
+
if (!listResult?.selectedDocument || listResult.cancelled) {
|
|
768
|
+
showList = false;
|
|
769
|
+
continue;
|
|
770
|
+
}
|
|
771
|
+
// Show selected document in fullscreen detail overlay
|
|
772
|
+
const detailOverlay = new DocumentDetailOverlayV2(listResult.selectedDocument);
|
|
773
|
+
const detailResult = await ctx.ui.showOverlay(detailOverlay);
|
|
774
|
+
// Ctrl+C from detail - exit completely
|
|
775
|
+
// Esc/q from detail (goBack=true) - loop back to show list again
|
|
776
|
+
showList = detailResult?.goBack === true;
|
|
777
|
+
}
|
|
778
|
+
return true;
|
|
779
|
+
},
|
|
780
|
+
};
|
|
781
|
+
// =============================================================================
|
|
782
|
+
// Projects Command
|
|
783
|
+
// =============================================================================
|
|
784
|
+
export const projectsCommand = {
|
|
785
|
+
name: 'projects',
|
|
786
|
+
description: 'View and manage all projects',
|
|
787
|
+
async execute(_args, ctx) {
|
|
788
|
+
const projectsOverlay = new ProjectsOverlayV2();
|
|
789
|
+
await ctx.ui.showOverlay(projectsOverlay);
|
|
790
|
+
// Sync footer with current project (may have changed during overlay)
|
|
791
|
+
syncFooterWithCurrentProject(ctx);
|
|
792
|
+
return true;
|
|
793
|
+
},
|
|
794
|
+
};
|
|
795
|
+
// =============================================================================
|
|
796
|
+
// Export All Project Commands
|
|
797
|
+
// =============================================================================
|
|
798
|
+
export const projectCommands = [
|
|
799
|
+
newCommand,
|
|
800
|
+
initCommand,
|
|
801
|
+
backlogCommand,
|
|
802
|
+
workflowCommand,
|
|
803
|
+
anchorsCommand,
|
|
804
|
+
designCommand,
|
|
805
|
+
sketchCommand,
|
|
806
|
+
refineCommand,
|
|
807
|
+
buildCommand,
|
|
808
|
+
noteCommand,
|
|
809
|
+
prdCommand,
|
|
810
|
+
scaffoldCommand,
|
|
811
|
+
archCommand,
|
|
812
|
+
docsCommand,
|
|
813
|
+
projectsCommand,
|
|
814
|
+
];
|