@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,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug Logger
|
|
3
|
+
*
|
|
4
|
+
* Writes timestamped logs to a file for debugging timing issues.
|
|
5
|
+
* Usage: import { debugLog } from './utils/debug-log.js';
|
|
6
|
+
* debugLog('event-name', 'description');
|
|
7
|
+
*
|
|
8
|
+
* For rendering debug: set DEBUG_RENDERING=1 environment variable
|
|
9
|
+
* Usage: DEBUG_RENDERING=1 compilr
|
|
10
|
+
* Then: tail -f /tmp/compilr-debug.log
|
|
11
|
+
*/
|
|
12
|
+
import fs from 'node:fs';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
import os from 'node:os';
|
|
15
|
+
const LOG_FILE = path.join(os.tmpdir(), 'compilr-debug.log');
|
|
16
|
+
const startTime = Date.now();
|
|
17
|
+
// Check if rendering debug is enabled via environment variable
|
|
18
|
+
export const DEBUG_RENDERING = process.env['DEBUG_RENDERING'] === '1';
|
|
19
|
+
/**
|
|
20
|
+
* Log a debug message with timestamp
|
|
21
|
+
*/
|
|
22
|
+
export function debugLog(event, details) {
|
|
23
|
+
const elapsed = Date.now() - startTime;
|
|
24
|
+
const timestamp = new Date().toISOString();
|
|
25
|
+
const line = `[${timestamp}] +${String(elapsed)}ms | ${event}${details ? ` | ${details}` : ''}\n`;
|
|
26
|
+
try {
|
|
27
|
+
fs.appendFileSync(LOG_FILE, line);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// Ignore errors
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Clear the log file
|
|
35
|
+
*/
|
|
36
|
+
export function clearDebugLog() {
|
|
37
|
+
try {
|
|
38
|
+
fs.writeFileSync(LOG_FILE, `=== Debug Log Started ${new Date().toISOString()} ===\n`);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// Ignore errors
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get the log file path
|
|
46
|
+
*/
|
|
47
|
+
export function getDebugLogPath() {
|
|
48
|
+
return LOG_FILE;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Log rendering-specific debug info (only if DEBUG_RENDERING=1)
|
|
52
|
+
*/
|
|
53
|
+
export function debugRender(component, details) {
|
|
54
|
+
if (!DEBUG_RENDERING)
|
|
55
|
+
return;
|
|
56
|
+
debugLog(`[RENDER:${component}]`, details);
|
|
57
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path Safety Utilities
|
|
3
|
+
*
|
|
4
|
+
* Safety validation for file operations, especially deletion.
|
|
5
|
+
* Prevents accidental deletion of system directories or unrelated folders.
|
|
6
|
+
*/
|
|
7
|
+
export interface DeleteValidation {
|
|
8
|
+
valid: boolean;
|
|
9
|
+
reason?: string;
|
|
10
|
+
warnings?: string[];
|
|
11
|
+
}
|
|
12
|
+
export interface CwdValidation {
|
|
13
|
+
matches: boolean;
|
|
14
|
+
projectPath: string;
|
|
15
|
+
cwd: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Validate a path is safe to delete
|
|
19
|
+
*
|
|
20
|
+
* @param projectPath - The path to validate for deletion
|
|
21
|
+
* @returns Validation result with valid flag, optional reason, and warnings
|
|
22
|
+
*/
|
|
23
|
+
export declare function validateDeletePath(projectPath: string): DeleteValidation;
|
|
24
|
+
/**
|
|
25
|
+
* Validate active project matches current working directory
|
|
26
|
+
*
|
|
27
|
+
* @param project - Project with path property
|
|
28
|
+
* @returns Validation result with matches flag and paths
|
|
29
|
+
*/
|
|
30
|
+
export declare function validateProjectCwd(project: {
|
|
31
|
+
path: string;
|
|
32
|
+
}): CwdValidation;
|
|
33
|
+
/**
|
|
34
|
+
* Check if CWD validation warning should be shown
|
|
35
|
+
*/
|
|
36
|
+
export declare function shouldWarnCwdMismatch(project: {
|
|
37
|
+
path: string;
|
|
38
|
+
}): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Format a CWD mismatch warning message
|
|
41
|
+
*/
|
|
42
|
+
export declare function formatCwdMismatchWarning(project: {
|
|
43
|
+
path: string;
|
|
44
|
+
}): string[];
|
|
45
|
+
/**
|
|
46
|
+
* Format delete validation result for display
|
|
47
|
+
*/
|
|
48
|
+
export declare function formatDeleteValidation(validation: DeleteValidation, projectPath: string): string[];
|
|
49
|
+
/**
|
|
50
|
+
* Check if a path is within the projects directory
|
|
51
|
+
*/
|
|
52
|
+
export declare function isWithinProjectsDir(targetPath: string): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Get a safe display path (truncated if too long)
|
|
55
|
+
*/
|
|
56
|
+
export declare function getSafeDisplayPath(targetPath: string, maxLength?: number): string;
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path Safety Utilities
|
|
3
|
+
*
|
|
4
|
+
* Safety validation for file operations, especially deletion.
|
|
5
|
+
* Prevents accidental deletion of system directories or unrelated folders.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import * as os from 'os';
|
|
10
|
+
import { getAllowedDeletePaths, isDeleteProtectionEnabled, isProjectMatchRequired } from '../settings/paths.js';
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// Dangerous Paths
|
|
13
|
+
// =============================================================================
|
|
14
|
+
/**
|
|
15
|
+
* Get list of dangerous system paths that should never be deleted
|
|
16
|
+
*/
|
|
17
|
+
function getDangerousPaths() {
|
|
18
|
+
const home = os.homedir();
|
|
19
|
+
return [
|
|
20
|
+
home, // Home directory itself
|
|
21
|
+
'/', // Root
|
|
22
|
+
'/usr',
|
|
23
|
+
'/bin',
|
|
24
|
+
'/sbin',
|
|
25
|
+
'/lib',
|
|
26
|
+
'/lib64',
|
|
27
|
+
'/opt',
|
|
28
|
+
'/etc',
|
|
29
|
+
'/var',
|
|
30
|
+
'/tmp',
|
|
31
|
+
'/dev',
|
|
32
|
+
'/proc',
|
|
33
|
+
'/sys',
|
|
34
|
+
'/boot',
|
|
35
|
+
'/root',
|
|
36
|
+
'/home', // Parent of all home directories
|
|
37
|
+
// macOS specific
|
|
38
|
+
'/System',
|
|
39
|
+
'/Library',
|
|
40
|
+
'/Applications',
|
|
41
|
+
'/Users',
|
|
42
|
+
'/Volumes',
|
|
43
|
+
'/private',
|
|
44
|
+
'/cores',
|
|
45
|
+
// Windows specific (when running under WSL or similar)
|
|
46
|
+
'/mnt/c',
|
|
47
|
+
'/mnt/c/Windows',
|
|
48
|
+
'/mnt/c/Program Files',
|
|
49
|
+
'/mnt/c/Program Files (x86)',
|
|
50
|
+
'/mnt/c/Users',
|
|
51
|
+
// Common temp directories
|
|
52
|
+
os.tmpdir(),
|
|
53
|
+
path.join(home, 'Desktop'),
|
|
54
|
+
path.join(home, 'Documents'),
|
|
55
|
+
path.join(home, 'Downloads'),
|
|
56
|
+
path.join(home, 'Pictures'),
|
|
57
|
+
path.join(home, 'Videos'),
|
|
58
|
+
path.join(home, 'Music'),
|
|
59
|
+
// CLI data directory should not be deleted via project delete
|
|
60
|
+
path.join(home, '.compilr-dev'),
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
// =============================================================================
|
|
64
|
+
// Validation Functions
|
|
65
|
+
// =============================================================================
|
|
66
|
+
/**
|
|
67
|
+
* Validate a path is safe to delete
|
|
68
|
+
*
|
|
69
|
+
* @param projectPath - The path to validate for deletion
|
|
70
|
+
* @returns Validation result with valid flag, optional reason, and warnings
|
|
71
|
+
*/
|
|
72
|
+
export function validateDeletePath(projectPath) {
|
|
73
|
+
const resolved = path.resolve(projectPath);
|
|
74
|
+
const warnings = [];
|
|
75
|
+
// 1. Path must be absolute (after resolve, it always is)
|
|
76
|
+
if (!path.isAbsolute(resolved)) {
|
|
77
|
+
return { valid: false, reason: 'Project path must be absolute' };
|
|
78
|
+
}
|
|
79
|
+
// 2. Check if path exists (OK to proceed if it doesn't - just skip file deletion)
|
|
80
|
+
if (!fs.existsSync(resolved)) {
|
|
81
|
+
return { valid: true, warnings: ['Path does not exist, skipping file deletion'] };
|
|
82
|
+
}
|
|
83
|
+
// 3. Prevent dangerous system paths
|
|
84
|
+
const dangerousPaths = getDangerousPaths();
|
|
85
|
+
for (const dangerous of dangerousPaths) {
|
|
86
|
+
const resolvedDangerous = path.resolve(dangerous);
|
|
87
|
+
if (resolved === resolvedDangerous) {
|
|
88
|
+
return {
|
|
89
|
+
valid: false,
|
|
90
|
+
reason: `Cannot delete system directory: ${resolved}`,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// 4. Check path is within allowed directories (if protection enabled)
|
|
95
|
+
if (isDeleteProtectionEnabled()) {
|
|
96
|
+
const allowedRoots = getAllowedDeletePaths();
|
|
97
|
+
const isWithinAllowed = allowedRoots.some((root) => {
|
|
98
|
+
const resolvedRoot = path.resolve(root);
|
|
99
|
+
return resolved.startsWith(resolvedRoot + path.sep) || resolved === resolvedRoot;
|
|
100
|
+
});
|
|
101
|
+
if (!isWithinAllowed) {
|
|
102
|
+
return {
|
|
103
|
+
valid: false,
|
|
104
|
+
reason: `Path is outside allowed directories. Configure allowedPaths in /config if needed.`,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// 5. Check for project markers (.compilr, .git, package.json)
|
|
109
|
+
const hasCompilrMarker = fs.existsSync(path.join(resolved, '.compilr'));
|
|
110
|
+
const hasGit = fs.existsSync(path.join(resolved, '.git'));
|
|
111
|
+
const hasPackageJson = fs.existsSync(path.join(resolved, 'package.json'));
|
|
112
|
+
const hasPyprojectToml = fs.existsSync(path.join(resolved, 'pyproject.toml'));
|
|
113
|
+
const hasCargoToml = fs.existsSync(path.join(resolved, 'Cargo.toml'));
|
|
114
|
+
const hasGoMod = fs.existsSync(path.join(resolved, 'go.mod'));
|
|
115
|
+
const hasProjectMarker = hasCompilrMarker || hasGit || hasPackageJson || hasPyprojectToml || hasCargoToml || hasGoMod;
|
|
116
|
+
if (!hasProjectMarker) {
|
|
117
|
+
warnings.push('Directory has no project markers (.compilr, .git, package.json, etc.)');
|
|
118
|
+
}
|
|
119
|
+
// 6. Warn if path seems too short (e.g., /home/user/a)
|
|
120
|
+
const pathParts = resolved.split(path.sep).filter(Boolean);
|
|
121
|
+
if (pathParts.length < 3) {
|
|
122
|
+
warnings.push('Path seems unusually short - double check this is correct');
|
|
123
|
+
}
|
|
124
|
+
// 7. Warn if path is very deep (might indicate system path)
|
|
125
|
+
if (pathParts.length > 15) {
|
|
126
|
+
warnings.push('Path is very deep - verify this is the correct project');
|
|
127
|
+
}
|
|
128
|
+
// 8. Check if path is a parent of current working directory
|
|
129
|
+
const cwd = process.cwd();
|
|
130
|
+
if (cwd.startsWith(resolved + path.sep) || cwd === resolved) {
|
|
131
|
+
warnings.push('This path contains or is your current working directory');
|
|
132
|
+
}
|
|
133
|
+
return { valid: true, warnings };
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Validate active project matches current working directory
|
|
137
|
+
*
|
|
138
|
+
* @param project - Project with path property
|
|
139
|
+
* @returns Validation result with matches flag and paths
|
|
140
|
+
*/
|
|
141
|
+
export function validateProjectCwd(project) {
|
|
142
|
+
const cwd = process.cwd();
|
|
143
|
+
const projectPath = path.resolve(project.path);
|
|
144
|
+
// CWD should be within or equal to project path
|
|
145
|
+
const matches = cwd === projectPath || cwd.startsWith(projectPath + path.sep);
|
|
146
|
+
return { matches, projectPath, cwd };
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Check if CWD validation warning should be shown
|
|
150
|
+
*/
|
|
151
|
+
export function shouldWarnCwdMismatch(project) {
|
|
152
|
+
if (!isProjectMatchRequired()) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
const { matches } = validateProjectCwd(project);
|
|
156
|
+
return !matches;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Format a CWD mismatch warning message
|
|
160
|
+
*/
|
|
161
|
+
export function formatCwdMismatchWarning(project) {
|
|
162
|
+
const { projectPath, cwd } = validateProjectCwd(project);
|
|
163
|
+
return [
|
|
164
|
+
"Current directory doesn't match active project",
|
|
165
|
+
` Active project: ${projectPath}`,
|
|
166
|
+
` Current dir: ${cwd}`,
|
|
167
|
+
` Consider: cd ${projectPath}`,
|
|
168
|
+
];
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Format delete validation result for display
|
|
172
|
+
*/
|
|
173
|
+
export function formatDeleteValidation(validation, projectPath) {
|
|
174
|
+
const lines = [];
|
|
175
|
+
if (validation.valid) {
|
|
176
|
+
lines.push('Path is within allowed directory');
|
|
177
|
+
// Check for project markers
|
|
178
|
+
if (fs.existsSync(path.join(projectPath, '.compilr'))) {
|
|
179
|
+
lines.push('Project has .compilr marker');
|
|
180
|
+
}
|
|
181
|
+
else if (fs.existsSync(path.join(projectPath, '.git'))) {
|
|
182
|
+
lines.push('Project has .git repository');
|
|
183
|
+
}
|
|
184
|
+
else if (fs.existsSync(path.join(projectPath, 'package.json'))) {
|
|
185
|
+
lines.push('Project has package.json');
|
|
186
|
+
}
|
|
187
|
+
if (validation.warnings && validation.warnings.length > 0) {
|
|
188
|
+
lines.push('');
|
|
189
|
+
lines.push('Warnings:');
|
|
190
|
+
for (const warning of validation.warnings) {
|
|
191
|
+
lines.push(` - ${warning}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
lines.push(`Error: ${validation.reason || 'Unknown error'}`);
|
|
197
|
+
lines.push('');
|
|
198
|
+
lines.push('Allowed directories:');
|
|
199
|
+
for (const allowed of getAllowedDeletePaths()) {
|
|
200
|
+
lines.push(` - ${allowed}`);
|
|
201
|
+
}
|
|
202
|
+
lines.push('');
|
|
203
|
+
lines.push('Options:');
|
|
204
|
+
lines.push(' 1. Move the project to an allowed directory');
|
|
205
|
+
lines.push(' 2. Add path to allowedPaths in /config');
|
|
206
|
+
lines.push(' 3. Delete files manually and remove from database only');
|
|
207
|
+
}
|
|
208
|
+
return lines;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Check if a path is within the projects directory
|
|
212
|
+
*/
|
|
213
|
+
export function isWithinProjectsDir(targetPath) {
|
|
214
|
+
const allowedPaths = getAllowedDeletePaths();
|
|
215
|
+
const resolved = path.resolve(targetPath);
|
|
216
|
+
return allowedPaths.some((allowed) => {
|
|
217
|
+
const resolvedAllowed = path.resolve(allowed);
|
|
218
|
+
return resolved.startsWith(resolvedAllowed + path.sep) || resolved === resolvedAllowed;
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Get a safe display path (truncated if too long)
|
|
223
|
+
*/
|
|
224
|
+
export function getSafeDisplayPath(targetPath, maxLength = 50) {
|
|
225
|
+
if (targetPath.length <= maxLength) {
|
|
226
|
+
return targetPath;
|
|
227
|
+
}
|
|
228
|
+
const parts = targetPath.split(path.sep);
|
|
229
|
+
if (parts.length <= 2) {
|
|
230
|
+
return targetPath.slice(0, maxLength - 3) + '...';
|
|
231
|
+
}
|
|
232
|
+
// Show first and last parts with ellipsis
|
|
233
|
+
const first = parts.slice(0, 2).join(path.sep);
|
|
234
|
+
const last = parts.slice(-2).join(path.sep);
|
|
235
|
+
if (first.length + last.length + 4 <= maxLength) {
|
|
236
|
+
return first + '/.../' + last;
|
|
237
|
+
}
|
|
238
|
+
return targetPath.slice(0, maxLength - 3) + '...';
|
|
239
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guided Mode System Prompt Injector
|
|
3
|
+
*
|
|
4
|
+
* Injects guided workflow context into the agent's system prompt.
|
|
5
|
+
* Two types of injection:
|
|
6
|
+
* - Static: General rules about guided mode behavior (added to base system prompt)
|
|
7
|
+
* - Dynamic: Current project/item/step state (injected per-session)
|
|
8
|
+
*/
|
|
9
|
+
import type { Project } from '../db/repositories/project-repository.js';
|
|
10
|
+
import type { WorkItem } from '../db/repositories/work-item-repository.js';
|
|
11
|
+
/**
|
|
12
|
+
* Static system prompt addition for guided mode.
|
|
13
|
+
* Added to base system prompt when a project uses guided mode.
|
|
14
|
+
*/
|
|
15
|
+
export declare const GUIDED_MODE_SYSTEM_PROMPT: string;
|
|
16
|
+
/**
|
|
17
|
+
* Options for generating dynamic context
|
|
18
|
+
*/
|
|
19
|
+
export interface DynamicContextOptions {
|
|
20
|
+
project: Project;
|
|
21
|
+
currentItem: WorkItem | null;
|
|
22
|
+
backlogCount: number;
|
|
23
|
+
inProgressCount: number;
|
|
24
|
+
completedCount: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Generate dynamic context injection for current workflow state.
|
|
28
|
+
* Injected on startup and when project/step changes.
|
|
29
|
+
*/
|
|
30
|
+
export declare function generateDynamicContext(options: DynamicContextOptions): string;
|
|
31
|
+
/**
|
|
32
|
+
* Generate a compact status line for footer display
|
|
33
|
+
*/
|
|
34
|
+
export declare function generateStatusLine(options: DynamicContextOptions): string;
|
|
35
|
+
/**
|
|
36
|
+
* Check if we should inject guided mode context
|
|
37
|
+
*/
|
|
38
|
+
export declare function shouldInjectGuidedContext(project: Project | null): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Combine static and dynamic prompts for full guided mode injection
|
|
41
|
+
*/
|
|
42
|
+
export declare function getFullGuidedPrompt(options: DynamicContextOptions): string;
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guided Mode System Prompt Injector
|
|
3
|
+
*
|
|
4
|
+
* Injects guided workflow context into the agent's system prompt.
|
|
5
|
+
* Two types of injection:
|
|
6
|
+
* - Static: General rules about guided mode behavior (added to base system prompt)
|
|
7
|
+
* - Dynamic: Current project/item/step state (injected per-session)
|
|
8
|
+
*/
|
|
9
|
+
import { STEP_ORDER, getStepCriteria, formatStepDisplay, getStepDescription } from './step-criteria.js';
|
|
10
|
+
/**
|
|
11
|
+
* Static system prompt addition for guided mode.
|
|
12
|
+
* Added to base system prompt when a project uses guided mode.
|
|
13
|
+
*/
|
|
14
|
+
export const GUIDED_MODE_SYSTEM_PROMPT = `
|
|
15
|
+
## Guided Workflow Mode
|
|
16
|
+
|
|
17
|
+
When a project uses **guided mode**, follow these rules:
|
|
18
|
+
|
|
19
|
+
1. **Work Item Focus**: Always work on the current work item unless the user explicitly requests otherwise
|
|
20
|
+
2. **Step Cycle**: Progress through steps in order: ${STEP_ORDER.join(' → ')}
|
|
21
|
+
3. **Step Transitions**: Use \`workitem_advance_step\` tool when the criteria for the current step are met
|
|
22
|
+
4. **Visibility**: Announce step transitions clearly in conversation so the user sees progress
|
|
23
|
+
5. **Flexibility**: The user can always interrupt - acknowledge and respect their requests
|
|
24
|
+
6. **Test Failures**: After 2 failed test attempts, ask the user how to proceed (skip, retry, switch item)
|
|
25
|
+
|
|
26
|
+
### Step Criteria
|
|
27
|
+
|
|
28
|
+
- **PLAN**: Requirements understood, approach designed, target files identified
|
|
29
|
+
- **IMPLEMENT**: Code written, no placeholder TODOs left, lint passes
|
|
30
|
+
- **TEST**: All tests pass (or user overrides after 2 failures)
|
|
31
|
+
- **COMMIT**: Changes committed with proper message, commit hash captured
|
|
32
|
+
- **REVIEW**: User confirms ready for next item
|
|
33
|
+
|
|
34
|
+
### Detour Handling
|
|
35
|
+
|
|
36
|
+
If the user wants to work on something else mid-cycle:
|
|
37
|
+
1. Acknowledge their request
|
|
38
|
+
2. Optionally suggest finishing the current item (gentle challenge)
|
|
39
|
+
3. If they insist, accommodate gracefully
|
|
40
|
+
4. Options: pause current item, switch to different item, or switch to flexible mode
|
|
41
|
+
`.trim();
|
|
42
|
+
/**
|
|
43
|
+
* Generate dynamic context injection for current workflow state.
|
|
44
|
+
* Injected on startup and when project/step changes.
|
|
45
|
+
*/
|
|
46
|
+
export function generateDynamicContext(options) {
|
|
47
|
+
const { project, currentItem, backlogCount, inProgressCount, completedCount } = options;
|
|
48
|
+
// Base project context
|
|
49
|
+
let context = `
|
|
50
|
+
## Current Workflow State
|
|
51
|
+
|
|
52
|
+
**Project:** ${project.displayName} (Mode: ${project.workflowMode})
|
|
53
|
+
**Lifecycle:** ${project.lifecycleState}
|
|
54
|
+
**Progress:** ${String(completedCount)} completed, ${String(inProgressCount)} in progress, ${String(backlogCount)} in backlog
|
|
55
|
+
`.trim();
|
|
56
|
+
// Add current item context if in guided mode with active item
|
|
57
|
+
if (project.workflowMode === 'guided' && currentItem) {
|
|
58
|
+
context += `
|
|
59
|
+
|
|
60
|
+
### Current Work Item
|
|
61
|
+
|
|
62
|
+
**Item:** ${currentItem.itemId} "${currentItem.title}"
|
|
63
|
+
**Type:** ${currentItem.type}
|
|
64
|
+
**Priority:** ${currentItem.priority}
|
|
65
|
+
**Status:** ${currentItem.status}
|
|
66
|
+
**Step:** ${currentItem.guidedStep ? formatStepDisplay(currentItem.guidedStep) : 'Not started'}
|
|
67
|
+
${currentItem.description ? `\n**Description:**\n${currentItem.description}` : ''}
|
|
68
|
+
|
|
69
|
+
### Instructions
|
|
70
|
+
|
|
71
|
+
${getStepInstructions(currentItem.guidedStep)}`;
|
|
72
|
+
}
|
|
73
|
+
else if (project.workflowMode === 'guided') {
|
|
74
|
+
context += `
|
|
75
|
+
|
|
76
|
+
### No Active Work Item
|
|
77
|
+
|
|
78
|
+
Use \`workitem_next\` to get the highest priority item from the backlog, or ask the user which item to work on.
|
|
79
|
+
Once an item is selected, set its status to 'in_progress' and begin the guided cycle.`;
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
// Flexible mode
|
|
83
|
+
context += `
|
|
84
|
+
|
|
85
|
+
### Flexible Mode
|
|
86
|
+
|
|
87
|
+
Work on tasks as requested by the user. Work items are tracked but the step cycle is not enforced.
|
|
88
|
+
You can still use \`workitem_advance_step\` if you want to track progress through steps.`;
|
|
89
|
+
}
|
|
90
|
+
return context;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get step-specific instructions for the agent
|
|
94
|
+
*/
|
|
95
|
+
function getStepInstructions(step) {
|
|
96
|
+
if (!step) {
|
|
97
|
+
return `No step active. Use \`workitem_advance_step\` to start at PLAN step.`;
|
|
98
|
+
}
|
|
99
|
+
const criteria = getStepCriteria(step);
|
|
100
|
+
const stepDesc = getStepDescription(step);
|
|
101
|
+
let instructions = `You are in **${step.toUpperCase()}** step: ${stepDesc}
|
|
102
|
+
|
|
103
|
+
**Exit Criteria:**
|
|
104
|
+
${criteria.exitCriteria.map((c) => `- ${c}`).join('\n')}
|
|
105
|
+
|
|
106
|
+
**When complete:** Use \`workitem_advance_step\` with a reason explaining why criteria are met.`;
|
|
107
|
+
// Add step-specific hints
|
|
108
|
+
switch (step) {
|
|
109
|
+
case 'plan':
|
|
110
|
+
instructions += `
|
|
111
|
+
|
|
112
|
+
**Actions:**
|
|
113
|
+
1. Read and understand the requirements
|
|
114
|
+
2. Design the approach (what files to create/modify)
|
|
115
|
+
3. Consider edge cases and potential issues
|
|
116
|
+
4. Document the plan in conversation`;
|
|
117
|
+
break;
|
|
118
|
+
case 'implement':
|
|
119
|
+
instructions += `
|
|
120
|
+
|
|
121
|
+
**Actions:**
|
|
122
|
+
1. Create/modify files according to the plan
|
|
123
|
+
2. Ensure code is complete (no TODOs unless intentional)
|
|
124
|
+
3. Run lint if available and fix any issues
|
|
125
|
+
4. Review your changes before advancing`;
|
|
126
|
+
break;
|
|
127
|
+
case 'test':
|
|
128
|
+
instructions += `
|
|
129
|
+
|
|
130
|
+
**Actions:**
|
|
131
|
+
1. Run the test suite
|
|
132
|
+
2. If tests fail, analyze and fix the issues
|
|
133
|
+
3. Re-run tests after fixes
|
|
134
|
+
4. After 2 failed attempts, ask user how to proceed
|
|
135
|
+
|
|
136
|
+
**Note:** Track failed attempts. After 2 failures, offer options:
|
|
137
|
+
- Try again (you'll fix the issue)
|
|
138
|
+
- Skip tests and continue to commit
|
|
139
|
+
- Switch to flexible mode for this item
|
|
140
|
+
- Work on a different item`;
|
|
141
|
+
break;
|
|
142
|
+
case 'commit':
|
|
143
|
+
instructions += `
|
|
144
|
+
|
|
145
|
+
**Actions:**
|
|
146
|
+
1. Stage the relevant changes
|
|
147
|
+
2. Create a descriptive commit message
|
|
148
|
+
3. Run git commit
|
|
149
|
+
4. Capture the commit hash
|
|
150
|
+
5. Use \`workitem_update\` to store the commit_hash on the item`;
|
|
151
|
+
break;
|
|
152
|
+
case 'review':
|
|
153
|
+
instructions += `
|
|
154
|
+
|
|
155
|
+
**Actions:**
|
|
156
|
+
1. Summarize what was accomplished
|
|
157
|
+
2. Ask user if they're ready for the next item
|
|
158
|
+
3. Wait for user confirmation before proceeding
|
|
159
|
+
|
|
160
|
+
**On user confirmation:**
|
|
161
|
+
- Use \`workitem_advance_step\` to complete this item
|
|
162
|
+
- Then use \`workitem_next\` to get the next item`;
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
return instructions;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Generate a compact status line for footer display
|
|
169
|
+
*/
|
|
170
|
+
export function generateStatusLine(options) {
|
|
171
|
+
const { project, currentItem } = options;
|
|
172
|
+
if (!currentItem) {
|
|
173
|
+
return `${project.displayName} | ${project.workflowMode} mode | No active item`;
|
|
174
|
+
}
|
|
175
|
+
const stepDisplay = currentItem.guidedStep
|
|
176
|
+
? currentItem.guidedStep.toUpperCase()
|
|
177
|
+
: 'READY';
|
|
178
|
+
return `${project.displayName} | ${currentItem.itemId} | ${stepDisplay}`;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Check if we should inject guided mode context
|
|
182
|
+
*/
|
|
183
|
+
export function shouldInjectGuidedContext(project) {
|
|
184
|
+
return project !== null && project.workflowMode === 'guided';
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Combine static and dynamic prompts for full guided mode injection
|
|
188
|
+
*/
|
|
189
|
+
export function getFullGuidedPrompt(options) {
|
|
190
|
+
return `${GUIDED_MODE_SYSTEM_PROMPT}\n\n${generateDynamicContext(options)}`;
|
|
191
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guided Workflow Module
|
|
3
|
+
*
|
|
4
|
+
* Provides step-by-step workflow tracking for guided mode.
|
|
5
|
+
*/
|
|
6
|
+
export { type StepCriteria, STEP_ORDER, GUIDED_STEP_CRITERIA, getNextStep, getPreviousStep, getStepNumber, isValidTransition, getStepCriteria, getStepDescription, formatStepDisplay, } from './step-criteria.js';
|
|
7
|
+
export { type StepAttempt, GuidedStepTracker, stepTracker, } from './step-tracker.js';
|
|
8
|
+
export { type DynamicContextOptions, GUIDED_MODE_SYSTEM_PROMPT, generateDynamicContext, generateStatusLine, shouldInjectGuidedContext, getFullGuidedPrompt, } from './guided-mode-injector.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guided Workflow Module
|
|
3
|
+
*
|
|
4
|
+
* Provides step-by-step workflow tracking for guided mode.
|
|
5
|
+
*/
|
|
6
|
+
export { STEP_ORDER, GUIDED_STEP_CRITERIA, getNextStep, getPreviousStep, getStepNumber, isValidTransition, getStepCriteria, getStepDescription, formatStepDisplay, } from './step-criteria.js';
|
|
7
|
+
export { GuidedStepTracker, stepTracker, } from './step-tracker.js';
|
|
8
|
+
export { GUIDED_MODE_SYSTEM_PROMPT, generateDynamicContext, generateStatusLine, shouldInjectGuidedContext, getFullGuidedPrompt, } from './guided-mode-injector.js';
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Step Criteria - Defines exit criteria for each guided workflow step
|
|
3
|
+
*
|
|
4
|
+
* Each step has:
|
|
5
|
+
* - Human-readable exit criteria (for system prompt)
|
|
6
|
+
* - Success indicators (what agent looks for)
|
|
7
|
+
* - Configuration (max attempts, auto-advance)
|
|
8
|
+
*/
|
|
9
|
+
import type { GuidedStep } from '../db/schema.js';
|
|
10
|
+
/**
|
|
11
|
+
* Step criteria definition
|
|
12
|
+
*/
|
|
13
|
+
export interface StepCriteria {
|
|
14
|
+
/** The guided step */
|
|
15
|
+
step: GuidedStep;
|
|
16
|
+
/** Human-readable exit criteria for system prompt */
|
|
17
|
+
exitCriteria: string[];
|
|
18
|
+
/** What agent looks for to determine success */
|
|
19
|
+
successIndicators: string[];
|
|
20
|
+
/** Maximum attempts for retryable steps (like test) */
|
|
21
|
+
maxAttempts?: number;
|
|
22
|
+
/** Can agent advance automatically when criteria met? */
|
|
23
|
+
autoAdvance: boolean;
|
|
24
|
+
/** Hint for next action after advancing */
|
|
25
|
+
nextActionHint: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Step order - defines valid step progression
|
|
29
|
+
*/
|
|
30
|
+
export declare const STEP_ORDER: readonly GuidedStep[];
|
|
31
|
+
/**
|
|
32
|
+
* Get the next step in the workflow
|
|
33
|
+
*/
|
|
34
|
+
export declare function getNextStep(current: GuidedStep | null): GuidedStep | 'complete';
|
|
35
|
+
/**
|
|
36
|
+
* Get the previous step in the workflow
|
|
37
|
+
*/
|
|
38
|
+
export declare function getPreviousStep(current: GuidedStep): GuidedStep | null;
|
|
39
|
+
/**
|
|
40
|
+
* Get step number (1-indexed for display)
|
|
41
|
+
*/
|
|
42
|
+
export declare function getStepNumber(step: GuidedStep): number;
|
|
43
|
+
/**
|
|
44
|
+
* Check if step transition is valid (can only advance to next step)
|
|
45
|
+
*/
|
|
46
|
+
export declare function isValidTransition(from: GuidedStep | null, to: GuidedStep | 'complete'): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Guided step criteria definitions
|
|
49
|
+
*/
|
|
50
|
+
export declare const GUIDED_STEP_CRITERIA: readonly StepCriteria[];
|
|
51
|
+
/**
|
|
52
|
+
* Get criteria for a specific step
|
|
53
|
+
*/
|
|
54
|
+
export declare function getStepCriteria(step: GuidedStep): StepCriteria;
|
|
55
|
+
/**
|
|
56
|
+
* Get human-readable step description for messages
|
|
57
|
+
*/
|
|
58
|
+
export declare function getStepDescription(step: GuidedStep): string;
|
|
59
|
+
/**
|
|
60
|
+
* Format step for display (e.g., "IMPLEMENT (2 of 5)")
|
|
61
|
+
*/
|
|
62
|
+
export declare function formatStepDisplay(step: GuidedStep): string;
|