@paths.design/caws-cli 9.3.2 → 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 +50 -25
- 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 +130 -151
- 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 +2 -2
- package/dist/templates/.claude/hooks/worktree-write-guard.sh +1 -1
- 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 +390 -93
- 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 +2 -2
- package/templates/.claude/hooks/worktree-write-guard.sh +1 -1
- 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,13 +369,15 @@ 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
|
|
|
398
375
|
worktreeCmd
|
|
399
376
|
.command('repair')
|
|
400
377
|
.description('Reconcile registry with git and filesystem state')
|
|
401
378
|
.option('--dry-run', 'Report only, do not persist changes', false)
|
|
402
|
-
.option('--prune', 'Remove destroyed
|
|
379
|
+
.option('--prune', 'Remove destroyed, stale-merged, and missing entries', false)
|
|
380
|
+
.option('--force', 'Allow pruning entries owned by other sessions', false)
|
|
403
381
|
.action((options) => worktreeCommand('repair', options));
|
|
404
382
|
|
|
405
383
|
// Session command group
|
|
@@ -525,6 +503,14 @@ program
|
|
|
525
503
|
.option('-v, --verbose', 'Show detailed error information', false)
|
|
526
504
|
.action(iterateCommand);
|
|
527
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
|
+
|
|
528
514
|
// Waivers command group
|
|
529
515
|
const waiversCmd = program.command('waivers').description('Manage CAWS quality gate waivers');
|
|
530
516
|
|
|
@@ -567,7 +553,7 @@ waiversCmd
|
|
|
567
553
|
.action((id, options) => waiversCommand('revoke', { ...options, id }));
|
|
568
554
|
|
|
569
555
|
// Workflow command group
|
|
570
|
-
|
|
556
|
+
program
|
|
571
557
|
.command('workflow <type>')
|
|
572
558
|
.description('Get workflow-specific guidance')
|
|
573
559
|
.option('--spec-id <id>', 'Feature-specific spec ID (e.g., user-auth)')
|
|
@@ -603,7 +589,9 @@ program
|
|
|
603
589
|
.command('test-analysis <subcommand> [options...]')
|
|
604
590
|
.description('Statistical analysis for budget prediction')
|
|
605
591
|
.option('--spec-id <id>', 'Feature-specific spec ID (e.g., user-auth)')
|
|
606
|
-
.action(
|
|
592
|
+
.action((subcommand, optionArgs, command) => {
|
|
593
|
+
testAnalysisCommand(subcommand, optionArgs, command.opts());
|
|
594
|
+
});
|
|
607
595
|
|
|
608
596
|
// Provenance command group
|
|
609
597
|
const provenanceCmd = program.command('provenance').description('Manage CAWS provenance tracking');
|
|
@@ -613,6 +601,8 @@ provenanceCmd
|
|
|
613
601
|
.command('update')
|
|
614
602
|
.description('Add new commit to provenance chain')
|
|
615
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)')
|
|
616
606
|
.option('-m, --message <msg>', 'Commit message')
|
|
617
607
|
.option('-a, --author <info>', 'Author information')
|
|
618
608
|
.option('-q, --quiet', 'Suppress output')
|
|
@@ -649,6 +639,8 @@ provenanceCmd
|
|
|
649
639
|
provenanceCmd
|
|
650
640
|
.command('init')
|
|
651
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)')
|
|
652
644
|
.option('-o, --output <path>', 'Output path for provenance files', '.caws/provenance')
|
|
653
645
|
.option('--cursor-api <url>', 'Cursor tracking API endpoint')
|
|
654
646
|
.option('--cursor-key <key>', 'Cursor API key')
|
|
@@ -725,6 +717,36 @@ program.configureHelp({
|
|
|
725
717
|
showError: () => {}, // Suppress default error display
|
|
726
718
|
});
|
|
727
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
|
+
|
|
728
750
|
program.exitOverride((err) => {
|
|
729
751
|
// Handle help and version requests gracefully
|
|
730
752
|
if (
|
|
@@ -739,34 +761,7 @@ program.exitOverride((err) => {
|
|
|
739
761
|
|
|
740
762
|
// Check for unknown command
|
|
741
763
|
if (err.code === 'commander.unknownCommand') {
|
|
742
|
-
const
|
|
743
|
-
'init',
|
|
744
|
-
'validate',
|
|
745
|
-
'scaffold',
|
|
746
|
-
'status',
|
|
747
|
-
'archive',
|
|
748
|
-
'specs',
|
|
749
|
-
'mode',
|
|
750
|
-
'tutorial',
|
|
751
|
-
'plan',
|
|
752
|
-
'templates',
|
|
753
|
-
'diagnose',
|
|
754
|
-
'evaluate',
|
|
755
|
-
'iterate',
|
|
756
|
-
'waivers',
|
|
757
|
-
'workflow',
|
|
758
|
-
'quality-monitor',
|
|
759
|
-
'troubleshoot',
|
|
760
|
-
'provenance',
|
|
761
|
-
'hooks',
|
|
762
|
-
'burnup',
|
|
763
|
-
'tool',
|
|
764
|
-
'worktree',
|
|
765
|
-
'session',
|
|
766
|
-
'parallel',
|
|
767
|
-
'verify-acs',
|
|
768
|
-
];
|
|
769
|
-
const similar = findSimilarCommand(commandName, validCommands);
|
|
764
|
+
const similar = findSimilarCommand(commandName, VALID_COMMANDS);
|
|
770
765
|
|
|
771
766
|
console.error(chalk.red(`\nUnknown command: ${commandName}`));
|
|
772
767
|
|
|
@@ -774,9 +769,7 @@ program.exitOverride((err) => {
|
|
|
774
769
|
console.error(chalk.yellow(`\nDid you mean: caws ${similar}?`));
|
|
775
770
|
}
|
|
776
771
|
|
|
777
|
-
console.error(
|
|
778
|
-
chalk.yellow('Available commands: init, validate, scaffold, provenance, hooks')
|
|
779
|
-
);
|
|
772
|
+
console.error(chalk.yellow('Run: caws --help for the full command list'));
|
|
780
773
|
console.error(chalk.yellow('Try: caws --help for full command list'));
|
|
781
774
|
console.error(
|
|
782
775
|
chalk.blue(
|
|
@@ -821,6 +814,12 @@ program.exitOverride((err) => {
|
|
|
821
814
|
process.exit(1);
|
|
822
815
|
});
|
|
823
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
|
+
|
|
824
823
|
// Parse and run
|
|
825
824
|
if (require.main === module) {
|
|
826
825
|
try {
|
|
@@ -844,25 +843,7 @@ if (require.main === module) {
|
|
|
844
843
|
|
|
845
844
|
// Check for unknown command
|
|
846
845
|
if (error.code === 'commander.unknownCommand') {
|
|
847
|
-
const
|
|
848
|
-
'init',
|
|
849
|
-
'validate',
|
|
850
|
-
'scaffold',
|
|
851
|
-
'status',
|
|
852
|
-
'archive',
|
|
853
|
-
'specs',
|
|
854
|
-
'mode',
|
|
855
|
-
'tutorial',
|
|
856
|
-
'plan',
|
|
857
|
-
'provenance',
|
|
858
|
-
'hooks',
|
|
859
|
-
'burnup',
|
|
860
|
-
'tool',
|
|
861
|
-
'worktree',
|
|
862
|
-
'session',
|
|
863
|
-
'parallel',
|
|
864
|
-
];
|
|
865
|
-
const similar = findSimilarCommand(commandName, validCommands);
|
|
846
|
+
const similar = findSimilarCommand(commandName, VALID_COMMANDS);
|
|
866
847
|
|
|
867
848
|
console.error(chalk.red(`\nUnknown command: ${commandName}`));
|
|
868
849
|
|
|
@@ -870,9 +851,7 @@ if (require.main === module) {
|
|
|
870
851
|
console.error(chalk.yellow(`\nDid you mean: caws ${similar}?`));
|
|
871
852
|
}
|
|
872
853
|
|
|
873
|
-
console.error(
|
|
874
|
-
chalk.yellow('Available commands: init, validate, scaffold, provenance, hooks, parallel')
|
|
875
|
-
);
|
|
854
|
+
console.error(chalk.yellow('Run: caws --help for the full command list'));
|
|
876
855
|
console.error(chalk.yellow('Try: caws --help for full command list'));
|
|
877
856
|
console.error(
|
|
878
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) {
|