@paths.design/caws-cli 9.3.1 → 10.0.1
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 +58 -27
- package/dist/commands/archive.js +67 -28
- package/dist/commands/burnup.js +20 -11
- package/dist/commands/diagnose.js +34 -22
- package/dist/commands/evaluate.js +27 -15
- package/dist/commands/gates.js +122 -0
- package/dist/commands/init.js +143 -15
- package/dist/commands/iterate.js +77 -4
- package/dist/commands/parallel.js +4 -0
- package/dist/commands/plan.js +9 -19
- package/dist/commands/provenance.js +53 -17
- package/dist/commands/quality-monitor.js +64 -45
- package/dist/commands/sidecar.js +71 -0
- package/dist/commands/specs.js +233 -44
- package/dist/commands/status.js +113 -9
- package/dist/commands/tutorial.js +10 -9
- package/dist/commands/validate.js +49 -6
- package/dist/commands/verify-acs.js +35 -78
- package/dist/commands/waivers.js +69 -12
- package/dist/commands/worktree.js +104 -26
- package/dist/error-handler.js +2 -13
- package/dist/gates/budget-limit.js +116 -0
- package/dist/gates/feedback.js +260 -0
- package/dist/gates/format.js +179 -0
- package/dist/gates/god-object.js +117 -0
- package/dist/gates/pipeline.js +167 -0
- package/dist/gates/scope-boundary.js +93 -0
- package/dist/gates/spec-completeness.js +102 -0
- package/dist/gates/todo-detection.js +205 -0
- package/dist/index.js +136 -150
- package/dist/parallel/parallel-manager.js +3 -3
- package/dist/policy/PolicyManager.js +42 -10
- package/dist/scaffold/claude-hooks.js +24 -1
- package/dist/scaffold/git-hooks.js +45 -102
- package/dist/scaffold/index.js +4 -3
- package/dist/session/session-manager.js +71 -14
- package/dist/sidecars/index.js +33 -0
- package/dist/sidecars/listeners.js +40 -0
- package/dist/sidecars/provenance-summary.js +238 -0
- package/dist/sidecars/quality-gaps.js +258 -0
- package/dist/sidecars/schema.js +149 -0
- package/dist/sidecars/spec-drift.js +151 -0
- package/dist/sidecars/waiver-draft.js +176 -0
- package/dist/templates/.caws/schemas/policy.schema.json +50 -0
- package/dist/templates/.caws/schemas/waivers.schema.json +30 -24
- package/dist/templates/.caws/schemas/working-spec.schema.json +51 -8
- package/dist/templates/.caws/schemas/worktrees.schema.json +3 -1
- package/dist/templates/.caws/templates/working-spec.template.yml +7 -3
- package/dist/templates/.claude/hooks/audit.sh +0 -0
- package/dist/templates/.claude/hooks/block-dangerous.sh +52 -11
- package/dist/templates/.claude/hooks/classify_command.py +592 -0
- package/dist/templates/.claude/hooks/doc-frontmatter-check.sh +173 -0
- package/dist/templates/.claude/hooks/quality-check.sh +23 -10
- package/dist/templates/.claude/hooks/scope-guard.sh +34 -32
- package/dist/templates/.claude/hooks/session-caws-status.sh +2 -2
- package/dist/templates/.claude/hooks/session-log.sh +76 -3
- package/dist/templates/.claude/hooks/stop-worktree-check.sh +1 -1
- package/dist/templates/.claude/hooks/test_classify_command.py +370 -0
- package/dist/templates/.claude/hooks/test_wrapper_smoke.sh +96 -0
- package/dist/templates/.claude/hooks/worktree-guard.sh +36 -23
- package/dist/templates/.claude/hooks/worktree-write-guard.sh +6 -5
- package/dist/templates/.claude/settings.json +26 -0
- package/dist/templates/.cursor/hooks/caws-quality-check.sh +4 -4
- package/dist/templates/.cursor/hooks/caws-scope-guard.sh +1 -1
- package/dist/templates/.cursor/hooks/session-log.sh +924 -0
- package/dist/templates/.cursor/hooks.json +25 -0
- package/dist/templates/.cursor/rules/02-quality-gates.mdc +3 -5
- package/dist/templates/.cursor/rules/10-documentation-quality-standards.mdc +6 -11
- package/dist/templates/.cursor/rules/11-scope-management-waivers.mdc +14 -18
- package/dist/templates/.cursor/rules/12-implementation-completeness.mdc +4 -4
- package/dist/templates/.cursor/rules/13-language-agnostic-standards.mdc +3 -13
- package/dist/templates/.github/copilot-instructions.md +5 -5
- package/dist/templates/.idea/runConfigurations/CAWS_Evaluate.xml +1 -1
- package/dist/templates/.junie/guidelines.md +2 -2
- package/dist/templates/.vscode/settings.json +3 -1
- package/dist/templates/.windsurf/rules/caws-quality-standards.md +2 -2
- package/dist/templates/.windsurf/workflows/caws-guided-development.md +3 -3
- package/dist/templates/CLAUDE.md +43 -8
- package/dist/templates/agents.md +29 -9
- package/dist/templates/docs/README.md +8 -7
- package/dist/templates/scripts/new_feature.sh +80 -0
- package/dist/test-analysis.js +43 -30
- package/dist/tool-loader.js +1 -1
- package/dist/utils/agent-session.js +202 -0
- package/dist/utils/detection.js +8 -2
- package/dist/utils/finalization.js +7 -6
- package/dist/utils/gitignore-updater.js +3 -0
- package/dist/utils/lifecycle-events.js +94 -0
- package/dist/utils/quality-gates-utils.js +29 -44
- package/dist/utils/schema-validator.js +42 -0
- package/dist/utils/spec-resolver.js +93 -21
- package/dist/utils/working-state.js +505 -0
- package/dist/validation/spec-validation.js +92 -22
- package/dist/waivers-manager.js +60 -6
- package/dist/worktree/worktree-manager.js +496 -95
- package/package.json +6 -6
- package/templates/.caws/schemas/policy.schema.json +50 -0
- package/templates/.caws/schemas/waivers.schema.json +30 -24
- package/templates/.caws/schemas/working-spec.schema.json +51 -8
- package/templates/.caws/schemas/worktrees.schema.json +3 -1
- package/templates/.caws/templates/working-spec.template.yml +7 -3
- package/templates/.claude/hooks/block-dangerous.sh +52 -11
- package/templates/.claude/hooks/classify_command.py +592 -0
- package/templates/.claude/hooks/doc-frontmatter-check.sh +173 -0
- package/templates/.claude/hooks/quality-check.sh +23 -10
- package/templates/.claude/hooks/scope-guard.sh +34 -32
- package/templates/.claude/hooks/session-caws-status.sh +2 -2
- package/templates/.claude/hooks/session-log.sh +76 -3
- package/templates/.claude/hooks/stop-worktree-check.sh +1 -1
- package/templates/.claude/hooks/test_classify_command.py +370 -0
- package/templates/.claude/hooks/test_wrapper_smoke.sh +96 -0
- package/templates/.claude/hooks/worktree-guard.sh +36 -23
- package/templates/.claude/hooks/worktree-write-guard.sh +6 -5
- package/templates/.claude/settings.json +26 -0
- package/templates/.cursor/hooks/caws-quality-check.sh +4 -4
- package/templates/.cursor/hooks/caws-scope-guard.sh +1 -1
- package/templates/.cursor/hooks/session-log.sh +924 -0
- package/templates/.cursor/hooks.json +25 -0
- package/templates/.cursor/rules/02-quality-gates.mdc +3 -5
- package/templates/.cursor/rules/10-documentation-quality-standards.mdc +6 -11
- package/templates/.cursor/rules/11-scope-management-waivers.mdc +14 -18
- package/templates/.cursor/rules/12-implementation-completeness.mdc +4 -4
- package/templates/.cursor/rules/13-language-agnostic-standards.mdc +3 -13
- package/templates/.github/copilot-instructions.md +5 -5
- package/templates/.idea/runConfigurations/CAWS_Evaluate.xml +1 -1
- package/templates/.junie/guidelines.md +2 -2
- package/templates/.vscode/settings.json +3 -1
- package/templates/.windsurf/rules/caws-quality-standards.md +2 -2
- package/templates/.windsurf/workflows/caws-guided-development.md +3 -3
- package/templates/CLAUDE.md +43 -8
- package/templates/{AGENTS.md → agents.md} +29 -9
- package/templates/docs/README.md +8 -7
- package/templates/scripts/new_feature.sh +80 -0
- package/dist/budget-derivation.d.ts +0 -74
- package/dist/budget-derivation.d.ts.map +0 -1
- package/dist/cicd-optimizer.d.ts +0 -142
- package/dist/cicd-optimizer.d.ts.map +0 -1
- package/dist/commands/archive.d.ts +0 -51
- package/dist/commands/archive.d.ts.map +0 -1
- package/dist/commands/burnup.d.ts +0 -6
- package/dist/commands/burnup.d.ts.map +0 -1
- package/dist/commands/diagnose.d.ts +0 -52
- package/dist/commands/diagnose.d.ts.map +0 -1
- package/dist/commands/evaluate.d.ts +0 -8
- package/dist/commands/evaluate.d.ts.map +0 -1
- package/dist/commands/init.d.ts +0 -5
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/iterate.d.ts +0 -8
- package/dist/commands/iterate.d.ts.map +0 -1
- package/dist/commands/mode.d.ts +0 -25
- package/dist/commands/mode.d.ts.map +0 -1
- package/dist/commands/parallel.d.ts +0 -7
- package/dist/commands/parallel.d.ts.map +0 -1
- package/dist/commands/plan.d.ts +0 -49
- package/dist/commands/plan.d.ts.map +0 -1
- package/dist/commands/provenance.d.ts +0 -32
- package/dist/commands/provenance.d.ts.map +0 -1
- package/dist/commands/quality-gates.d.ts +0 -6
- package/dist/commands/quality-gates.d.ts.map +0 -1
- package/dist/commands/quality-gates.js +0 -444
- package/dist/commands/quality-monitor.d.ts +0 -17
- package/dist/commands/quality-monitor.d.ts.map +0 -1
- package/dist/commands/session.d.ts +0 -7
- package/dist/commands/session.d.ts.map +0 -1
- package/dist/commands/specs.d.ts +0 -77
- package/dist/commands/specs.d.ts.map +0 -1
- package/dist/commands/status.d.ts +0 -44
- package/dist/commands/status.d.ts.map +0 -1
- package/dist/commands/templates.d.ts +0 -74
- package/dist/commands/templates.d.ts.map +0 -1
- package/dist/commands/tool.d.ts +0 -13
- package/dist/commands/tool.d.ts.map +0 -1
- package/dist/commands/troubleshoot.d.ts +0 -8
- package/dist/commands/troubleshoot.d.ts.map +0 -1
- package/dist/commands/troubleshoot.js +0 -104
- package/dist/commands/tutorial.d.ts +0 -55
- package/dist/commands/tutorial.d.ts.map +0 -1
- package/dist/commands/validate.d.ts +0 -15
- package/dist/commands/validate.d.ts.map +0 -1
- package/dist/commands/waivers.d.ts +0 -8
- package/dist/commands/waivers.d.ts.map +0 -1
- package/dist/commands/workflow.d.ts +0 -85
- package/dist/commands/workflow.d.ts.map +0 -1
- package/dist/commands/worktree.d.ts +0 -7
- package/dist/commands/worktree.d.ts.map +0 -1
- package/dist/config/index.d.ts +0 -29
- package/dist/config/index.d.ts.map +0 -1
- package/dist/config/lite-scope.d.ts +0 -33
- package/dist/config/lite-scope.d.ts.map +0 -1
- package/dist/config/modes.d.ts +0 -264
- package/dist/config/modes.d.ts.map +0 -1
- package/dist/constants/spec-types.d.ts +0 -93
- package/dist/constants/spec-types.d.ts.map +0 -1
- package/dist/error-handler.d.ts +0 -151
- package/dist/error-handler.d.ts.map +0 -1
- package/dist/generators/jest-config-generator.d.ts +0 -32
- package/dist/generators/jest-config-generator.d.ts.map +0 -1
- package/dist/generators/jest-config.d.ts +0 -32
- package/dist/generators/jest-config.d.ts.map +0 -1
- package/dist/generators/jest-config.js +0 -242
- package/dist/generators/working-spec.d.ts +0 -13
- package/dist/generators/working-spec.d.ts.map +0 -1
- package/dist/index-new.d.ts +0 -5
- package/dist/index-new.d.ts.map +0 -1
- package/dist/index-new.js +0 -317
- package/dist/index.d.ts +0 -5
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.backup +0 -4711
- package/dist/minimal-cli.d.ts +0 -3
- package/dist/minimal-cli.d.ts.map +0 -1
- package/dist/parallel/parallel-manager.d.ts +0 -67
- package/dist/parallel/parallel-manager.d.ts.map +0 -1
- package/dist/policy/PolicyManager.d.ts +0 -104
- package/dist/policy/PolicyManager.d.ts.map +0 -1
- package/dist/scaffold/claude-hooks.d.ts +0 -28
- package/dist/scaffold/claude-hooks.d.ts.map +0 -1
- package/dist/scaffold/cursor-hooks.d.ts +0 -7
- package/dist/scaffold/cursor-hooks.d.ts.map +0 -1
- package/dist/scaffold/git-hooks.d.ts +0 -38
- package/dist/scaffold/git-hooks.d.ts.map +0 -1
- package/dist/scaffold/index.d.ts +0 -17
- package/dist/scaffold/index.d.ts.map +0 -1
- package/dist/session/session-manager.d.ts +0 -94
- package/dist/session/session-manager.d.ts.map +0 -1
- package/dist/spec/SpecFileManager.d.ts +0 -146
- package/dist/spec/SpecFileManager.d.ts.map +0 -1
- package/dist/templates/.cursor/hooks/caws-tool-validation.sh +0 -121
- package/dist/templates/.github/copilot/instructions.md +0 -311
- package/dist/test-analysis.d.ts +0 -231
- package/dist/test-analysis.d.ts.map +0 -1
- package/dist/tool-interface.d.ts +0 -236
- package/dist/tool-interface.d.ts.map +0 -1
- package/dist/tool-loader.d.ts +0 -77
- package/dist/tool-loader.d.ts.map +0 -1
- package/dist/tool-validator.d.ts +0 -72
- package/dist/tool-validator.d.ts.map +0 -1
- package/dist/utils/async-utils.d.ts +0 -73
- package/dist/utils/async-utils.d.ts.map +0 -1
- package/dist/utils/command-wrapper.d.ts +0 -66
- package/dist/utils/command-wrapper.d.ts.map +0 -1
- package/dist/utils/detection.d.ts +0 -14
- package/dist/utils/detection.d.ts.map +0 -1
- package/dist/utils/error-categories.d.ts +0 -52
- package/dist/utils/error-categories.d.ts.map +0 -1
- package/dist/utils/finalization.d.ts +0 -17
- package/dist/utils/finalization.d.ts.map +0 -1
- package/dist/utils/git-lock.d.ts +0 -13
- package/dist/utils/git-lock.d.ts.map +0 -1
- package/dist/utils/gitignore-updater.d.ts +0 -39
- package/dist/utils/gitignore-updater.d.ts.map +0 -1
- package/dist/utils/ide-detection.d.ts +0 -89
- package/dist/utils/ide-detection.d.ts.map +0 -1
- package/dist/utils/project-analysis.d.ts +0 -34
- package/dist/utils/project-analysis.d.ts.map +0 -1
- package/dist/utils/promise-utils.d.ts +0 -30
- package/dist/utils/promise-utils.d.ts.map +0 -1
- package/dist/utils/quality-gates-utils.d.ts +0 -49
- package/dist/utils/quality-gates-utils.d.ts.map +0 -1
- package/dist/utils/quality-gates.d.ts +0 -49
- package/dist/utils/quality-gates.d.ts.map +0 -1
- package/dist/utils/quality-gates.js +0 -402
- package/dist/utils/spec-resolver.d.ts +0 -80
- package/dist/utils/spec-resolver.d.ts.map +0 -1
- package/dist/utils/typescript-detector.d.ts +0 -66
- package/dist/utils/typescript-detector.d.ts.map +0 -1
- package/dist/utils/yaml-validation.d.ts +0 -32
- package/dist/utils/yaml-validation.d.ts.map +0 -1
- package/dist/validation/spec-validation.d.ts +0 -43
- package/dist/validation/spec-validation.d.ts.map +0 -1
- package/dist/waivers-manager.d.ts +0 -167
- package/dist/waivers-manager.d.ts.map +0 -1
- package/dist/worktree/worktree-manager.d.ts +0 -54
- package/dist/worktree/worktree-manager.d.ts.map +0 -1
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview TODO/FIXME scanning gate
|
|
3
|
+
* Detects actionable TODO, FIXME, HACK, XXX markers in comments.
|
|
4
|
+
* Filters out false positives: string literals, regex definitions, test assertions,
|
|
5
|
+
* and documentation about the TODO system itself.
|
|
6
|
+
* Context-aware: commit context scans staged diff, cli/edit context scans file content.
|
|
7
|
+
* @author @darianrosebrook
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { execSync } = require('child_process');
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
const name = 'todo_detection';
|
|
15
|
+
|
|
16
|
+
const TODO_MARKERS = /\b(TODO|FIXME|HACK|XXX)\b/g;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Comment patterns for languages we scan.
|
|
20
|
+
* A line is a "comment TODO" if the TODO marker appears after a comment introducer.
|
|
21
|
+
*/
|
|
22
|
+
const COMMENT_TODO = /(?:\/\/|#|\/?\*|\{\/\*)\s*\b(TODO|FIXME|HACK|XXX)\b/;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Patterns that indicate the line is ABOUT the TODO system, not an actual TODO.
|
|
26
|
+
* These are lines where TODO appears as data, not as intent.
|
|
27
|
+
*/
|
|
28
|
+
const FALSE_POSITIVE_PATTERNS = [
|
|
29
|
+
/TODO_PATTERN/, // regex variable name
|
|
30
|
+
/TODO\/FIXME/, // describing the pattern itself
|
|
31
|
+
/\btoMatch\b|\btoContain\b|\bexpect\(/, // test assertions
|
|
32
|
+
/writeFileSync.*TODO/, // test fixture data
|
|
33
|
+
/\bdescribe\(.*TODO|\btest\(.*TODO|\bit\(.*TODO/, // test names
|
|
34
|
+
/Pattern.*TODO|regex.*TODO/i, // documentation about patterns
|
|
35
|
+
/["'`].*\bTODO\b.*["'`]/, // string literals containing TODO
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
/** Directories to skip when scanning files directly */
|
|
39
|
+
const EXCLUDE_DIRS = ['node_modules/', 'dist/', 'dist-bundle/', 'build/', '.next/', 'coverage/', 'vendor/', '__pycache__/'];
|
|
40
|
+
|
|
41
|
+
/** Files that are part of the TODO detection system itself — skip to avoid self-analysis */
|
|
42
|
+
const SELF_FILES = ['todo-detection.js', 'todo_detection.js', 'todo_analyzer.py', 'todo-analyzer'];
|
|
43
|
+
|
|
44
|
+
/** Extensions to scan */
|
|
45
|
+
const SOURCE_EXTENSIONS = ['.js', '.ts', '.tsx', '.jsx', '.py', '.rs', '.go', '.java', '.rb', '.cs', '.sh'];
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Check if a file should be excluded from scanning.
|
|
49
|
+
* @param {string} filePath - Relative file path
|
|
50
|
+
* @returns {boolean}
|
|
51
|
+
*/
|
|
52
|
+
function isExcluded(filePath) {
|
|
53
|
+
for (const dir of EXCLUDE_DIRS) {
|
|
54
|
+
if (filePath.startsWith(dir) || filePath.includes('/' + dir)) return true;
|
|
55
|
+
}
|
|
56
|
+
// Skip the gate's own implementation files
|
|
57
|
+
const basename = path.basename(filePath);
|
|
58
|
+
for (const self of SELF_FILES) {
|
|
59
|
+
if (basename === self || basename.includes(self)) return true;
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Check if a line contains a real TODO comment (not a false positive).
|
|
66
|
+
* Returns the marker name if real, null if false positive.
|
|
67
|
+
* @param {string} line - Source line
|
|
68
|
+
* @returns {string|null} The marker found, or null
|
|
69
|
+
*/
|
|
70
|
+
function findRealTodo(line) {
|
|
71
|
+
const trimmed = line.trim();
|
|
72
|
+
|
|
73
|
+
// Must contain a marker at all
|
|
74
|
+
TODO_MARKERS.lastIndex = 0;
|
|
75
|
+
if (!TODO_MARKERS.test(trimmed)) return null;
|
|
76
|
+
|
|
77
|
+
// Filter out false positives
|
|
78
|
+
for (const fp of FALSE_POSITIVE_PATTERNS) {
|
|
79
|
+
if (fp.test(trimmed)) return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Must look like a comment containing the marker — not just any line with TODO in it
|
|
83
|
+
if (!COMMENT_TODO.test(trimmed)) return null;
|
|
84
|
+
|
|
85
|
+
// Extract which marker
|
|
86
|
+
TODO_MARKERS.lastIndex = 0;
|
|
87
|
+
const match = TODO_MARKERS.exec(trimmed);
|
|
88
|
+
return match ? match[1] : null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Scan staged diff for newly-added TODO markers.
|
|
93
|
+
* Used in commit context — only flags markers being added, not pre-existing ones.
|
|
94
|
+
*/
|
|
95
|
+
function scanStagedDiff(projectRoot) {
|
|
96
|
+
const messages = [];
|
|
97
|
+
let totalCount = 0;
|
|
98
|
+
|
|
99
|
+
const diff = execSync('git diff --cached -U0', {
|
|
100
|
+
cwd: projectRoot,
|
|
101
|
+
encoding: 'utf8',
|
|
102
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
let currentFile = null;
|
|
106
|
+
let lineNum = 0;
|
|
107
|
+
|
|
108
|
+
for (const line of diff.split('\n')) {
|
|
109
|
+
if (line.startsWith('+++ b/')) {
|
|
110
|
+
currentFile = line.slice(6);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (line.startsWith('@@')) {
|
|
114
|
+
const match = line.match(/@@ -\d+(?:,\d+)? \+(\d+)/);
|
|
115
|
+
if (match) {
|
|
116
|
+
lineNum = parseInt(match[1], 10) - 1;
|
|
117
|
+
}
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (line.startsWith('+') && !line.startsWith('+++')) {
|
|
121
|
+
lineNum++;
|
|
122
|
+
const content = line.slice(1); // remove the leading +
|
|
123
|
+
const marker = findRealTodo(content);
|
|
124
|
+
if (marker) {
|
|
125
|
+
totalCount++;
|
|
126
|
+
messages.push(`${currentFile}:${lineNum}: ${marker} found`);
|
|
127
|
+
}
|
|
128
|
+
} else if (!line.startsWith('-')) {
|
|
129
|
+
lineNum++;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return { totalCount, messages };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Scan file contents directly for TODO markers.
|
|
138
|
+
* Used in cli/edit context — reports all existing markers in the given files.
|
|
139
|
+
*/
|
|
140
|
+
function scanFiles(stagedFiles, projectRoot) {
|
|
141
|
+
const messages = [];
|
|
142
|
+
let totalCount = 0;
|
|
143
|
+
|
|
144
|
+
const filesToScan = stagedFiles.filter(f =>
|
|
145
|
+
SOURCE_EXTENSIONS.some(ext => f.endsWith(ext)) && !isExcluded(f)
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
for (const file of filesToScan) {
|
|
149
|
+
try {
|
|
150
|
+
const fullPath = path.resolve(projectRoot, file);
|
|
151
|
+
if (!fs.existsSync(fullPath)) continue;
|
|
152
|
+
|
|
153
|
+
const content = fs.readFileSync(fullPath, 'utf8');
|
|
154
|
+
const lines = content.split('\n');
|
|
155
|
+
|
|
156
|
+
for (let i = 0; i < lines.length; i++) {
|
|
157
|
+
const marker = findRealTodo(lines[i]);
|
|
158
|
+
if (marker) {
|
|
159
|
+
totalCount++;
|
|
160
|
+
messages.push(`${file}:${i + 1}: ${marker} found`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
} catch {
|
|
164
|
+
// Skip unreadable files
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return { totalCount, messages };
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Run the TODO detection gate
|
|
173
|
+
* @param {Object} params - Gate parameters
|
|
174
|
+
* @param {string[]} params.stagedFiles - File paths to check
|
|
175
|
+
* @param {string} params.projectRoot - Project root
|
|
176
|
+
* @param {string} [params.context] - Execution context (commit, cli, edit)
|
|
177
|
+
* @returns {Promise<Object>} Gate result with status and messages
|
|
178
|
+
*/
|
|
179
|
+
async function run({ stagedFiles, projectRoot, context }) {
|
|
180
|
+
try {
|
|
181
|
+
let result;
|
|
182
|
+
|
|
183
|
+
if (context === 'commit') {
|
|
184
|
+
// Commit context: scan only newly-added lines in staged diff
|
|
185
|
+
result = scanStagedDiff(projectRoot);
|
|
186
|
+
} else {
|
|
187
|
+
// CLI/edit context: scan file contents directly
|
|
188
|
+
result = scanFiles(stagedFiles, projectRoot);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (result.totalCount > 0) {
|
|
192
|
+
result.messages.unshift(`Found ${result.totalCount} TODO/FIXME/HACK/XXX marker(s)${context === 'commit' ? ' in staged changes' : ''}`);
|
|
193
|
+
return { status: 'warn', messages: result.messages };
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return { status: 'pass', messages: [] };
|
|
197
|
+
} catch (err) {
|
|
198
|
+
return {
|
|
199
|
+
status: 'warn',
|
|
200
|
+
messages: [`Cannot scan for TODO markers: ${err.message}`],
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
module.exports = { name, run };
|
package/dist/index.js
CHANGED
|
@@ -8,14 +8,16 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
const { Command } = require('commander');
|
|
11
|
-
// eslint-disable-next-line no-unused-vars
|
|
12
|
-
const fs = require('fs-extra');
|
|
13
|
-
// eslint-disable-next-line no-unused-vars
|
|
14
|
-
const path = require('path');
|
|
15
|
-
// eslint-disable-next-line no-unused-vars
|
|
16
|
-
const yaml = require('js-yaml');
|
|
17
11
|
const chalk = require('chalk');
|
|
18
12
|
|
|
13
|
+
if (
|
|
14
|
+
process.argv.includes('--json') ||
|
|
15
|
+
process.argv.includes('--quiet') ||
|
|
16
|
+
process.argv.includes('-q')
|
|
17
|
+
) {
|
|
18
|
+
process.env.CAWS_QUIET = '1';
|
|
19
|
+
}
|
|
20
|
+
|
|
19
21
|
// Import configuration and utilities
|
|
20
22
|
const {
|
|
21
23
|
CLI_VERSION,
|
|
@@ -42,8 +44,7 @@ const { iterateCommand } = require('./commands/iterate');
|
|
|
42
44
|
const { waiversCommand } = require('./commands/waivers');
|
|
43
45
|
const { workflowCommand } = require('./commands/workflow');
|
|
44
46
|
const { qualityMonitorCommand } = require('./commands/quality-monitor');
|
|
45
|
-
const {
|
|
46
|
-
const { troubleshootCommand } = require('./commands/troubleshoot');
|
|
47
|
+
const { gatesCommand } = require('./commands/gates');
|
|
47
48
|
const { archiveCommand } = require('./commands/archive');
|
|
48
49
|
const { specsCommand } = require('./commands/specs');
|
|
49
50
|
const { modeCommand } = require('./commands/mode');
|
|
@@ -53,6 +54,7 @@ const { worktreeCommand } = require('./commands/worktree');
|
|
|
53
54
|
const { sessionCommand } = require('./commands/session');
|
|
54
55
|
const { parallelCommand } = require('./commands/parallel');
|
|
55
56
|
const { verifyAcsCommand } = require('./commands/verify-acs');
|
|
57
|
+
const { sidecarCommand } = require('./commands/sidecar');
|
|
56
58
|
|
|
57
59
|
// Import scaffold functionality
|
|
58
60
|
const { scaffoldProject, setScaffoldDependencies } = require('./scaffold');
|
|
@@ -60,16 +62,8 @@ const { scaffoldProject, setScaffoldDependencies } = require('./scaffold');
|
|
|
60
62
|
// Import git hooks functionality
|
|
61
63
|
const { scaffoldGitHooks, removeGitHooks, checkGitHooksStatus } = require('./scaffold/git-hooks');
|
|
62
64
|
|
|
63
|
-
// Import validation functionality
|
|
64
|
-
// eslint-disable-next-line no-unused-vars
|
|
65
|
-
const { validateWorkingSpecWithSuggestions } = require('./validation/spec-validation');
|
|
66
|
-
|
|
67
65
|
// Import finalization utilities
|
|
68
66
|
const {
|
|
69
|
-
// eslint-disable-next-line no-unused-vars
|
|
70
|
-
finalizeProject,
|
|
71
|
-
// eslint-disable-next-line no-unused-vars
|
|
72
|
-
continueToSuccess,
|
|
73
67
|
setFinalizationDependencies,
|
|
74
68
|
} = require('./utils/finalization');
|
|
75
69
|
|
|
@@ -139,84 +133,40 @@ program
|
|
|
139
133
|
.option('--format <format>', 'Output format (text, json)', 'text')
|
|
140
134
|
.action(validateCommand);
|
|
141
135
|
|
|
142
|
-
//
|
|
136
|
+
// Gates command group (v2 pipeline)
|
|
137
|
+
const gatesCmd = program
|
|
138
|
+
.command('gates')
|
|
139
|
+
.description('Run quality gate checks');
|
|
140
|
+
|
|
141
|
+
gatesCmd
|
|
142
|
+
.command('run')
|
|
143
|
+
.description('Run quality gates against staged files or a specific file')
|
|
144
|
+
.option('--context <context>', 'Execution context (cli, commit, edit)', 'cli')
|
|
145
|
+
.option('--spec-id <id>', 'Target spec ID')
|
|
146
|
+
.option('--file <path>', 'Single file to check (for edit context)')
|
|
147
|
+
.option('--json', 'Output as JSON', false)
|
|
148
|
+
.option('--quiet', 'Minimal output', false)
|
|
149
|
+
.action((options) => gatesCommand(options));
|
|
150
|
+
|
|
151
|
+
// Quality Gates command (legacy alias — delegates to gates command)
|
|
143
152
|
program
|
|
144
153
|
.command('quality-gates')
|
|
145
|
-
.description('Run
|
|
154
|
+
.description('Run quality gates (alias for "caws gates run")')
|
|
146
155
|
.option('--ci', 'CI mode - exit with error code if violations found', false)
|
|
147
156
|
.option('--json', 'Output machine-readable JSON to stdout', false)
|
|
148
|
-
.option(
|
|
149
|
-
'--gates <gates>',
|
|
150
|
-
'Run only specific gates (comma-separated: naming,code_freeze,duplication,god_objects,hidden-todo,documentation,placeholders)',
|
|
151
|
-
''
|
|
152
|
-
)
|
|
153
|
-
.option('--fix', 'Attempt automatic fixes (experimental)', false)
|
|
154
|
-
.option('--context <context>', 'Execution context: commit (staged files), push (all tracked files), or ci (all tracked files)', 'commit')
|
|
157
|
+
.option('--context <context>', 'Execution context: commit, push, ci', 'commit')
|
|
155
158
|
.option('--all-files', 'Check all tracked files (equivalent to --context=ci)', false)
|
|
156
|
-
.option('--
|
|
159
|
+
.option('--spec-id <id>', 'Target spec ID')
|
|
160
|
+
.option('--quiet', 'Minimal output', false)
|
|
157
161
|
.action(async (options) => {
|
|
158
|
-
//
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
DESCRIPTION:
|
|
167
|
-
Runs comprehensive quality gates to maintain code quality standards.
|
|
168
|
-
Supports selective gate execution, JSON output, and CI/CD integration.
|
|
169
|
-
|
|
170
|
-
OPTIONS:
|
|
171
|
-
--ci CI mode - exit with error code if violations found
|
|
172
|
-
--json Output machine-readable JSON to stdout
|
|
173
|
-
--gates=<gates> Run only specific gates (comma-separated)
|
|
174
|
-
--fix Attempt automatic fixes (experimental)
|
|
175
|
-
--context=<ctx> Execution context: commit (staged files), push (all tracked), ci (all tracked)
|
|
176
|
-
--all-files Check all tracked files (shortcut for --context=ci)
|
|
177
|
-
--help Show this help message
|
|
178
|
-
|
|
179
|
-
VALID GATES:
|
|
180
|
-
naming Check naming conventions and banned modifiers
|
|
181
|
-
code_freeze Enforce code freeze compliance
|
|
182
|
-
duplication Detect functional duplication
|
|
183
|
-
god_objects Prevent oversized files
|
|
184
|
-
hidden-todo Detect hidden incomplete implementations
|
|
185
|
-
documentation Check documentation quality
|
|
186
|
-
placeholders Placeholder governance (explicit degradations)
|
|
187
|
-
|
|
188
|
-
EXAMPLES:
|
|
189
|
-
# Run all gates in development mode
|
|
190
|
-
caws quality-gates
|
|
191
|
-
|
|
192
|
-
# Run only specific gates
|
|
193
|
-
caws quality-gates --gates=naming,duplication
|
|
194
|
-
|
|
195
|
-
# CI mode with JSON output
|
|
196
|
-
caws quality-gates --ci --json
|
|
197
|
-
|
|
198
|
-
# Check all files in repository (not just staged)
|
|
199
|
-
caws quality-gates --all-files
|
|
200
|
-
|
|
201
|
-
# Use specific context
|
|
202
|
-
caws quality-gates --context=ci
|
|
203
|
-
|
|
204
|
-
# Show detailed help
|
|
205
|
-
caws quality-gates --help
|
|
206
|
-
|
|
207
|
-
OUTPUT:
|
|
208
|
-
- Console: Human-readable results with enforcement levels
|
|
209
|
-
- JSON: Machine-readable structured data (--json flag)
|
|
210
|
-
- Artifacts: docs-status/quality-gates-report.json
|
|
211
|
-
- GitHub Actions: Automatic step summaries when GITHUB_STEP_SUMMARY is set
|
|
212
|
-
|
|
213
|
-
For more information, see: packages/quality-gates/README.md
|
|
214
|
-
`);
|
|
215
|
-
process.exit(0);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// Call the actual quality gates runner
|
|
219
|
-
await qualityGatesCommand(options);
|
|
162
|
+
// Map legacy options to new gates command options
|
|
163
|
+
const gateOpts = {
|
|
164
|
+
context: options.allFiles ? 'ci' : (options.context || 'cli'),
|
|
165
|
+
specId: options.specId,
|
|
166
|
+
json: options.json,
|
|
167
|
+
quiet: options.quiet,
|
|
168
|
+
};
|
|
169
|
+
await gatesCommand(gateOpts);
|
|
220
170
|
});
|
|
221
171
|
|
|
222
172
|
// Status command
|
|
@@ -234,6 +184,7 @@ program
|
|
|
234
184
|
.command('archive <change-id>')
|
|
235
185
|
.description('Archive completed change')
|
|
236
186
|
.option('--spec-id <id>', 'Feature-specific spec ID (e.g., user-auth)')
|
|
187
|
+
.option('-s, --spec <path>', 'Path to spec file (explicit override)')
|
|
237
188
|
.option('-f, --force', 'Force archive even if criteria not met', false)
|
|
238
189
|
.option('--dry-run', 'Preview archive without performing it', false)
|
|
239
190
|
.action(archiveCommand);
|
|
@@ -300,6 +251,38 @@ specsCmd
|
|
|
300
251
|
.description('Show available spec types')
|
|
301
252
|
.action(() => specsCommand('types', {}));
|
|
302
253
|
|
|
254
|
+
// Sidecar command group
|
|
255
|
+
const sidecarCmd = program.command('sidecar').description('Advisory analysis tools (drift, gaps, waivers, provenance)');
|
|
256
|
+
|
|
257
|
+
sidecarCmd
|
|
258
|
+
.command('drift')
|
|
259
|
+
.description('Analyze spec drift vs implementation evidence')
|
|
260
|
+
.option('--spec-id <id>', 'Target spec ID')
|
|
261
|
+
.option('--json', 'Output as JSON', false)
|
|
262
|
+
.action((options) => sidecarCommand('drift', options));
|
|
263
|
+
|
|
264
|
+
sidecarCmd
|
|
265
|
+
.command('gaps')
|
|
266
|
+
.description('Diagnose quality gaps preventing phase advancement')
|
|
267
|
+
.option('--spec-id <id>', 'Target spec ID')
|
|
268
|
+
.option('--json', 'Output as JSON', false)
|
|
269
|
+
.action((options) => sidecarCommand('gaps', options));
|
|
270
|
+
|
|
271
|
+
sidecarCmd
|
|
272
|
+
.command('waiver-draft')
|
|
273
|
+
.description('Generate pre-filled waiver templates from gate failures')
|
|
274
|
+
.option('--spec-id <id>', 'Target spec ID')
|
|
275
|
+
.option('--gate <gate>', 'Specific gate to draft waiver for')
|
|
276
|
+
.option('--json', 'Output as JSON', false)
|
|
277
|
+
.action((options) => sidecarCommand('waiver-draft', options));
|
|
278
|
+
|
|
279
|
+
sidecarCmd
|
|
280
|
+
.command('provenance')
|
|
281
|
+
.description('Summarize work provenance for merge readiness')
|
|
282
|
+
.option('--spec-id <id>', 'Target spec ID')
|
|
283
|
+
.option('--json', 'Output as JSON', false)
|
|
284
|
+
.action((options) => sidecarCommand('provenance', options));
|
|
285
|
+
|
|
303
286
|
// Mode command group
|
|
304
287
|
const modeCmd = program.command('mode').description('Manage CAWS complexity tiers');
|
|
305
288
|
|
|
@@ -314,13 +297,6 @@ modeCmd
|
|
|
314
297
|
.description('Set CAWS complexity tier')
|
|
315
298
|
.action((mode) => modeCommand('set', { mode }));
|
|
316
299
|
|
|
317
|
-
modeCmd
|
|
318
|
-
.command('set')
|
|
319
|
-
.description('Set CAWS complexity tier (interactive)')
|
|
320
|
-
.option('-i, --interactive', 'Interactive mode selection', false)
|
|
321
|
-
.option('-m, --mode <mode>', 'Specific mode to set')
|
|
322
|
-
.action((options) => modeCommand('set', options));
|
|
323
|
-
|
|
324
300
|
modeCmd
|
|
325
301
|
.command('compare')
|
|
326
302
|
.description('Compare all available tiers')
|
|
@@ -393,8 +369,17 @@ worktreeCmd
|
|
|
393
369
|
.command('prune')
|
|
394
370
|
.description('Clean up stale worktree entries')
|
|
395
371
|
.option('--max-age <days>', 'Remove entries older than N days', '30')
|
|
372
|
+
.option('--force', 'Allow pruning entries owned by other sessions', false)
|
|
396
373
|
.action((options) => worktreeCommand('prune', options));
|
|
397
374
|
|
|
375
|
+
worktreeCmd
|
|
376
|
+
.command('repair')
|
|
377
|
+
.description('Reconcile registry with git and filesystem state')
|
|
378
|
+
.option('--dry-run', 'Report only, do not persist changes', false)
|
|
379
|
+
.option('--prune', 'Remove destroyed, stale-merged, and missing entries', false)
|
|
380
|
+
.option('--force', 'Allow pruning entries owned by other sessions', false)
|
|
381
|
+
.action((options) => worktreeCommand('repair', options));
|
|
382
|
+
|
|
398
383
|
// Session command group
|
|
399
384
|
const sessionCmd = program
|
|
400
385
|
.command('session')
|
|
@@ -518,6 +503,14 @@ program
|
|
|
518
503
|
.option('-v, --verbose', 'Show detailed error information', false)
|
|
519
504
|
.action(iterateCommand);
|
|
520
505
|
|
|
506
|
+
// Burnup command
|
|
507
|
+
program
|
|
508
|
+
.command('burnup [spec-file]')
|
|
509
|
+
.description('Generate budget burn-up report for scope visibility')
|
|
510
|
+
.option('--spec-id <id>', 'Feature-specific spec ID (e.g., user-auth)')
|
|
511
|
+
.option('-v, --verbose', 'Show detailed error information', false)
|
|
512
|
+
.action(burnupCommand);
|
|
513
|
+
|
|
521
514
|
// Waivers command group
|
|
522
515
|
const waiversCmd = program.command('waivers').description('Manage CAWS quality gate waivers');
|
|
523
516
|
|
|
@@ -560,7 +553,7 @@ waiversCmd
|
|
|
560
553
|
.action((id, options) => waiversCommand('revoke', { ...options, id }));
|
|
561
554
|
|
|
562
555
|
// Workflow command group
|
|
563
|
-
|
|
556
|
+
program
|
|
564
557
|
.command('workflow <type>')
|
|
565
558
|
.description('Get workflow-specific guidance')
|
|
566
559
|
.option('--spec-id <id>', 'Feature-specific spec ID (e.g., user-auth)')
|
|
@@ -596,7 +589,9 @@ program
|
|
|
596
589
|
.command('test-analysis <subcommand> [options...]')
|
|
597
590
|
.description('Statistical analysis for budget prediction')
|
|
598
591
|
.option('--spec-id <id>', 'Feature-specific spec ID (e.g., user-auth)')
|
|
599
|
-
.action(
|
|
592
|
+
.action((subcommand, optionArgs, command) => {
|
|
593
|
+
testAnalysisCommand(subcommand, optionArgs, command.opts());
|
|
594
|
+
});
|
|
600
595
|
|
|
601
596
|
// Provenance command group
|
|
602
597
|
const provenanceCmd = program.command('provenance').description('Manage CAWS provenance tracking');
|
|
@@ -606,6 +601,8 @@ provenanceCmd
|
|
|
606
601
|
.command('update')
|
|
607
602
|
.description('Add new commit to provenance chain')
|
|
608
603
|
.requiredOption('-c, --commit <hash>', 'Git commit hash')
|
|
604
|
+
.option('--spec-id <id>', 'Feature-specific spec ID')
|
|
605
|
+
.option('-s, --spec <path>', 'Path to spec file (explicit override)')
|
|
609
606
|
.option('-m, --message <msg>', 'Commit message')
|
|
610
607
|
.option('-a, --author <info>', 'Author information')
|
|
611
608
|
.option('-q, --quiet', 'Suppress output')
|
|
@@ -642,6 +639,8 @@ provenanceCmd
|
|
|
642
639
|
provenanceCmd
|
|
643
640
|
.command('init')
|
|
644
641
|
.description('Initialize provenance tracking for the project')
|
|
642
|
+
.option('--spec-id <id>', 'Feature-specific spec ID')
|
|
643
|
+
.option('-s, --spec <path>', 'Path to spec file (explicit override)')
|
|
645
644
|
.option('-o, --output <path>', 'Output path for provenance files', '.caws/provenance')
|
|
646
645
|
.option('--cursor-api <url>', 'Cursor tracking API endpoint')
|
|
647
646
|
.option('--cursor-key <key>', 'Cursor API key')
|
|
@@ -718,6 +717,36 @@ program.configureHelp({
|
|
|
718
717
|
showError: () => {}, // Suppress default error display
|
|
719
718
|
});
|
|
720
719
|
|
|
720
|
+
const VALID_COMMANDS = [
|
|
721
|
+
'init',
|
|
722
|
+
'validate',
|
|
723
|
+
'scaffold',
|
|
724
|
+
'status',
|
|
725
|
+
'archive',
|
|
726
|
+
'specs',
|
|
727
|
+
'sidecar',
|
|
728
|
+
'mode',
|
|
729
|
+
'tutorial',
|
|
730
|
+
'plan',
|
|
731
|
+
'templates',
|
|
732
|
+
'diagnose',
|
|
733
|
+
'evaluate',
|
|
734
|
+
'iterate',
|
|
735
|
+
'waivers',
|
|
736
|
+
'workflow',
|
|
737
|
+
'quality-monitor',
|
|
738
|
+
'quality-gates',
|
|
739
|
+
'gates',
|
|
740
|
+
'provenance',
|
|
741
|
+
'hooks',
|
|
742
|
+
'burnup',
|
|
743
|
+
'tool',
|
|
744
|
+
'worktree',
|
|
745
|
+
'session',
|
|
746
|
+
'parallel',
|
|
747
|
+
'verify-acs',
|
|
748
|
+
];
|
|
749
|
+
|
|
721
750
|
program.exitOverride((err) => {
|
|
722
751
|
// Handle help and version requests gracefully
|
|
723
752
|
if (
|
|
@@ -732,34 +761,7 @@ program.exitOverride((err) => {
|
|
|
732
761
|
|
|
733
762
|
// Check for unknown command
|
|
734
763
|
if (err.code === 'commander.unknownCommand') {
|
|
735
|
-
const
|
|
736
|
-
'init',
|
|
737
|
-
'validate',
|
|
738
|
-
'scaffold',
|
|
739
|
-
'status',
|
|
740
|
-
'archive',
|
|
741
|
-
'specs',
|
|
742
|
-
'mode',
|
|
743
|
-
'tutorial',
|
|
744
|
-
'plan',
|
|
745
|
-
'templates',
|
|
746
|
-
'diagnose',
|
|
747
|
-
'evaluate',
|
|
748
|
-
'iterate',
|
|
749
|
-
'waivers',
|
|
750
|
-
'workflow',
|
|
751
|
-
'quality-monitor',
|
|
752
|
-
'troubleshoot',
|
|
753
|
-
'provenance',
|
|
754
|
-
'hooks',
|
|
755
|
-
'burnup',
|
|
756
|
-
'tool',
|
|
757
|
-
'worktree',
|
|
758
|
-
'session',
|
|
759
|
-
'parallel',
|
|
760
|
-
'verify-acs',
|
|
761
|
-
];
|
|
762
|
-
const similar = findSimilarCommand(commandName, validCommands);
|
|
764
|
+
const similar = findSimilarCommand(commandName, VALID_COMMANDS);
|
|
763
765
|
|
|
764
766
|
console.error(chalk.red(`\nUnknown command: ${commandName}`));
|
|
765
767
|
|
|
@@ -767,9 +769,7 @@ program.exitOverride((err) => {
|
|
|
767
769
|
console.error(chalk.yellow(`\nDid you mean: caws ${similar}?`));
|
|
768
770
|
}
|
|
769
771
|
|
|
770
|
-
console.error(
|
|
771
|
-
chalk.yellow('Available commands: init, validate, scaffold, provenance, hooks')
|
|
772
|
-
);
|
|
772
|
+
console.error(chalk.yellow('Run: caws --help for the full command list'));
|
|
773
773
|
console.error(chalk.yellow('Try: caws --help for full command list'));
|
|
774
774
|
console.error(
|
|
775
775
|
chalk.blue(
|
|
@@ -814,6 +814,12 @@ program.exitOverride((err) => {
|
|
|
814
814
|
process.exit(1);
|
|
815
815
|
});
|
|
816
816
|
|
|
817
|
+
// Register sidecar lifecycle listeners (non-fatal hints)
|
|
818
|
+
try {
|
|
819
|
+
const { registerSidecarListeners } = require('./sidecars/listeners');
|
|
820
|
+
registerSidecarListeners();
|
|
821
|
+
} catch { /* sidecars module not available — non-fatal */ }
|
|
822
|
+
|
|
817
823
|
// Parse and run
|
|
818
824
|
if (require.main === module) {
|
|
819
825
|
try {
|
|
@@ -837,25 +843,7 @@ if (require.main === module) {
|
|
|
837
843
|
|
|
838
844
|
// Check for unknown command
|
|
839
845
|
if (error.code === 'commander.unknownCommand') {
|
|
840
|
-
const
|
|
841
|
-
'init',
|
|
842
|
-
'validate',
|
|
843
|
-
'scaffold',
|
|
844
|
-
'status',
|
|
845
|
-
'archive',
|
|
846
|
-
'specs',
|
|
847
|
-
'mode',
|
|
848
|
-
'tutorial',
|
|
849
|
-
'plan',
|
|
850
|
-
'provenance',
|
|
851
|
-
'hooks',
|
|
852
|
-
'burnup',
|
|
853
|
-
'tool',
|
|
854
|
-
'worktree',
|
|
855
|
-
'session',
|
|
856
|
-
'parallel',
|
|
857
|
-
];
|
|
858
|
-
const similar = findSimilarCommand(commandName, validCommands);
|
|
846
|
+
const similar = findSimilarCommand(commandName, VALID_COMMANDS);
|
|
859
847
|
|
|
860
848
|
console.error(chalk.red(`\nUnknown command: ${commandName}`));
|
|
861
849
|
|
|
@@ -863,9 +851,7 @@ if (require.main === module) {
|
|
|
863
851
|
console.error(chalk.yellow(`\nDid you mean: caws ${similar}?`));
|
|
864
852
|
}
|
|
865
853
|
|
|
866
|
-
console.error(
|
|
867
|
-
chalk.yellow('Available commands: init, validate, scaffold, provenance, hooks, parallel')
|
|
868
|
-
);
|
|
854
|
+
console.error(chalk.yellow('Run: caws --help for the full command list'));
|
|
869
855
|
console.error(chalk.yellow('Try: caws --help for full command list'));
|
|
870
856
|
console.error(
|
|
871
857
|
chalk.blue(
|
|
@@ -192,7 +192,7 @@ function getParallelStatus() {
|
|
|
192
192
|
let commitCount = 0;
|
|
193
193
|
let dirty = false;
|
|
194
194
|
|
|
195
|
-
if (wt && wt.status === 'active') {
|
|
195
|
+
if (wt && (wt.status === 'active' || wt.status === 'fresh' || wt.status === 'merged')) {
|
|
196
196
|
try {
|
|
197
197
|
const log = execFileSync(
|
|
198
198
|
'git',
|
|
@@ -250,7 +250,7 @@ function detectFileConflicts(baseBranch, agentStatuses) {
|
|
|
250
250
|
const filesByAgent = {};
|
|
251
251
|
|
|
252
252
|
for (const agent of agentStatuses) {
|
|
253
|
-
if (agent.status !== 'active') continue;
|
|
253
|
+
if (agent.status !== 'active' && agent.status !== 'fresh' && agent.status !== 'merged') continue;
|
|
254
254
|
try {
|
|
255
255
|
const diff = execFileSync(
|
|
256
256
|
'git',
|
|
@@ -302,7 +302,7 @@ function mergeParallel(options = {}) {
|
|
|
302
302
|
const wt = worktrees.find((w) => w.name === a.name);
|
|
303
303
|
return wt ? { ...a, ...wt } : null;
|
|
304
304
|
})
|
|
305
|
-
.filter((a) => a && a.status === 'active');
|
|
305
|
+
.filter((a) => a && (a.status === 'active' || a.status === 'fresh' || a.status === 'merged'));
|
|
306
306
|
|
|
307
307
|
// Check for dirty worktrees
|
|
308
308
|
for (const agent of activeAgents) {
|