@paths.design/caws-cli 7.0.1 → 7.0.3

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.
Files changed (121) hide show
  1. package/dist/budget-derivation.js +5 -4
  2. package/dist/commands/diagnose.js +26 -20
  3. package/dist/commands/init.js +72 -5
  4. package/dist/commands/specs.js +40 -1
  5. package/dist/commands/status.js +2 -2
  6. package/dist/commands/templates.js +10 -0
  7. package/dist/commands/tool.js +2 -3
  8. package/dist/commands/validate.js +12 -0
  9. package/dist/config/index.js +17 -8
  10. package/dist/generators/working-spec.js +42 -9
  11. package/dist/index.js +3 -1
  12. package/dist/scaffold/cursor-hooks.js +10 -2
  13. package/dist/scaffold/git-hooks.js +189 -32
  14. package/dist/scaffold/index.js +105 -17
  15. package/dist/templates/.caws/tools/README.md +20 -0
  16. package/dist/templates/.cursor/README.md +311 -0
  17. package/dist/templates/.cursor/hooks/audit.sh +55 -0
  18. package/dist/templates/.cursor/hooks/block-dangerous.sh +83 -0
  19. package/dist/templates/.cursor/hooks/caws-quality-check.sh +52 -0
  20. package/dist/templates/.cursor/hooks/caws-scope-guard.sh +130 -0
  21. package/dist/templates/.cursor/hooks/caws-tool-validation.sh +121 -0
  22. package/dist/templates/.cursor/hooks/format.sh +38 -0
  23. package/dist/templates/.cursor/hooks/naming-check.sh +64 -0
  24. package/dist/templates/.cursor/hooks/scan-secrets.sh +46 -0
  25. package/dist/templates/.cursor/hooks/scope-guard.sh +52 -0
  26. package/dist/templates/.cursor/hooks/validate-spec.sh +83 -0
  27. package/dist/templates/.cursor/hooks.json +59 -0
  28. package/dist/templates/.cursor/rules/00-claims-verification.mdc +144 -0
  29. package/dist/templates/.cursor/rules/01-working-style.mdc +50 -0
  30. package/dist/templates/.cursor/rules/02-quality-gates.mdc +370 -0
  31. package/dist/templates/.cursor/rules/03-naming-and-refactor.mdc +33 -0
  32. package/dist/templates/.cursor/rules/04-logging-language-style.mdc +23 -0
  33. package/dist/templates/.cursor/rules/05-safe-defaults-guards.mdc +23 -0
  34. package/dist/templates/.cursor/rules/06-typescript-conventions.mdc +36 -0
  35. package/dist/templates/.cursor/rules/07-process-ops.mdc +20 -0
  36. package/dist/templates/.cursor/rules/08-solid-and-architecture.mdc +16 -0
  37. package/dist/templates/.cursor/rules/09-docstrings.mdc +89 -0
  38. package/dist/templates/.cursor/rules/10-documentation-quality-standards.mdc +390 -0
  39. package/dist/templates/.cursor/rules/11-scope-management-waivers.mdc +385 -0
  40. package/dist/templates/.cursor/rules/12-implementation-completeness.mdc +516 -0
  41. package/dist/templates/.cursor/rules/13-language-agnostic-standards.mdc +588 -0
  42. package/dist/templates/.cursor/rules/README.md +148 -0
  43. package/dist/templates/.github/copilot/instructions.md +311 -0
  44. package/dist/templates/.idea/runConfigurations/CAWS_Evaluate.xml +5 -0
  45. package/dist/templates/.idea/runConfigurations/CAWS_Validate.xml +5 -0
  46. package/dist/templates/.vscode/launch.json +56 -0
  47. package/dist/templates/.vscode/settings.json +93 -0
  48. package/dist/templates/.windsurf/workflows/caws-guided-development.md +92 -0
  49. package/dist/templates/COMMIT_CONVENTIONS.md +86 -0
  50. package/dist/templates/OIDC_SETUP.md +300 -0
  51. package/dist/templates/agents.md +1047 -0
  52. package/dist/templates/codemod/README.md +1 -0
  53. package/dist/templates/codemod/test.js +93 -0
  54. package/dist/templates/docs/README.md +150 -0
  55. package/dist/templates/scripts/quality-gates/check-god-objects.js +146 -0
  56. package/dist/templates/scripts/quality-gates/run-quality-gates.js +50 -0
  57. package/dist/templates/scripts/v3/analysis/todo_analyzer.py +1997 -0
  58. package/dist/tool-loader.js +6 -1
  59. package/dist/tool-validator.js +8 -2
  60. package/dist/utils/detection.js +34 -6
  61. package/dist/utils/git-lock.js +118 -0
  62. package/dist/utils/gitignore-updater.js +148 -0
  63. package/dist/utils/quality-gates.js +47 -7
  64. package/dist/utils/spec-resolver.js +23 -3
  65. package/dist/utils/yaml-validation.js +155 -0
  66. package/dist/validation/spec-validation.js +105 -2
  67. package/package.json +2 -2
  68. package/templates/.caws/schemas/waivers.schema.json +30 -0
  69. package/templates/.caws/schemas/working-spec.schema.json +133 -0
  70. package/templates/.caws/templates/working-spec.template.yml +74 -0
  71. package/templates/.caws/tools/README.md +20 -0
  72. package/templates/.caws/tools/scope-guard.js +208 -0
  73. package/templates/.caws/tools-allow.json +331 -0
  74. package/templates/.caws/waivers.yml +19 -0
  75. package/templates/.cursor/hooks/scope-guard.sh +2 -2
  76. package/templates/.cursor/hooks/validate-spec.sh +42 -7
  77. package/templates/apps/tools/caws/COMPLETION_REPORT.md +0 -331
  78. package/templates/apps/tools/caws/MIGRATION_SUMMARY.md +0 -360
  79. package/templates/apps/tools/caws/README.md +0 -463
  80. package/templates/apps/tools/caws/TEST_STATUS.md +0 -365
  81. package/templates/apps/tools/caws/attest.js +0 -357
  82. package/templates/apps/tools/caws/ci-optimizer.js +0 -642
  83. package/templates/apps/tools/caws/config.ts +0 -245
  84. package/templates/apps/tools/caws/cross-functional.js +0 -876
  85. package/templates/apps/tools/caws/dashboard.js +0 -1112
  86. package/templates/apps/tools/caws/flake-detector.ts +0 -362
  87. package/templates/apps/tools/caws/gates.js +0 -198
  88. package/templates/apps/tools/caws/gates.ts +0 -271
  89. package/templates/apps/tools/caws/language-adapters.ts +0 -381
  90. package/templates/apps/tools/caws/language-support.d.ts +0 -367
  91. package/templates/apps/tools/caws/language-support.d.ts.map +0 -1
  92. package/templates/apps/tools/caws/language-support.js +0 -585
  93. package/templates/apps/tools/caws/legacy-assessment.ts +0 -408
  94. package/templates/apps/tools/caws/legacy-assessor.js +0 -764
  95. package/templates/apps/tools/caws/mutant-analyzer.js +0 -734
  96. package/templates/apps/tools/caws/perf-budgets.ts +0 -349
  97. package/templates/apps/tools/caws/prompt-lint.js.backup +0 -274
  98. package/templates/apps/tools/caws/property-testing.js +0 -707
  99. package/templates/apps/tools/caws/provenance.d.ts +0 -14
  100. package/templates/apps/tools/caws/provenance.d.ts.map +0 -1
  101. package/templates/apps/tools/caws/provenance.js +0 -132
  102. package/templates/apps/tools/caws/provenance.js.backup +0 -73
  103. package/templates/apps/tools/caws/provenance.ts +0 -211
  104. package/templates/apps/tools/caws/security-provenance.ts +0 -483
  105. package/templates/apps/tools/caws/shared/base-tool.ts +0 -281
  106. package/templates/apps/tools/caws/shared/config-manager.ts +0 -366
  107. package/templates/apps/tools/caws/shared/gate-checker.ts +0 -849
  108. package/templates/apps/tools/caws/shared/types.ts +0 -444
  109. package/templates/apps/tools/caws/shared/validator.ts +0 -305
  110. package/templates/apps/tools/caws/shared/waivers-manager.ts +0 -174
  111. package/templates/apps/tools/caws/spec-test-mapper.ts +0 -391
  112. package/templates/apps/tools/caws/test-quality.js +0 -578
  113. package/templates/apps/tools/caws/validate.js +0 -76
  114. package/templates/apps/tools/caws/validate.ts +0 -228
  115. package/templates/apps/tools/caws/waivers.js +0 -344
  116. /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/waivers.schema.json +0 -0
  117. /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/working-spec.schema.json +0 -0
  118. /package/{templates/apps/tools/caws → dist/templates/.caws}/templates/working-spec.template.yml +0 -0
  119. /package/{templates/apps/tools/caws → dist/templates/.caws/tools}/scope-guard.js +0 -0
  120. /package/{templates/apps/tools/caws → dist/templates/.caws}/tools-allow.json +0 -0
  121. /package/{templates/apps/tools/caws → dist/templates/.caws}/waivers.yml +0 -0
@@ -1,483 +0,0 @@
1
- #!/usr/bin/env tsx
2
-
3
- /**
4
- * CAWS Security & Provenance Manager
5
- * Cryptographic signing, SLSA attestations, and security scanning
6
- *
7
- * @author @darianrosebrook
8
- */
9
-
10
- import * as crypto from 'crypto';
11
- import * as fs from 'fs';
12
- import * as path from 'path';
13
- import { CawsBaseTool } from './shared/base-tool.js';
14
-
15
- interface SecurityProvenance {
16
- signature: string;
17
- signedBy: string;
18
- signedAt: string;
19
- algorithm: string;
20
- publicKeyFingerprint: string;
21
- }
22
-
23
- interface ModelProvenance {
24
- modelId: string;
25
- version: string;
26
- trainingDataCutoff?: string;
27
- provider: string;
28
- checksumVerified: boolean;
29
- }
30
-
31
- interface PromptProvenance {
32
- promptHashes: string[];
33
- totalPrompts: number;
34
- sanitizationApplied: boolean;
35
- injectionChecksPassed: boolean;
36
- }
37
-
38
- export class SecurityProvenanceManager extends CawsBaseTool {
39
- /**
40
- * Sign code or provenance manifest with cryptographic signature
41
- */
42
- async signArtifact(artifactPath: string, privateKeyPath?: string): Promise<SecurityProvenance> {
43
- try {
44
- const content = fs.readFileSync(artifactPath, 'utf-8');
45
-
46
- // Generate hash of content
47
- const hash = crypto.createHash('sha256').update(content).digest('hex');
48
-
49
- // In production, would use actual private key signing
50
- // For now, create a deterministic signature
51
- const signature = this.generateSignature(content, privateKeyPath);
52
-
53
- const publicKeyFingerprint = this.getPublicKeyFingerprint(privateKeyPath);
54
-
55
- return {
56
- signature,
57
- signedBy: process.env.CAWS_SIGNER || 'caws-agent',
58
- signedAt: new Date().toISOString(),
59
- algorithm: 'SHA256withRSA',
60
- publicKeyFingerprint,
61
- };
62
- } catch (error) {
63
- throw new Error(`Failed to sign artifact: ${error}`);
64
- }
65
- }
66
-
67
- /**
68
- * Verify artifact signature
69
- */
70
- async verifySignature(
71
- artifactPath: string,
72
- signature: string,
73
- publicKeyPath?: string
74
- ): Promise<boolean> {
75
- try {
76
- const content = fs.readFileSync(artifactPath, 'utf-8');
77
-
78
- // In production, would verify with actual public key
79
- // For now, recreate signature and compare
80
- const expectedSignature = this.generateSignature(content, publicKeyPath);
81
-
82
- return signature === expectedSignature;
83
- } catch (error) {
84
- console.error(`Signature verification failed: ${error}`);
85
- return false;
86
- }
87
- }
88
-
89
- /**
90
- * Track model provenance for AI-generated code
91
- */
92
- async trackModelProvenance(
93
- modelId: string,
94
- version: string,
95
- provider: string = 'openai'
96
- ): Promise<ModelProvenance> {
97
- const checksumVerified = await this.verifyModelChecksum(modelId, version);
98
-
99
- return {
100
- modelId,
101
- version,
102
- trainingDataCutoff: this.getTrainingCutoff(modelId),
103
- provider,
104
- checksumVerified,
105
- };
106
- }
107
-
108
- /**
109
- * Hash prompts for audit trail without storing sensitive content
110
- */
111
- async hashPrompts(prompts: string[]): Promise<PromptProvenance> {
112
- const sanitizationApplied = prompts.some((p) => this.containsSensitiveData(p));
113
-
114
- const promptHashes = prompts.map((prompt) => {
115
- // Sanitize before hashing
116
- const sanitized = this.sanitizePrompt(prompt);
117
- return crypto.createHash('sha256').update(sanitized).digest('hex');
118
- });
119
-
120
- const injectionChecksPassed = prompts.every((p) => this.checkPromptInjection(p));
121
-
122
- return {
123
- promptHashes,
124
- totalPrompts: prompts.length,
125
- sanitizationApplied,
126
- injectionChecksPassed,
127
- };
128
- }
129
-
130
- /**
131
- * Run security scans and collect results
132
- */
133
- async runSecurityScans(projectDir: string): Promise<{
134
- secretScanPassed: boolean;
135
- sastPassed: boolean;
136
- dependencyScanPassed: boolean;
137
- details: Record<string, any>;
138
- }> {
139
- const results = {
140
- secretScanPassed: true,
141
- sastPassed: true,
142
- dependencyScanPassed: true,
143
- details: {} as Record<string, any>,
144
- };
145
-
146
- // Check for secrets
147
- const secretScan = await this.scanForSecrets(projectDir);
148
- results.secretScanPassed = secretScan.passed;
149
- results.details.secrets = secretScan;
150
-
151
- // Check for vulnerabilities
152
- const sastScan = await this.runSAST(projectDir);
153
- results.sastPassed = sastScan.passed;
154
- results.details.sast = sastScan;
155
-
156
- // Check dependencies
157
- const depScan = await this.scanDependencies(projectDir);
158
- results.dependencyScanPassed = depScan.passed;
159
- results.details.dependencies = depScan;
160
-
161
- return results;
162
- }
163
-
164
- /**
165
- * Generate SLSA provenance attestation
166
- */
167
- async generateSLSAAttestation(buildInfo: {
168
- commit: string;
169
- builder: string;
170
- buildTime: string;
171
- artifacts: string[];
172
- }): Promise<Record<string, any>> {
173
- return {
174
- _type: 'https://in-toto.io/Statement/v0.1',
175
- predicateType: 'https://slsa.dev/provenance/v0.2',
176
- subject: buildInfo.artifacts.map((artifact) => ({
177
- name: artifact,
178
- digest: {
179
- sha256: this.hashFile(artifact),
180
- },
181
- })),
182
- predicate: {
183
- builder: {
184
- id: buildInfo.builder,
185
- },
186
- buildType: 'https://caws.dev/build/v1',
187
- invocation: {
188
- configSource: {
189
- uri: `git+https://github.com/repo@${buildInfo.commit}`,
190
- digest: {
191
- sha256: buildInfo.commit,
192
- },
193
- },
194
- },
195
- metadata: {
196
- buildStartedOn: buildInfo.buildTime,
197
- buildFinishedOn: new Date().toISOString(),
198
- completeness: {
199
- parameters: true,
200
- environment: false,
201
- materials: true,
202
- },
203
- reproducible: false,
204
- },
205
- materials: buildInfo.artifacts.map((artifact) => ({
206
- uri: `file://${artifact}`,
207
- digest: {
208
- sha256: this.hashFile(artifact),
209
- },
210
- })),
211
- },
212
- };
213
- }
214
-
215
- private generateSignature(content: string, keyPath?: string): string {
216
- // Simplified signature generation
217
- // In production, use actual RSA signing with private key
218
- const hash = crypto.createHash('sha256').update(content);
219
-
220
- if (keyPath && fs.existsSync(keyPath)) {
221
- const keyContent = fs.readFileSync(keyPath, 'utf-8');
222
- hash.update(keyContent);
223
- }
224
-
225
- return hash.digest('hex');
226
- }
227
-
228
- private getPublicKeyFingerprint(keyPath?: string): string {
229
- if (keyPath && fs.existsSync(keyPath)) {
230
- const keyContent = fs.readFileSync(keyPath, 'utf-8');
231
- return crypto.createHash('sha256').update(keyContent).digest('hex').substring(0, 16);
232
- }
233
- return 'no-key';
234
- }
235
-
236
- private async verifyModelChecksum(modelId: string, version: string): Promise<boolean> {
237
- // In production, verify against known model checksums
238
- // For now, return true as placeholder
239
- return true;
240
- }
241
-
242
- private getTrainingCutoff(modelId: string): string | undefined {
243
- // Known cutoff dates for common models
244
- const cutoffs: Record<string, string> = {
245
- 'gpt-4': '2023-04-01',
246
- 'gpt-4-turbo': '2023-12-01',
247
- 'claude-3': '2023-08-01',
248
- 'claude-sonnet-4': '2024-09-01',
249
- };
250
-
251
- return cutoffs[modelId];
252
- }
253
-
254
- private containsSensitiveData(prompt: string): boolean {
255
- const patterns = [
256
- /password/i,
257
- /api[_-]?key/i,
258
- /secret/i,
259
- /token/i,
260
- /credential/i,
261
- /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/, // email
262
- /\b\d{3}-\d{2}-\d{4}\b/, // SSN
263
- ];
264
-
265
- return patterns.some((pattern) => pattern.test(prompt));
266
- }
267
-
268
- private sanitizePrompt(prompt: string): string {
269
- // Remove sensitive data before hashing
270
- let sanitized = prompt;
271
-
272
- // Redact emails
273
- sanitized = sanitized.replace(
274
- /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,
275
- '[EMAIL_REDACTED]'
276
- );
277
-
278
- // Redact potential API keys
279
- sanitized = sanitized.replace(/[a-zA-Z0-9]{32,}/g, '[KEY_REDACTED]');
280
-
281
- return sanitized;
282
- }
283
-
284
- private checkPromptInjection(prompt: string): boolean {
285
- // Check for common prompt injection patterns
286
- const injectionPatterns = [
287
- /ignore previous instructions/i,
288
- /disregard all above/i,
289
- /system:\s*you are now/i,
290
- /<\|im_start\|>/,
291
- ];
292
-
293
- return !injectionPatterns.some((pattern) => pattern.test(prompt));
294
- }
295
-
296
- private async scanForSecrets(
297
- projectDir: string
298
- ): Promise<{ passed: boolean; findings: string[] }> {
299
- const findings: string[] = [];
300
-
301
- // Simple secret scan (in production, use trufflehog or similar)
302
- const files = this.findFilesRecursive(projectDir);
303
-
304
- for (const file of files) {
305
- if (file.includes('node_modules')) continue;
306
-
307
- const content = fs.readFileSync(file, 'utf-8');
308
- if (this.containsSensitiveData(content)) {
309
- findings.push(`Potential secret in ${file}`);
310
- }
311
- }
312
-
313
- return { passed: findings.length === 0, findings };
314
- }
315
-
316
- private async runSAST(projectDir: string): Promise<{ passed: boolean; vulnerabilities: number }> {
317
- // Placeholder for SAST integration
318
- // In production, integrate with Snyk, SonarQube, etc.
319
- return { passed: true, vulnerabilities: 0 };
320
- }
321
-
322
- private async scanDependencies(
323
- projectDir: string
324
- ): Promise<{ passed: boolean; vulnerable: number }> {
325
- // Placeholder for dependency scanning
326
- // In production, use npm audit, snyk, etc.
327
- return { passed: true, vulnerable: 0 };
328
- }
329
-
330
- private hashFile(filePath: string): string {
331
- if (!fs.existsSync(filePath)) {
332
- return '';
333
- }
334
- const content = fs.readFileSync(filePath);
335
- return crypto.createHash('sha256').update(content).digest('hex');
336
- }
337
-
338
- private findFilesRecursive(dir: string, files: string[] = []): string[] {
339
- try {
340
- const entries = fs.readdirSync(dir, { withFileTypes: true });
341
-
342
- for (const entry of entries) {
343
- const fullPath = path.join(dir, entry.name);
344
- if (entry.isDirectory() && !entry.name.includes('node_modules')) {
345
- this.findFilesRecursive(fullPath, files);
346
- } else if (entry.isFile()) {
347
- files.push(fullPath);
348
- }
349
- }
350
- } catch {
351
- // Directory doesn't exist
352
- }
353
-
354
- return files;
355
- }
356
- }
357
-
358
- // CLI interface
359
- if (import.meta.url === `file://${process.argv[1]}`) {
360
- (async () => {
361
- const command = process.argv[2];
362
- const manager = new SecurityProvenanceManager();
363
-
364
- switch (command) {
365
- case 'sign': {
366
- const artifactPath = process.argv[3];
367
- const keyPath = process.argv[4];
368
-
369
- if (!artifactPath) {
370
- console.error('Usage: security-provenance sign <artifact> [key]');
371
- process.exit(1);
372
- }
373
-
374
- try {
375
- const signature = await manager.signArtifact(artifactPath, keyPath);
376
- console.log('✅ Artifact signed successfully');
377
- console.log(JSON.stringify(signature, null, 2));
378
- } catch (error) {
379
- console.error(`❌ Signing failed: ${error}`);
380
- process.exit(1);
381
- }
382
- break;
383
- }
384
-
385
- case 'verify': {
386
- const artifactPath = process.argv[3];
387
- const signature = process.argv[4];
388
- const keyPath = process.argv[5];
389
-
390
- if (!artifactPath || !signature) {
391
- console.error('Usage: security-provenance verify <artifact> <signature> [key]');
392
- process.exit(1);
393
- }
394
-
395
- try {
396
- const valid = await manager.verifySignature(artifactPath, signature, keyPath);
397
- if (valid) {
398
- console.log('✅ Signature is valid');
399
- } else {
400
- console.log('❌ Signature is invalid');
401
- process.exit(1);
402
- }
403
- } catch (error) {
404
- console.error(`❌ Verification failed: ${error}`);
405
- process.exit(1);
406
- }
407
- break;
408
- }
409
-
410
- case 'scan': {
411
- const projectDir = process.argv[3] || process.cwd();
412
-
413
- try {
414
- const results = await manager.runSecurityScans(projectDir);
415
-
416
- console.log('\n🔒 Security Scan Results');
417
- console.log('='.repeat(50));
418
- console.log(`Secret Scan: ${results.secretScanPassed ? '✅ PASSED' : '❌ FAILED'}`);
419
- console.log(`SAST Scan: ${results.sastPassed ? '✅ PASSED' : '❌ FAILED'}`);
420
- console.log(
421
- `Dependency Scan: ${results.dependencyScanPassed ? '✅ PASSED' : '❌ FAILED'}`
422
- );
423
-
424
- if (results.details.secrets?.findings?.length > 0) {
425
- console.log('\n🚨 Secret Findings:');
426
- results.details.secrets.findings.forEach((finding: string) => {
427
- console.log(` - ${finding}`);
428
- });
429
- }
430
-
431
- const allPassed =
432
- results.secretScanPassed && results.sastPassed && results.dependencyScanPassed;
433
- process.exit(allPassed ? 0 : 1);
434
- } catch (error) {
435
- console.error(`❌ Scan failed: ${error}`);
436
- process.exit(1);
437
- }
438
- break;
439
- }
440
-
441
- case 'slsa': {
442
- const commit = process.argv[3];
443
- const builder = process.argv[4] || 'caws-builder';
444
-
445
- if (!commit) {
446
- console.error('Usage: security-provenance slsa <commit> [builder]');
447
- process.exit(1);
448
- }
449
-
450
- try {
451
- const attestation = await manager.generateSLSAAttestation({
452
- commit,
453
- builder,
454
- buildTime: new Date().toISOString(),
455
- artifacts: ['.agent/provenance.json'],
456
- });
457
-
458
- console.log(JSON.stringify(attestation, null, 2));
459
- } catch (error) {
460
- console.error(`❌ SLSA generation failed: ${error}`);
461
- process.exit(1);
462
- }
463
- break;
464
- }
465
-
466
- default:
467
- console.log('CAWS Security & Provenance Manager');
468
- console.log('');
469
- console.log('Usage:');
470
- console.log(' security-provenance sign <artifact> [key] - Sign artifact');
471
- console.log(' security-provenance verify <artifact> <sig> [key] - Verify signature');
472
- console.log(' security-provenance scan [dir] - Run security scans');
473
- console.log(
474
- ' security-provenance slsa <commit> [builder] - Generate SLSA attestation'
475
- );
476
- console.log('');
477
- console.log('Examples:');
478
- console.log(' security-provenance sign .agent/provenance.json');
479
- console.log(' security-provenance scan .');
480
- break;
481
- }
482
- })();
483
- }