@paths.design/caws-cli 8.0.0 → 8.1.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/dist/budget-derivation.d.ts +74 -0
- package/dist/budget-derivation.d.ts.map +1 -0
- package/dist/cicd-optimizer.d.ts +142 -0
- package/dist/cicd-optimizer.d.ts.map +1 -0
- package/dist/commands/archive.d.ts +51 -0
- package/dist/commands/archive.d.ts.map +1 -0
- package/dist/commands/archive.js +114 -6
- package/dist/commands/burnup.d.ts +6 -0
- package/dist/commands/burnup.d.ts.map +1 -0
- package/dist/commands/burnup.js +109 -10
- package/dist/commands/diagnose.d.ts +52 -0
- package/dist/commands/diagnose.d.ts.map +1 -0
- package/dist/commands/diagnose.js +1 -1
- package/dist/commands/evaluate.d.ts +8 -0
- package/dist/commands/evaluate.d.ts.map +1 -0
- package/dist/commands/init.d.ts +5 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/iterate.d.ts +8 -0
- package/dist/commands/iterate.d.ts.map +1 -0
- package/dist/commands/mode.d.ts +24 -0
- package/dist/commands/mode.d.ts.map +1 -0
- package/dist/commands/mode.js +24 -14
- package/dist/commands/plan.d.ts +49 -0
- package/dist/commands/plan.d.ts.map +1 -0
- package/dist/commands/provenance.d.ts +32 -0
- package/dist/commands/provenance.d.ts.map +1 -0
- package/dist/commands/provenance.js +216 -93
- package/dist/commands/quality-gates.d.ts +6 -0
- package/dist/commands/quality-gates.d.ts.map +1 -0
- package/dist/commands/quality-gates.js +82 -3
- package/dist/commands/quality-monitor.d.ts +17 -0
- package/dist/commands/quality-monitor.d.ts.map +1 -0
- package/dist/commands/specs.d.ts +71 -0
- package/dist/commands/specs.d.ts.map +1 -0
- package/dist/commands/specs.js +184 -6
- package/dist/commands/status.d.ts +44 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +134 -10
- package/dist/commands/templates.d.ts +74 -0
- package/dist/commands/templates.d.ts.map +1 -0
- package/dist/commands/templates.js +2 -2
- package/dist/commands/tool.d.ts +13 -0
- package/dist/commands/tool.d.ts.map +1 -0
- package/dist/commands/troubleshoot.d.ts +8 -0
- package/dist/commands/troubleshoot.d.ts.map +1 -0
- package/dist/commands/tutorial.d.ts +55 -0
- package/dist/commands/tutorial.d.ts.map +1 -0
- package/dist/commands/validate.d.ts +15 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/waivers.d.ts +8 -0
- package/dist/commands/waivers.d.ts.map +1 -0
- package/dist/commands/workflow.d.ts +85 -0
- package/dist/commands/workflow.d.ts.map +1 -0
- package/dist/config/index.d.ts +29 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/modes.d.ts +225 -0
- package/dist/config/modes.d.ts.map +1 -0
- package/dist/constants/spec-types.d.ts +41 -0
- package/dist/constants/spec-types.d.ts.map +1 -0
- package/dist/error-handler.d.ts +164 -0
- package/dist/error-handler.d.ts.map +1 -0
- package/dist/error-handler.js +6 -98
- package/dist/generators/jest-config-generator.js +242 -0
- package/dist/generators/jest-config.d.ts +32 -0
- package/dist/generators/jest-config.d.ts.map +1 -0
- package/dist/generators/working-spec.d.ts +13 -0
- package/dist/generators/working-spec.d.ts.map +1 -0
- package/dist/index-new.d.ts +5 -0
- package/dist/index-new.d.ts.map +1 -0
- package/dist/index-new.js +317 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -7
- package/dist/index.js.backup +4711 -0
- package/dist/minimal-cli.d.ts +3 -0
- package/dist/minimal-cli.d.ts.map +1 -0
- package/dist/minimal-cli.js +3 -1
- package/dist/policy/PolicyManager.d.ts +104 -0
- package/dist/policy/PolicyManager.d.ts.map +1 -0
- package/dist/scaffold/claude-hooks.js +316 -0
- package/dist/scaffold/cursor-hooks.d.ts +7 -0
- package/dist/scaffold/cursor-hooks.d.ts.map +1 -0
- package/dist/scaffold/git-hooks.d.ts +38 -0
- package/dist/scaffold/git-hooks.d.ts.map +1 -0
- package/dist/scaffold/index.d.ts +15 -0
- package/dist/scaffold/index.d.ts.map +1 -0
- package/dist/scaffold/index.js +18 -0
- package/dist/spec/SpecFileManager.d.ts +146 -0
- package/dist/spec/SpecFileManager.d.ts.map +1 -0
- package/dist/templates/.claude/README.md +190 -0
- package/dist/templates/.claude/hooks/audit.sh +96 -0
- package/dist/templates/.claude/hooks/block-dangerous.sh +90 -0
- package/dist/templates/.claude/hooks/naming-check.sh +97 -0
- package/dist/templates/.claude/hooks/quality-check.sh +68 -0
- package/dist/templates/.claude/hooks/scan-secrets.sh +85 -0
- package/dist/templates/.claude/hooks/scope-guard.sh +105 -0
- package/dist/templates/.claude/hooks/validate-spec.sh +76 -0
- package/dist/templates/.claude/settings.json +95 -0
- package/dist/test-analysis.d.ts +182 -0
- package/dist/test-analysis.d.ts.map +1 -0
- package/dist/test-analysis.js +203 -10
- package/dist/tool-interface.d.ts +236 -0
- package/dist/tool-interface.d.ts.map +1 -0
- package/dist/tool-loader.d.ts +77 -0
- package/dist/tool-loader.d.ts.map +1 -0
- package/dist/tool-validator.d.ts +72 -0
- package/dist/tool-validator.d.ts.map +1 -0
- package/dist/utils/async-utils.d.ts +73 -0
- package/dist/utils/async-utils.d.ts.map +1 -0
- package/dist/utils/command-wrapper.d.ts +66 -0
- package/dist/utils/command-wrapper.d.ts.map +1 -0
- package/dist/utils/detection.d.ts +14 -0
- package/dist/utils/detection.d.ts.map +1 -0
- package/dist/utils/error-categories.js +210 -0
- package/dist/utils/finalization.d.ts +17 -0
- package/dist/utils/finalization.d.ts.map +1 -0
- package/dist/utils/git-lock.d.ts +13 -0
- package/dist/utils/git-lock.d.ts.map +1 -0
- package/dist/utils/gitignore-updater.d.ts +39 -0
- package/dist/utils/gitignore-updater.d.ts.map +1 -0
- package/dist/utils/project-analysis.d.ts +34 -0
- package/dist/utils/project-analysis.d.ts.map +1 -0
- package/dist/utils/promise-utils.d.ts +30 -0
- package/dist/utils/promise-utils.d.ts.map +1 -0
- package/dist/utils/quality-gates-utils.js +402 -0
- package/dist/utils/quality-gates.d.ts +49 -0
- package/dist/utils/quality-gates.d.ts.map +1 -0
- package/dist/utils/spec-resolver.d.ts +80 -0
- package/dist/utils/spec-resolver.d.ts.map +1 -0
- package/dist/utils/typescript-detector.d.ts +63 -0
- package/dist/utils/typescript-detector.d.ts.map +1 -0
- package/dist/utils/typescript-detector.js +36 -90
- package/dist/utils/yaml-validation.d.ts +32 -0
- package/dist/utils/yaml-validation.d.ts.map +1 -0
- package/dist/validation/spec-validation.d.ts +43 -0
- package/dist/validation/spec-validation.d.ts.map +1 -0
- package/dist/validation/spec-validation.js +59 -6
- package/dist/waivers-manager.d.ts +167 -0
- package/dist/waivers-manager.d.ts.map +1 -0
- package/package.json +5 -3
- package/templates/.claude/README.md +190 -0
- package/templates/.claude/hooks/audit.sh +96 -0
- package/templates/.claude/hooks/block-dangerous.sh +90 -0
- package/templates/.claude/hooks/naming-check.sh +97 -0
- package/templates/.claude/hooks/quality-check.sh +68 -0
- package/templates/.claude/hooks/scan-secrets.sh +85 -0
- package/templates/.claude/hooks/scope-guard.sh +105 -0
- package/templates/.claude/hooks/validate-spec.sh +76 -0
- package/templates/.claude/settings.json +95 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"minimal-cli.d.ts","sourceRoot":"","sources":["../src/minimal-cli.js"],"names":[],"mappings":""}
|
package/dist/minimal-cli.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @fileoverview Minimal CAWS CLI
|
|
4
|
+
* @fileoverview Minimal CAWS CLI for testing and development
|
|
5
|
+
* Provides a lightweight CLI structure with version and help commands
|
|
6
|
+
* for quick verification of CLI functionality.
|
|
5
7
|
* @author @darianrosebrook
|
|
6
8
|
*/
|
|
7
9
|
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy Manager - Handles policy loading with intelligent caching
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - TTL-based caching for performance
|
|
6
|
+
* - Graceful fallback to defaults when policy.yaml missing
|
|
7
|
+
* - Cache inspection and management API
|
|
8
|
+
* - Waiver validation and delta application
|
|
9
|
+
*/
|
|
10
|
+
export class PolicyManager {
|
|
11
|
+
constructor(options?: {});
|
|
12
|
+
enableCaching: any;
|
|
13
|
+
cacheTTL: any;
|
|
14
|
+
policyCache: Map<any, any>;
|
|
15
|
+
/**
|
|
16
|
+
* Load CAWS policy from policy.yaml with caching
|
|
17
|
+
*
|
|
18
|
+
* @param {string} projectRoot - Project root directory
|
|
19
|
+
* @param {Object} options - Loading options
|
|
20
|
+
* @param {boolean} options.useCache - Use cache if available (default: true)
|
|
21
|
+
* @param {number} options.cacheTTL - Cache TTL override in milliseconds
|
|
22
|
+
* @returns {Promise<Object>} Policy object
|
|
23
|
+
*/
|
|
24
|
+
loadPolicy(projectRoot: string, options?: {
|
|
25
|
+
useCache: boolean;
|
|
26
|
+
cacheTTL: number;
|
|
27
|
+
}): Promise<any>;
|
|
28
|
+
/**
|
|
29
|
+
* Load a waiver document by ID
|
|
30
|
+
*
|
|
31
|
+
* @param {string} waiverId - Waiver ID (e.g., WV-0001)
|
|
32
|
+
* @param {string} projectRoot - Project root directory
|
|
33
|
+
* @returns {Promise<Object|null>} Waiver document or null if not found
|
|
34
|
+
*/
|
|
35
|
+
loadWaiver(waiverId: string, projectRoot: string): Promise<any | null>;
|
|
36
|
+
/**
|
|
37
|
+
* Check if a waiver is currently valid
|
|
38
|
+
*
|
|
39
|
+
* @param {Object} waiver - Waiver document
|
|
40
|
+
* @returns {boolean} True if waiver is valid and active
|
|
41
|
+
*/
|
|
42
|
+
isWaiverValid(waiver: any): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Apply waivers to baseline budget
|
|
45
|
+
*
|
|
46
|
+
* @param {Object} baseline - Baseline budget from policy
|
|
47
|
+
* @param {string[]} waiverIds - Array of waiver IDs to apply
|
|
48
|
+
* @param {string} projectRoot - Project root directory
|
|
49
|
+
* @returns {Promise<Object>} Effective budget with waivers applied
|
|
50
|
+
*/
|
|
51
|
+
applyWaivers(baseline: any, waiverIds: string[], projectRoot: string): Promise<any>;
|
|
52
|
+
/**
|
|
53
|
+
* Validate policy structure
|
|
54
|
+
*
|
|
55
|
+
* @param {Object} policy - Policy to validate
|
|
56
|
+
* @throws {Error} If policy is invalid
|
|
57
|
+
*/
|
|
58
|
+
validatePolicy(policy: any): void;
|
|
59
|
+
/**
|
|
60
|
+
* Get default CAWS policy
|
|
61
|
+
*
|
|
62
|
+
* Returns sensible defaults when policy.yaml doesn't exist.
|
|
63
|
+
*
|
|
64
|
+
* @returns {Object} Default policy configuration
|
|
65
|
+
*/
|
|
66
|
+
getDefaultPolicy(): any;
|
|
67
|
+
/**
|
|
68
|
+
* Clear policy cache
|
|
69
|
+
*
|
|
70
|
+
* @param {string} [projectRoot] - Specific project to clear, or all if omitted
|
|
71
|
+
*/
|
|
72
|
+
clearCache(projectRoot?: string): void;
|
|
73
|
+
/**
|
|
74
|
+
* Get cache status for a project
|
|
75
|
+
*
|
|
76
|
+
* @param {string} projectRoot - Project root directory
|
|
77
|
+
* @returns {Object} Cache status information
|
|
78
|
+
*/
|
|
79
|
+
getCacheStatus(projectRoot: string): any;
|
|
80
|
+
/**
|
|
81
|
+
* Reload policy from disk (bypassing cache)
|
|
82
|
+
*
|
|
83
|
+
* @param {string} projectRoot - Project root directory
|
|
84
|
+
* @returns {Promise<Object>} Fresh policy
|
|
85
|
+
*/
|
|
86
|
+
reloadPolicy(projectRoot: string): Promise<any>;
|
|
87
|
+
/**
|
|
88
|
+
* Get all cached projects
|
|
89
|
+
*
|
|
90
|
+
* @returns {string[]} Array of project roots with cached policies
|
|
91
|
+
*/
|
|
92
|
+
getCachedProjects(): string[];
|
|
93
|
+
/**
|
|
94
|
+
* Get cache statistics
|
|
95
|
+
*
|
|
96
|
+
* @returns {Object} Cache statistics
|
|
97
|
+
*/
|
|
98
|
+
getCacheStats(): any;
|
|
99
|
+
}
|
|
100
|
+
export const defaultPolicyManager: PolicyManager;
|
|
101
|
+
export declare function loadPolicy(projectRoot: any, options: any): Promise<any>;
|
|
102
|
+
export declare function clearCache(projectRoot: any): void;
|
|
103
|
+
export declare function getCacheStatus(projectRoot: any): any;
|
|
104
|
+
//# sourceMappingURL=PolicyManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PolicyManager.d.ts","sourceRoot":"","sources":["../../src/policy/PolicyManager.js"],"names":[],"mappings":"AAWA;;;;;;;;GAQG;AACH;IACE,0BAIC;IAHC,mBAAkD;IAClD,cAA0C;IAC1C,2BAA4B;IAG9B;;;;;;;;OAQG;IACH,wBANW,MAAM,YAEd;QAAyB,QAAQ,EAAzB,OAAO;QACS,QAAQ,EAAxB,MAAM;KACd,GAAU,OAAO,KAAQ,CAuG3B;IAED;;;;;;OAMG;IACH,qBAJW,MAAM,eACN,MAAM,GACJ,OAAO,CAAC,MAAO,IAAI,CAAC,CAchC;IAED;;;;;OAKG;IACH,4BAFa,OAAO,CA2BnB;IAED;;;;;;;OAOG;IACH,uCAJW,MAAM,EAAE,eACR,MAAM,GACJ,OAAO,KAAQ,CA2B3B;IAED;;;;;OAKG;IACH,kCA8BC;IAED;;;;;;OAMG;IACH,wBAoDC;IAED;;;;OAIG;IACH,yBAFW,MAAM,QAQhB;IAED;;;;;OAKG;IACH,4BAHW,MAAM,OAmBhB;IAED;;;;;OAKG;IACH,0BAHW,MAAM,GACJ,OAAO,KAAQ,CAK3B;IAED;;;;OAIG;IACH,qBAFa,MAAM,EAAE,CAIpB;IAED;;;;OAIG;IACH,qBA2BC;CACF;AAGD,iDAAiD;AAOnC,iFAA+E;AAC/E,2DAA6D;AACzD,8DAAiE"}
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Claude Code Hooks Scaffolding
|
|
3
|
+
* Functions for setting up Claude Code hooks for CAWS projects
|
|
4
|
+
* @author @darianrosebrook
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs-extra');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const chalk = require('chalk');
|
|
10
|
+
|
|
11
|
+
// Import detection utilities
|
|
12
|
+
const { detectCAWSSetup, findPackageRoot } = require('../utils/detection');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Scaffold Claude Code hooks for a CAWS project
|
|
16
|
+
* Creates .claude/settings.json with hooks and .claude/hooks/ directory with scripts
|
|
17
|
+
*
|
|
18
|
+
* @param {string} projectDir - Project directory path
|
|
19
|
+
* @param {string[]} levels - Hook levels to enable: 'safety', 'quality', 'scope', 'audit'
|
|
20
|
+
*/
|
|
21
|
+
async function scaffoldClaudeHooks(projectDir, levels = ['safety', 'quality', 'scope', 'audit']) {
|
|
22
|
+
try {
|
|
23
|
+
const claudeDir = path.join(projectDir, '.claude');
|
|
24
|
+
const claudeHooksDir = path.join(claudeDir, 'hooks');
|
|
25
|
+
|
|
26
|
+
// Create .claude directory structure
|
|
27
|
+
await fs.ensureDir(claudeDir);
|
|
28
|
+
await fs.ensureDir(claudeHooksDir);
|
|
29
|
+
|
|
30
|
+
// Determine template directory - prefer bundled templates
|
|
31
|
+
const setup = detectCAWSSetup(projectDir);
|
|
32
|
+
|
|
33
|
+
// Find package root using shared utility
|
|
34
|
+
const packageRoot = findPackageRoot(__dirname);
|
|
35
|
+
|
|
36
|
+
// Try templates relative to package root first (works in both dev and global install)
|
|
37
|
+
const bundledTemplateDir = path.join(packageRoot, 'templates');
|
|
38
|
+
const fallbackTemplateDir = path.join(__dirname, '../../templates');
|
|
39
|
+
const templateDir = fs.existsSync(bundledTemplateDir)
|
|
40
|
+
? bundledTemplateDir
|
|
41
|
+
: fs.existsSync(fallbackTemplateDir)
|
|
42
|
+
? fallbackTemplateDir
|
|
43
|
+
: setup.templateDir || path.resolve(__dirname, '../templates');
|
|
44
|
+
|
|
45
|
+
const claudeTemplateDir = path.join(templateDir, '.claude');
|
|
46
|
+
const claudeHooksTemplateDir = path.join(claudeTemplateDir, 'hooks');
|
|
47
|
+
|
|
48
|
+
if (!fs.existsSync(claudeTemplateDir)) {
|
|
49
|
+
console.warn(chalk.yellow('⚠️ Claude Code hooks templates not found'));
|
|
50
|
+
console.warn(chalk.blue('💡 Skipping Claude Code hooks setup'));
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Map levels to hook scripts
|
|
55
|
+
const hookMapping = {
|
|
56
|
+
safety: ['block-dangerous.sh', 'scan-secrets.sh'],
|
|
57
|
+
quality: ['quality-check.sh', 'validate-spec.sh'],
|
|
58
|
+
scope: ['scope-guard.sh', 'naming-check.sh'],
|
|
59
|
+
audit: ['audit.sh'],
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// Determine which hooks to enable
|
|
63
|
+
const enabledHooks = new Set();
|
|
64
|
+
levels.forEach((level) => {
|
|
65
|
+
const hooks = hookMapping[level] || [];
|
|
66
|
+
hooks.forEach((hook) => enabledHooks.add(hook));
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Always enable audit.sh if any hooks are enabled
|
|
70
|
+
if (enabledHooks.size > 0) {
|
|
71
|
+
enabledHooks.add('audit.sh');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Copy enabled hook scripts
|
|
75
|
+
const allHookScripts = [
|
|
76
|
+
'audit.sh',
|
|
77
|
+
'validate-spec.sh',
|
|
78
|
+
'quality-check.sh',
|
|
79
|
+
'scan-secrets.sh',
|
|
80
|
+
'block-dangerous.sh',
|
|
81
|
+
'scope-guard.sh',
|
|
82
|
+
'naming-check.sh',
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
for (const script of allHookScripts) {
|
|
86
|
+
if (enabledHooks.has(script)) {
|
|
87
|
+
const sourcePath = path.join(claudeHooksTemplateDir, script);
|
|
88
|
+
const destPath = path.join(claudeHooksDir, script);
|
|
89
|
+
|
|
90
|
+
if (fs.existsSync(sourcePath)) {
|
|
91
|
+
await fs.copy(sourcePath, destPath);
|
|
92
|
+
// Make executable
|
|
93
|
+
await fs.chmod(destPath, 0o755);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Generate settings.json with hooks configuration
|
|
99
|
+
const settings = generateClaudeSettings(levels, enabledHooks);
|
|
100
|
+
|
|
101
|
+
// Check for existing settings and merge
|
|
102
|
+
const settingsPath = path.join(claudeDir, 'settings.json');
|
|
103
|
+
if (fs.existsSync(settingsPath)) {
|
|
104
|
+
try {
|
|
105
|
+
const existingSettings = await fs.readJSON(settingsPath);
|
|
106
|
+
// Merge hooks, preserving existing non-hook settings
|
|
107
|
+
settings.hooks = {
|
|
108
|
+
...existingSettings.hooks,
|
|
109
|
+
...settings.hooks,
|
|
110
|
+
};
|
|
111
|
+
// Preserve other settings
|
|
112
|
+
Object.keys(existingSettings).forEach((key) => {
|
|
113
|
+
if (key !== 'hooks' && !(key in settings)) {
|
|
114
|
+
settings[key] = existingSettings[key];
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
} catch (error) {
|
|
118
|
+
console.warn(chalk.yellow('⚠️ Could not merge existing settings:'), error.message);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Write settings.json
|
|
123
|
+
await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2));
|
|
124
|
+
|
|
125
|
+
// Copy README if it exists
|
|
126
|
+
const readmePath = path.join(claudeTemplateDir, 'README.md');
|
|
127
|
+
if (fs.existsSync(readmePath)) {
|
|
128
|
+
await fs.copy(readmePath, path.join(claudeDir, 'README.md'));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
console.log(chalk.green('✅ Claude Code hooks configured'));
|
|
132
|
+
console.log(chalk.gray(` Enabled: ${levels.join(', ')}`));
|
|
133
|
+
console.log(
|
|
134
|
+
chalk.gray(` Scripts: ${Array.from(enabledHooks).length} hook scripts installed`)
|
|
135
|
+
);
|
|
136
|
+
console.log(chalk.blue('💡 Hooks will activate on next Claude Code session'));
|
|
137
|
+
} catch (error) {
|
|
138
|
+
console.error(chalk.yellow('⚠️ Failed to setup Claude Code hooks:'), error.message);
|
|
139
|
+
console.log(chalk.blue('💡 You can manually copy .claude/ directory later'));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Generate Claude Code settings with hooks configuration
|
|
145
|
+
* @param {string[]} levels - Enabled hook levels
|
|
146
|
+
* @param {Set<string>} enabledHooks - Set of enabled hook script names
|
|
147
|
+
* @returns {Object} Settings object for settings.json
|
|
148
|
+
*/
|
|
149
|
+
function generateClaudeSettings(levels, _enabledHooks) {
|
|
150
|
+
const settings = {
|
|
151
|
+
hooks: {},
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
// Build hooks configuration based on enabled levels
|
|
155
|
+
// Claude Code uses different event names and matcher patterns
|
|
156
|
+
|
|
157
|
+
if (levels.includes('safety')) {
|
|
158
|
+
// Block dangerous bash commands
|
|
159
|
+
settings.hooks.PreToolUse = settings.hooks.PreToolUse || [];
|
|
160
|
+
settings.hooks.PreToolUse.push({
|
|
161
|
+
matcher: 'Bash',
|
|
162
|
+
hooks: [
|
|
163
|
+
{
|
|
164
|
+
type: 'command',
|
|
165
|
+
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/block-dangerous.sh',
|
|
166
|
+
timeout: 10,
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Scan for secrets on file read
|
|
172
|
+
settings.hooks.PreToolUse.push({
|
|
173
|
+
matcher: 'Read',
|
|
174
|
+
hooks: [
|
|
175
|
+
{
|
|
176
|
+
type: 'command',
|
|
177
|
+
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/scan-secrets.sh',
|
|
178
|
+
timeout: 10,
|
|
179
|
+
},
|
|
180
|
+
],
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (levels.includes('quality')) {
|
|
185
|
+
// Run quality checks after file edits
|
|
186
|
+
settings.hooks.PostToolUse = settings.hooks.PostToolUse || [];
|
|
187
|
+
settings.hooks.PostToolUse.push({
|
|
188
|
+
matcher: 'Write|Edit',
|
|
189
|
+
hooks: [
|
|
190
|
+
{
|
|
191
|
+
type: 'command',
|
|
192
|
+
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/quality-check.sh',
|
|
193
|
+
timeout: 30,
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
type: 'command',
|
|
197
|
+
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/validate-spec.sh',
|
|
198
|
+
timeout: 15,
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (levels.includes('scope')) {
|
|
205
|
+
// Scope guard before file writes
|
|
206
|
+
settings.hooks.PreToolUse = settings.hooks.PreToolUse || [];
|
|
207
|
+
settings.hooks.PreToolUse.push({
|
|
208
|
+
matcher: 'Write|Edit',
|
|
209
|
+
hooks: [
|
|
210
|
+
{
|
|
211
|
+
type: 'command',
|
|
212
|
+
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/scope-guard.sh',
|
|
213
|
+
timeout: 10,
|
|
214
|
+
},
|
|
215
|
+
],
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
// Naming check after edits
|
|
219
|
+
settings.hooks.PostToolUse = settings.hooks.PostToolUse || [];
|
|
220
|
+
settings.hooks.PostToolUse.push({
|
|
221
|
+
matcher: 'Write|Edit',
|
|
222
|
+
hooks: [
|
|
223
|
+
{
|
|
224
|
+
type: 'command',
|
|
225
|
+
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/naming-check.sh',
|
|
226
|
+
timeout: 10,
|
|
227
|
+
},
|
|
228
|
+
],
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (levels.includes('audit')) {
|
|
233
|
+
// Session audit logging
|
|
234
|
+
settings.hooks.SessionStart = settings.hooks.SessionStart || [];
|
|
235
|
+
settings.hooks.SessionStart.push({
|
|
236
|
+
hooks: [
|
|
237
|
+
{
|
|
238
|
+
type: 'command',
|
|
239
|
+
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/audit.sh session-start',
|
|
240
|
+
timeout: 5,
|
|
241
|
+
},
|
|
242
|
+
],
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
settings.hooks.Stop = settings.hooks.Stop || [];
|
|
246
|
+
settings.hooks.Stop.push({
|
|
247
|
+
hooks: [
|
|
248
|
+
{
|
|
249
|
+
type: 'command',
|
|
250
|
+
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/audit.sh stop',
|
|
251
|
+
timeout: 5,
|
|
252
|
+
},
|
|
253
|
+
],
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
// Audit tool usage
|
|
257
|
+
settings.hooks.PostToolUse = settings.hooks.PostToolUse || [];
|
|
258
|
+
settings.hooks.PostToolUse.push({
|
|
259
|
+
matcher: 'Write|Edit|Bash',
|
|
260
|
+
hooks: [
|
|
261
|
+
{
|
|
262
|
+
type: 'command',
|
|
263
|
+
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/audit.sh tool-use',
|
|
264
|
+
timeout: 5,
|
|
265
|
+
},
|
|
266
|
+
],
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return settings;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Check if Claude Code hooks are already configured
|
|
275
|
+
* @param {string} projectDir - Project directory
|
|
276
|
+
* @returns {boolean} True if hooks are configured
|
|
277
|
+
*/
|
|
278
|
+
function hasClaudeHooks(projectDir) {
|
|
279
|
+
const settingsPath = path.join(projectDir, '.claude', 'settings.json');
|
|
280
|
+
if (!fs.existsSync(settingsPath)) {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
try {
|
|
285
|
+
const settings = fs.readJSONSync(settingsPath);
|
|
286
|
+
return settings.hooks && Object.keys(settings.hooks).length > 0;
|
|
287
|
+
} catch {
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* List configured Claude Code hooks
|
|
294
|
+
* @param {string} projectDir - Project directory
|
|
295
|
+
* @returns {Object} Hook configuration or null
|
|
296
|
+
*/
|
|
297
|
+
function getClaudeHooksConfig(projectDir) {
|
|
298
|
+
const settingsPath = path.join(projectDir, '.claude', 'settings.json');
|
|
299
|
+
if (!fs.existsSync(settingsPath)) {
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
try {
|
|
304
|
+
const settings = fs.readJSONSync(settingsPath);
|
|
305
|
+
return settings.hooks || null;
|
|
306
|
+
} catch {
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
module.exports = {
|
|
312
|
+
scaffoldClaudeHooks,
|
|
313
|
+
generateClaudeSettings,
|
|
314
|
+
hasClaudeHooks,
|
|
315
|
+
getClaudeHooksConfig,
|
|
316
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scaffold Cursor hooks for a CAWS project
|
|
3
|
+
* @param {string} projectDir - Project directory path
|
|
4
|
+
* @param {string[]} levels - Hook levels to enable
|
|
5
|
+
*/
|
|
6
|
+
export function scaffoldCursorHooks(projectDir: string, levels?: string[]): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=cursor-hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor-hooks.d.ts","sourceRoot":"","sources":["../../src/scaffold/cursor-hooks.js"],"names":[],"mappings":"AAaA;;;;GAIG;AACH,gDAHW,MAAM,WACN,MAAM,EAAE,iBA6JlB"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scaffold git hooks for CAWS provenance tracking
|
|
3
|
+
* @param {string} projectDir - Project directory path
|
|
4
|
+
* @param {Object} options - Hook options
|
|
5
|
+
*/
|
|
6
|
+
export function scaffoldGitHooks(projectDir: string, options?: any): Promise<{
|
|
7
|
+
added: number;
|
|
8
|
+
skipped: number;
|
|
9
|
+
}>;
|
|
10
|
+
/**
|
|
11
|
+
* Remove CAWS git hooks
|
|
12
|
+
* @param {string} projectDir - Project directory path
|
|
13
|
+
*/
|
|
14
|
+
export function removeGitHooks(projectDir: string): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Check git hooks status
|
|
17
|
+
* @param {string} projectDir - Project directory path
|
|
18
|
+
*/
|
|
19
|
+
export function checkGitHooksStatus(projectDir: string): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Generate pre-push hook content
|
|
22
|
+
* Blocks --no-verify to enforce quality gates before pushing
|
|
23
|
+
*/
|
|
24
|
+
export function generatePrePushHook(): string;
|
|
25
|
+
/**
|
|
26
|
+
* Generate pre-commit hook content with staged file quality gates
|
|
27
|
+
* Implements fallback chain: Node script → CLI → Python scripts → Skip gracefully
|
|
28
|
+
*/
|
|
29
|
+
export function generatePreCommitHook(options: any): string;
|
|
30
|
+
/**
|
|
31
|
+
* Generate post-commit hook content
|
|
32
|
+
*/
|
|
33
|
+
export function generatePostCommitHook(): string;
|
|
34
|
+
/**
|
|
35
|
+
* Generate commit-msg hook content
|
|
36
|
+
*/
|
|
37
|
+
export function generateCommitMsgHook(): string;
|
|
38
|
+
//# sourceMappingURL=git-hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-hooks.d.ts","sourceRoot":"","sources":["../../src/scaffold/git-hooks.js"],"names":[],"mappings":"AAUA;;;;GAIG;AACH,6CAHW,MAAM;;;GAwGhB;AA4kBD;;;GAGG;AACH,2CAFW,MAAM,iBAkChB;AAED;;;GAGG;AACH,gDAFW,MAAM,iBAgDhB;AA9VD;;;GAGG;AACH,8CAqNC;AA7hBD;;;GAGG;AACH,4DAsRC;AAED;;GAEG;AACH,iDAmCC;AA6ND;;GAEG;AACH,gDAsCC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scaffold existing project with CAWS components
|
|
3
|
+
* @param {Object} options - Scaffold options
|
|
4
|
+
*/
|
|
5
|
+
export function scaffoldProject(options: any): Promise<void>;
|
|
6
|
+
export function scaffoldIDEIntegrations(targetDir: any, options: any): Promise<{
|
|
7
|
+
added: number;
|
|
8
|
+
skipped: number;
|
|
9
|
+
}>;
|
|
10
|
+
/**
|
|
11
|
+
* Set dependencies for scaffold module
|
|
12
|
+
* @param {Object} deps - Dependencies object
|
|
13
|
+
*/
|
|
14
|
+
export function setScaffoldDependencies(deps: any): void;
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scaffold/index.js"],"names":[],"mappings":"AA6LA;;;GAGG;AACH,6DA6jBC;AA3sBD;;;GA2HC;AAMD;;;GAGG;AACH,yDAGC"}
|
package/dist/scaffold/index.js
CHANGED
|
@@ -16,6 +16,9 @@ const { detectsPublishing } = require('../utils/project-analysis');
|
|
|
16
16
|
const { scaffoldGitHooks } = require('./git-hooks');
|
|
17
17
|
const { updateGitignore } = require('../utils/gitignore-updater');
|
|
18
18
|
|
|
19
|
+
// Import Claude Code hooks scaffolding
|
|
20
|
+
const { scaffoldClaudeHooks } = require('./claude-hooks');
|
|
21
|
+
|
|
19
22
|
// CLI version from package.json
|
|
20
23
|
const CLI_VERSION = require('../../package.json').version;
|
|
21
24
|
|
|
@@ -120,8 +123,22 @@ async function scaffoldIDEIntegrations(targetDir, options) {
|
|
|
120
123
|
dest: '.cursor/README.md',
|
|
121
124
|
desc: 'Cursor integration documentation',
|
|
122
125
|
},
|
|
126
|
+
|
|
127
|
+
// Claude Code hooks
|
|
128
|
+
{
|
|
129
|
+
src: '.claude/README.md',
|
|
130
|
+
dest: '.claude/README.md',
|
|
131
|
+
desc: 'Claude Code integration documentation',
|
|
132
|
+
},
|
|
123
133
|
];
|
|
124
134
|
|
|
135
|
+
// Setup Claude Code hooks
|
|
136
|
+
try {
|
|
137
|
+
await scaffoldClaudeHooks(targetDir, ['safety', 'quality', 'scope', 'audit']);
|
|
138
|
+
} catch (error) {
|
|
139
|
+
console.log(chalk.yellow(`⚠️ Claude Code hooks setup failed: ${error.message}`));
|
|
140
|
+
}
|
|
141
|
+
|
|
125
142
|
for (const template of ideTemplates) {
|
|
126
143
|
const srcPath = path.join(templateDir, template.src);
|
|
127
144
|
const destPath = path.join(targetDir, template.dest);
|
|
@@ -769,5 +786,6 @@ async function scaffoldProject(options) {
|
|
|
769
786
|
module.exports = {
|
|
770
787
|
scaffoldProject,
|
|
771
788
|
scaffoldIDEIntegrations,
|
|
789
|
+
scaffoldClaudeHooks,
|
|
772
790
|
setScaffoldDependencies,
|
|
773
791
|
};
|