@paths.design/caws-cli 9.3.2 → 10.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/README.md +71 -32
- package/dist/budget-derivation.js +221 -74
- 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 +41 -15
- package/dist/commands/gates.js +149 -0
- package/dist/commands/init.js +150 -19
- package/dist/commands/iterate.js +81 -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/scope.js +264 -0
- package/dist/commands/sidecar.js +74 -0
- package/dist/commands/specs.js +381 -45
- package/dist/commands/status.js +117 -9
- package/dist/commands/templates.js +0 -8
- package/dist/commands/tutorial.js +10 -9
- package/dist/commands/validate.js +70 -6
- package/dist/commands/verify-acs.js +48 -76
- package/dist/commands/waivers.js +212 -13
- package/dist/commands/worktree.js +131 -26
- package/dist/error-handler.js +2 -13
- package/dist/gates/budget-limit.js +121 -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 +109 -0
- package/dist/gates/todo-detection.js +205 -0
- package/dist/index.js +157 -151
- package/dist/parallel/parallel-manager.js +3 -3
- package/dist/policy/PolicyManager.js +51 -17
- 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 +105 -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 +112 -0
- package/dist/templates/.caws/schemas/scope.schema.json +3 -3
- package/dist/templates/.caws/schemas/waivers.schema.json +96 -20
- package/dist/templates/.caws/schemas/working-spec.schema.json +264 -57
- package/dist/templates/.caws/schemas/worktrees.schema.json +3 -1
- package/dist/templates/.caws/templates/working-spec.template.yml +10 -4
- package/dist/templates/.caws/tools/scope-guard.js +66 -15
- package/dist/templates/.claude/README.md +1 -1
- 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/protected-paths.sh +39 -0
- package/dist/templates/.claude/hooks/quality-check.sh +23 -10
- package/dist/templates/.claude/hooks/scope-guard.sh +136 -55
- 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 +97 -4
- package/dist/templates/.claude/settings.json +31 -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 +77 -8
- package/dist/templates/agents.md +50 -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/event-log.js +584 -0
- package/dist/utils/event-renderer.js +521 -0
- 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 +50 -0
- package/dist/utils/spec-resolver.js +93 -21
- package/dist/utils/working-state.js +530 -0
- package/dist/validation/spec-validation.js +191 -31
- package/dist/waivers-manager.js +144 -6
- package/dist/worktree/worktree-manager.js +598 -95
- package/package.json +9 -8
- package/templates/.caws/schemas/policy.schema.json +112 -0
- package/templates/.caws/schemas/scope.schema.json +3 -3
- package/templates/.caws/schemas/waivers.schema.json +96 -20
- package/templates/.caws/schemas/working-spec.schema.json +264 -57
- package/templates/.caws/schemas/worktrees.schema.json +3 -1
- package/templates/.caws/templates/working-spec.template.yml +10 -4
- package/templates/.caws/tools/scope-guard.js +66 -15
- package/templates/.claude/README.md +1 -1
- 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/protected-paths.sh +39 -0
- package/templates/.claude/hooks/quality-check.sh +23 -10
- package/templates/.claude/hooks/scope-guard.sh +136 -55
- 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 +97 -4
- package/templates/.claude/settings.json +31 -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 +77 -8
- package/templates/{AGENTS.md → agents.md} +50 -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
package/dist/commands/init.js
CHANGED
|
@@ -8,6 +8,7 @@ const fs = require('fs-extra');
|
|
|
8
8
|
const path = require('path');
|
|
9
9
|
const inquirer = require('inquirer');
|
|
10
10
|
const chalk = require('chalk');
|
|
11
|
+
const yaml = require('js-yaml');
|
|
11
12
|
|
|
12
13
|
// Import shared utilities
|
|
13
14
|
const { detectCAWSSetup } = require('../utils/detection');
|
|
@@ -27,6 +28,119 @@ const {
|
|
|
27
28
|
getRecommendedIDEs,
|
|
28
29
|
parseIDESelection,
|
|
29
30
|
} = require('../utils/ide-detection');
|
|
31
|
+
// CAWSFIX-10: share the canonical spec-ID regex with the validator
|
|
32
|
+
const { SPEC_ID_PATTERN } = require('../validation/spec-validation');
|
|
33
|
+
|
|
34
|
+
function buildInitialFeatureSpec(specContent, fallbackId) {
|
|
35
|
+
const parsed = yaml.load(specContent);
|
|
36
|
+
const riskTier =
|
|
37
|
+
typeof parsed.risk_tier === 'string'
|
|
38
|
+
? parseInt(parsed.risk_tier.replace(/^T/i, ''), 10) || 3
|
|
39
|
+
: parsed.risk_tier || 3;
|
|
40
|
+
const aiConfidenceRaw = parsed.ai_assessment?.confidence_level;
|
|
41
|
+
const aiConfidence =
|
|
42
|
+
typeof aiConfidenceRaw === 'number' && aiConfidenceRaw <= 1
|
|
43
|
+
? Math.max(1, Math.min(10, Math.round(aiConfidenceRaw * 10)))
|
|
44
|
+
: typeof aiConfidenceRaw === 'number'
|
|
45
|
+
? Math.max(1, Math.min(10, Math.round(aiConfidenceRaw)))
|
|
46
|
+
: 8;
|
|
47
|
+
const normalizedContracts =
|
|
48
|
+
Array.isArray(parsed.contracts) && parsed.contracts.length > 0
|
|
49
|
+
? parsed.contracts.map((contract, index) => ({
|
|
50
|
+
type: ['openapi', 'graphql', 'proto', 'pact'].includes(contract?.type)
|
|
51
|
+
? contract.type
|
|
52
|
+
: 'openapi',
|
|
53
|
+
path:
|
|
54
|
+
contract?.path ||
|
|
55
|
+
(index === 0 ? 'docs/api/initial-feature.yaml' : `docs/api/contract-${index + 1}.yaml`),
|
|
56
|
+
}))
|
|
57
|
+
: riskTier <= 2
|
|
58
|
+
? [{ type: 'openapi', path: 'docs/api/initial-feature.yaml' }]
|
|
59
|
+
: [];
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
id: parsed.id || fallbackId,
|
|
63
|
+
title: parsed.title || 'New CAWS Project',
|
|
64
|
+
risk_tier: riskTier,
|
|
65
|
+
mode: parsed.mode || 'feature',
|
|
66
|
+
blast_radius: parsed.blast_radius || { modules: ['src', 'tests'], data_migration: false },
|
|
67
|
+
operational_rollback_slo: parsed.operational_rollback_slo || '5m',
|
|
68
|
+
scope: parsed.scope || {
|
|
69
|
+
in: ['src/', 'tests/'],
|
|
70
|
+
out: ['node_modules/', 'dist/', 'build/'],
|
|
71
|
+
},
|
|
72
|
+
invariants: Array.isArray(parsed.invariants) && parsed.invariants.length > 0
|
|
73
|
+
? parsed.invariants
|
|
74
|
+
: ['System maintains data consistency'],
|
|
75
|
+
acceptance: Array.isArray(parsed.acceptance) && parsed.acceptance.length > 0
|
|
76
|
+
? parsed.acceptance
|
|
77
|
+
: [
|
|
78
|
+
{
|
|
79
|
+
id: 'A1',
|
|
80
|
+
given: 'Current system state',
|
|
81
|
+
when: 'the initial project is bootstrapped',
|
|
82
|
+
then: 'the CAWS project should validate successfully',
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
non_functional: parsed.non_functional || {
|
|
86
|
+
a11y: ['keyboard'],
|
|
87
|
+
perf: { api_p95_ms: 250 },
|
|
88
|
+
security: [],
|
|
89
|
+
},
|
|
90
|
+
contracts: normalizedContracts,
|
|
91
|
+
observability: parsed.observability || { logs: [], metrics: [], traces: [] },
|
|
92
|
+
migrations: Array.isArray(parsed.migrations) ? parsed.migrations : [],
|
|
93
|
+
rollback: Array.isArray(parsed.rollback) ? parsed.rollback : [],
|
|
94
|
+
ai_assessment: {
|
|
95
|
+
confidence_level: aiConfidence,
|
|
96
|
+
uncertainty_areas: Array.isArray(parsed.ai_assessment?.uncertainty_areas)
|
|
97
|
+
? parsed.ai_assessment.uncertainty_areas
|
|
98
|
+
: [],
|
|
99
|
+
recommended_pairing:
|
|
100
|
+
parsed.ai_assessment?.recommended_pairing !== undefined
|
|
101
|
+
? Boolean(parsed.ai_assessment.recommended_pairing)
|
|
102
|
+
: aiConfidence <= 6,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function writeInitialSpecArtifacts(specContent, fallbackId) {
|
|
108
|
+
const canonicalSpec = buildInitialFeatureSpec(specContent, fallbackId);
|
|
109
|
+
const now = new Date().toISOString();
|
|
110
|
+
const canonicalContent = yaml.dump(canonicalSpec, { indent: 2 });
|
|
111
|
+
const specsDir = path.join('.caws', 'specs');
|
|
112
|
+
const featureSpecPath = path.join(specsDir, `${canonicalSpec.id}.yaml`);
|
|
113
|
+
const workingSpecPath = path.join('.caws', 'working-spec.yaml');
|
|
114
|
+
const registryPath = path.join(specsDir, 'registry.json');
|
|
115
|
+
|
|
116
|
+
await fs.ensureDir(specsDir);
|
|
117
|
+
await fs.writeFile(featureSpecPath, canonicalContent);
|
|
118
|
+
await fs.writeFile(workingSpecPath, canonicalContent);
|
|
119
|
+
await fs.writeJson(
|
|
120
|
+
registryPath,
|
|
121
|
+
{
|
|
122
|
+
version: '1.0.0',
|
|
123
|
+
specs: {
|
|
124
|
+
[canonicalSpec.id]: {
|
|
125
|
+
path: `${canonicalSpec.id}.yaml`,
|
|
126
|
+
type: 'feature',
|
|
127
|
+
status: 'active',
|
|
128
|
+
created_at: now,
|
|
129
|
+
updated_at: now,
|
|
130
|
+
owner: null,
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
lastUpdated: now,
|
|
134
|
+
},
|
|
135
|
+
{ spaces: 2 }
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
canonicalSpec,
|
|
140
|
+
featureSpecPath,
|
|
141
|
+
workingSpecPath,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
30
144
|
|
|
31
145
|
/**
|
|
32
146
|
* Initialize a new project with CAWS
|
|
@@ -407,11 +521,12 @@ async function initProject(projectName, options) {
|
|
|
407
521
|
return `PROJ-${randomNum.toString().padStart(3, '0')}`;
|
|
408
522
|
},
|
|
409
523
|
validate: (input) => {
|
|
410
|
-
|
|
411
|
-
|
|
524
|
+
// CAWSFIX-10: accept multi-segment IDs like P03-IMPL-01
|
|
525
|
+
if (!SPEC_ID_PATTERN.test(input)) {
|
|
526
|
+
return 'Project ID must be in format PREFIX-NUMBER or PREFIX-SEGMENT-NUMBER (e.g., PROJ-001, P03-IMPL-01)';
|
|
412
527
|
}
|
|
413
|
-
if (input.length >
|
|
414
|
-
return 'Project ID must be less than
|
|
528
|
+
if (input.length > 40) {
|
|
529
|
+
return 'Project ID must be less than 40 characters';
|
|
415
530
|
}
|
|
416
531
|
return true;
|
|
417
532
|
},
|
|
@@ -492,10 +607,12 @@ async function initProject(projectName, options) {
|
|
|
492
607
|
console.log(chalk.blue('\nGenerating CAWS working spec...'));
|
|
493
608
|
const specContent = generateWorkingSpec(answers);
|
|
494
609
|
|
|
495
|
-
// Write
|
|
610
|
+
// Write canonical feature spec plus legacy compatibility mirror
|
|
496
611
|
await fs.ensureDir('.caws');
|
|
497
|
-
await
|
|
612
|
+
const initialSpec = await writeInitialSpecArtifacts(specContent, answers.projectId);
|
|
613
|
+
console.log(chalk.green(`Created ${initialSpec.featureSpecPath}`));
|
|
498
614
|
console.log(chalk.green('Created .caws/working-spec.yaml'));
|
|
615
|
+
console.log(chalk.green('Created .caws/specs/registry.json'));
|
|
499
616
|
|
|
500
617
|
// Optionally create policy.yaml (optional - defaults work fine)
|
|
501
618
|
const policyPath = path.join('.caws', 'policy.yaml');
|
|
@@ -503,7 +620,6 @@ async function initProject(projectName, options) {
|
|
|
503
620
|
const { PolicyManager } = require('../policy/PolicyManager');
|
|
504
621
|
const policyManager = new PolicyManager();
|
|
505
622
|
const defaultPolicy = policyManager.getDefaultPolicy();
|
|
506
|
-
const yaml = require('js-yaml');
|
|
507
623
|
const policyContent = yaml.dump(defaultPolicy, { indent: 2 });
|
|
508
624
|
await fs.writeFile(policyPath, policyContent);
|
|
509
625
|
console.log(chalk.green('Created .caws/policy.yaml (optional - defaults work fine)'));
|
|
@@ -522,10 +638,20 @@ ${answers.projectDescription}
|
|
|
522
638
|
## Risk Tier: ${answers.riskTier === 1 ? 'High (T1)' : answers.riskTier === 2 ? 'Medium (T2)' : 'Low (T3)'}
|
|
523
639
|
|
|
524
640
|
## Next Steps
|
|
525
|
-
1. Review and customize \`.caws/
|
|
641
|
+
1. Review and customize \`.caws/specs/${answers.projectId}.yaml\`
|
|
526
642
|
2. Set up your development environment
|
|
527
643
|
3. Implement features according to the spec
|
|
528
|
-
4. Run \`caws validate\` to check your progress
|
|
644
|
+
4. Run \`caws validate --spec-id ${answers.projectId}\` to check your progress
|
|
645
|
+
|
|
646
|
+
## Multi-Agent Recommendation
|
|
647
|
+
The initial project spec is also available in \`.caws/specs/${answers.projectId}.yaml\`.
|
|
648
|
+
For multi-agent work, treat feature specs in \`.caws/specs/\` as canonical and use
|
|
649
|
+
\`.caws/working-spec.yaml\` only as a compatibility mirror:
|
|
650
|
+
|
|
651
|
+
\`\`\`bash
|
|
652
|
+
caws specs create my-feature --type feature --title "My Feature"
|
|
653
|
+
caws validate --spec-id my-feature
|
|
654
|
+
\`\`\`
|
|
529
655
|
|
|
530
656
|
## Quality Gates
|
|
531
657
|
- **Coverage**: ${answers.riskTier === 1 ? '90%+' : answers.riskTier === 2 ? '80%+' : '70%+'}
|
|
@@ -584,7 +710,7 @@ Happy coding! `;
|
|
|
584
710
|
projectTitle: path.basename(process.cwd()),
|
|
585
711
|
projectDescription: `A ${detectedType} project managed with CAWS`,
|
|
586
712
|
riskTier: 2,
|
|
587
|
-
projectId: `PROJ-${Math.floor(Math.random() * 1000) + 1}`,
|
|
713
|
+
projectId: `PROJ-${String(Math.floor(Math.random() * 1000) + 1).padStart(3, '0')}`,
|
|
588
714
|
useCursorHooks: true,
|
|
589
715
|
generateExamples: false,
|
|
590
716
|
projectMode: 'feature',
|
|
@@ -624,8 +750,10 @@ Happy coding! `;
|
|
|
624
750
|
|
|
625
751
|
const specContent = generateWorkingSpec(defaultAnswers);
|
|
626
752
|
await fs.ensureDir('.caws');
|
|
627
|
-
await
|
|
753
|
+
const initialSpec = await writeInitialSpecArtifacts(specContent, defaultAnswers.projectId);
|
|
754
|
+
console.log(chalk.green(`Created ${initialSpec.featureSpecPath}`));
|
|
628
755
|
console.log(chalk.green('Created .caws/working-spec.yaml'));
|
|
756
|
+
console.log(chalk.green('Created .caws/specs/registry.json'));
|
|
629
757
|
|
|
630
758
|
// Optionally create policy.yaml (optional - defaults work fine)
|
|
631
759
|
const policyPath = path.join('.caws', 'policy.yaml');
|
|
@@ -633,7 +761,6 @@ Happy coding! `;
|
|
|
633
761
|
const { PolicyManager } = require('../policy/PolicyManager');
|
|
634
762
|
const policyManager = new PolicyManager();
|
|
635
763
|
const defaultPolicy = policyManager.getDefaultPolicy();
|
|
636
|
-
const yaml = require('js-yaml');
|
|
637
764
|
const policyContent = yaml.dump(defaultPolicy, { indent: 2 });
|
|
638
765
|
await fs.writeFile(policyPath, policyContent);
|
|
639
766
|
console.log(chalk.green('Created .caws/policy.yaml (optional - defaults work fine)'));
|
|
@@ -670,8 +797,10 @@ Happy coding! `;
|
|
|
670
797
|
// Success message
|
|
671
798
|
console.log(chalk.green('\nCAWS project initialized successfully!'));
|
|
672
799
|
console.log(chalk.blue('\nNext steps:'));
|
|
673
|
-
console.log('1. Review .caws/
|
|
674
|
-
console.log('2.
|
|
800
|
+
console.log('1. Review .caws/specs/<spec-id>.yaml');
|
|
801
|
+
console.log('2. Treat .caws/working-spec.yaml as the compatibility mirror, not the long-term source of truth');
|
|
802
|
+
console.log('3. If multiple agents will collaborate, create more feature specs with `caws specs create <id>`');
|
|
803
|
+
console.log('4. Use `--spec-id` on validation/status/diagnose commands for feature work');
|
|
675
804
|
|
|
676
805
|
// Show contract requirements if Tier 1 or 2
|
|
677
806
|
// Use answers if available (interactive mode), otherwise default to 2
|
|
@@ -688,16 +817,18 @@ Happy coding! `;
|
|
|
688
817
|
}
|
|
689
818
|
|
|
690
819
|
console.log('\nRecommended Setup Workflow:');
|
|
691
|
-
console.log(' 1. Review .caws/
|
|
820
|
+
console.log(' 1. Review .caws/specs/<spec-id>.yaml');
|
|
692
821
|
console.log(' 2. Run: caws scaffold (adds tools and templates)');
|
|
693
|
-
console.log(' 3.
|
|
694
|
-
console.log(' 4. Run: caws
|
|
695
|
-
console.log(' 5.
|
|
822
|
+
console.log(' 3. For multi-agent work, run: caws specs create <feature-id>');
|
|
823
|
+
console.log(' 4. Run: caws validate --spec-id <spec-id> (verify setup)');
|
|
824
|
+
console.log(' 5. Run: caws diagnose --spec-id <spec-id> (check health)');
|
|
825
|
+
console.log(' 6. Optional: Create .caws/policy.yaml for custom budgets');
|
|
696
826
|
const finalIDEs = answers?.selectedIDEs || [];
|
|
697
827
|
if (finalIDEs.includes('cursor') || finalIDEs.includes('claude') || options.interactive === false) {
|
|
698
|
-
console.log('
|
|
828
|
+
console.log(' 7. Restart your IDE to activate quality gates');
|
|
699
829
|
}
|
|
700
830
|
console.log('\nQuick start: caws scaffold && caws validate && caws diagnose');
|
|
831
|
+
console.log('Multi-agent quick start: caws specs create my-feature && caws validate --spec-id my-feature');
|
|
701
832
|
} catch (error) {
|
|
702
833
|
console.error(chalk.red('Error during initialization:'), error.message);
|
|
703
834
|
if (error.stack) {
|
package/dist/commands/iterate.js
CHANGED
|
@@ -14,6 +14,11 @@ const { initializeGlobalSetup } = require('../config');
|
|
|
14
14
|
|
|
15
15
|
// Import spec resolution system
|
|
16
16
|
const { resolveSpec } = require('../utils/spec-resolver');
|
|
17
|
+
// EVLOG-002 Phase 2 read flip: iterate reads from the event log instead of
|
|
18
|
+
// the state layer. loadStateFromEvents matches loadState's contract exactly
|
|
19
|
+
// (returns null for specs with no events), so the `workingState &&` guard
|
|
20
|
+
// below stays correct without code changes.
|
|
21
|
+
const { loadStateFromEvents } = require('../utils/event-renderer');
|
|
17
22
|
|
|
18
23
|
/**
|
|
19
24
|
* Iterate command handler
|
|
@@ -21,12 +26,12 @@ const { resolveSpec } = require('../utils/spec-resolver');
|
|
|
21
26
|
* @param {string} specFile - Path to working spec file
|
|
22
27
|
* @param {object} options - Command options
|
|
23
28
|
*/
|
|
24
|
-
async function iterateCommand(specFile
|
|
29
|
+
async function iterateCommand(specFile, options = {}) {
|
|
25
30
|
try {
|
|
26
31
|
// Resolve spec using priority system
|
|
27
32
|
const resolved = await resolveSpec({
|
|
28
33
|
specId: options.specId,
|
|
29
|
-
specFile,
|
|
34
|
+
specFile: specFile || undefined,
|
|
30
35
|
warnLegacy: false,
|
|
31
36
|
});
|
|
32
37
|
|
|
@@ -36,12 +41,19 @@ async function iterateCommand(specFile = '.caws/working-spec.yaml', options = {}
|
|
|
36
41
|
const setup = initializeGlobalSetup();
|
|
37
42
|
|
|
38
43
|
if (setup.hasWorkingSpec) {
|
|
39
|
-
console.log(`Detected ${setup.
|
|
44
|
+
console.log(`Detected ${setup.type} CAWS setup`);
|
|
40
45
|
console.log(` Capabilities: ${setup.capabilities.join(', ')}`);
|
|
41
46
|
}
|
|
42
47
|
|
|
43
48
|
// Parse current state from options
|
|
44
|
-
|
|
49
|
+
let currentState = {};
|
|
50
|
+
if (options.currentState) {
|
|
51
|
+
try {
|
|
52
|
+
currentState = JSON.parse(options.currentState);
|
|
53
|
+
} catch {
|
|
54
|
+
console.error('Invalid JSON in --current-state. Using defaults.');
|
|
55
|
+
}
|
|
56
|
+
}
|
|
45
57
|
const stateDescription = currentState.description || 'Starting implementation';
|
|
46
58
|
|
|
47
59
|
console.log(chalk.blue('\nIterative Development Guidance\n'));
|
|
@@ -50,9 +62,48 @@ async function iterateCommand(specFile = '.caws/working-spec.yaml', options = {}
|
|
|
50
62
|
console.log(`ID: ${spec.id} | Tier: ${spec.risk_tier} | Mode: ${spec.mode}`);
|
|
51
63
|
console.log(`Current State: ${stateDescription}\n`);
|
|
52
64
|
|
|
65
|
+
// Load working state for evidence-based guidance (EVLOG-002: from event log)
|
|
66
|
+
let workingState = null;
|
|
67
|
+
try { workingState = loadStateFromEvents(spec.id); } catch { /* non-fatal */ }
|
|
68
|
+
|
|
53
69
|
// Analyze progress based on mode
|
|
54
70
|
const guidance = generateGuidance(spec, currentState, options);
|
|
55
71
|
|
|
72
|
+
// If working state exists, overlay evidence-based data
|
|
73
|
+
if (workingState && workingState.phase !== 'not-started') {
|
|
74
|
+
guidance.phase = formatPhase(workingState.phase);
|
|
75
|
+
|
|
76
|
+
// Build evidence-based completed steps
|
|
77
|
+
const evidence = [];
|
|
78
|
+
if (workingState.validation && workingState.validation.passed) {
|
|
79
|
+
evidence.push(`Validation passed (Grade ${workingState.validation.grade || '?'})`);
|
|
80
|
+
}
|
|
81
|
+
if (workingState.evaluation) {
|
|
82
|
+
evidence.push(`Evaluation: ${workingState.evaluation.percentage}% (Grade ${workingState.evaluation.grade})`);
|
|
83
|
+
}
|
|
84
|
+
if (workingState.gates && workingState.gates.passed) {
|
|
85
|
+
evidence.push(`All gates passing (last run: ${workingState.gates.context} context)`);
|
|
86
|
+
}
|
|
87
|
+
if (workingState.acceptance_criteria) {
|
|
88
|
+
const ac = workingState.acceptance_criteria;
|
|
89
|
+
evidence.push(`AC verification: ${ac.pass}/${ac.total} pass, ${ac.fail} fail, ${ac.unchecked} unchecked`);
|
|
90
|
+
}
|
|
91
|
+
if (workingState.files_touched && workingState.files_touched.length > 0) {
|
|
92
|
+
evidence.push(`${workingState.files_touched.length} file(s) touched`);
|
|
93
|
+
}
|
|
94
|
+
if (evidence.length > 0) {
|
|
95
|
+
guidance.completed = evidence;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Overlay blockers and next actions from state
|
|
99
|
+
if (workingState.blockers && workingState.blockers.length > 0) {
|
|
100
|
+
guidance.blockers = workingState.blockers.map(b => b.message);
|
|
101
|
+
}
|
|
102
|
+
if (workingState.next_actions && workingState.next_actions.length > 0) {
|
|
103
|
+
guidance.nextActions = workingState.next_actions;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
56
107
|
// Display guidance
|
|
57
108
|
console.log(chalk.blue('Current Phase:\n'));
|
|
58
109
|
console.log(` ${guidance.phase}\n`);
|
|
@@ -72,6 +123,18 @@ async function iterateCommand(specFile = '.caws/working-spec.yaml', options = {}
|
|
|
72
123
|
guidance.blockers.forEach((blocker) => {
|
|
73
124
|
console.log(chalk.red(` ${blocker}`));
|
|
74
125
|
});
|
|
126
|
+
|
|
127
|
+
// Show quality gap summary if sidecars available
|
|
128
|
+
try {
|
|
129
|
+
const { diagnoseQualityGaps } = require('../sidecars');
|
|
130
|
+
if (workingState) {
|
|
131
|
+
const gapResult = diagnoseQualityGaps(workingState, spec);
|
|
132
|
+
if (gapResult.data && gapResult.data.gaps && gapResult.data.gaps.length > 0) {
|
|
133
|
+
console.log(chalk.yellow(`\n Quality gaps: ${gapResult.data.summary}`));
|
|
134
|
+
console.log(chalk.yellow(' Run: caws sidecar gaps --spec-id ' + spec.id));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
} catch { /* sidecars not available — non-fatal */ }
|
|
75
138
|
}
|
|
76
139
|
|
|
77
140
|
console.log(chalk.blue('\nRecommendations:\n'));
|
|
@@ -337,4 +400,18 @@ function getQualityGates(riskTier) {
|
|
|
337
400
|
return gates[riskTier] || gates[2];
|
|
338
401
|
}
|
|
339
402
|
|
|
403
|
+
/**
|
|
404
|
+
* Format phase slug into human-readable label
|
|
405
|
+
*/
|
|
406
|
+
function formatPhase(phase) {
|
|
407
|
+
const labels = {
|
|
408
|
+
'not-started': 'Not Started',
|
|
409
|
+
'spec-authoring': 'Spec Authoring',
|
|
410
|
+
'implementation': 'Implementation',
|
|
411
|
+
'verification': 'Verification',
|
|
412
|
+
'complete': 'Complete',
|
|
413
|
+
};
|
|
414
|
+
return labels[phase] || phase;
|
|
415
|
+
}
|
|
416
|
+
|
|
340
417
|
module.exports = { iterateCommand };
|
|
@@ -128,6 +128,10 @@ function handleStatus() {
|
|
|
128
128
|
const statusColor =
|
|
129
129
|
agent.status === 'active'
|
|
130
130
|
? chalk.green
|
|
131
|
+
: agent.status === 'fresh'
|
|
132
|
+
? chalk.cyan
|
|
133
|
+
: agent.status === 'merged'
|
|
134
|
+
? chalk.blue
|
|
131
135
|
: agent.status === 'missing'
|
|
132
136
|
? chalk.red
|
|
133
137
|
: chalk.yellow;
|
package/dist/commands/plan.js
CHANGED
|
@@ -10,7 +10,7 @@ const chalk = require('chalk');
|
|
|
10
10
|
const { safeAsync, outputResult } = require('../error-handler');
|
|
11
11
|
|
|
12
12
|
// Import spec resolution system
|
|
13
|
-
const { resolveSpec } = require('../utils/spec-resolver');
|
|
13
|
+
const { resolveSpec, loadSpecsRegistry } = require('../utils/spec-resolver');
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Plan templates for different spec types
|
|
@@ -86,15 +86,11 @@ const PLAN_TEMPLATES = {
|
|
|
86
86
|
* @returns {Promise<Object|null>} Spec data or null
|
|
87
87
|
*/
|
|
88
88
|
async function loadSpecForPlanning(specId) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return resolved.spec;
|
|
95
|
-
} catch (error) {
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
89
|
+
const resolved = await resolveSpec({
|
|
90
|
+
specId,
|
|
91
|
+
warnLegacy: false,
|
|
92
|
+
});
|
|
93
|
+
return resolved.spec;
|
|
98
94
|
}
|
|
99
95
|
|
|
100
96
|
/**
|
|
@@ -398,21 +394,18 @@ async function planCommand(action, options = {}) {
|
|
|
398
394
|
|
|
399
395
|
if (status.specCount === 1) {
|
|
400
396
|
// Use the single spec automatically
|
|
401
|
-
const registry = await
|
|
397
|
+
const registry = await loadSpecsRegistry();
|
|
402
398
|
const singleSpecId = Object.keys(registry.specs)[0];
|
|
403
399
|
console.log(chalk.blue(`Auto-detected single spec: ${singleSpecId}`));
|
|
404
400
|
|
|
405
401
|
const spec = await loadSpecForPlanning(singleSpecId);
|
|
406
|
-
if (!spec) {
|
|
407
|
-
throw new Error(`Auto-detected spec '${singleSpecId}' could not be loaded`);
|
|
408
|
-
}
|
|
409
|
-
|
|
410
402
|
await generateAndDisplayPlan(spec, singleSpecId, options);
|
|
411
403
|
} else if (status.specCount > 1) {
|
|
404
|
+
const registry = await loadSpecsRegistry();
|
|
412
405
|
throw new Error(
|
|
413
406
|
'Multiple specs detected. Please specify which one: caws plan generate --spec-id <id>\n' +
|
|
414
407
|
'Available specs: ' +
|
|
415
|
-
Object.keys(
|
|
408
|
+
Object.keys(registry.specs || {}).join(', ')
|
|
416
409
|
);
|
|
417
410
|
} else {
|
|
418
411
|
throw new Error('No specs found. Create a spec first: caws specs create <id>');
|
|
@@ -420,9 +413,6 @@ async function planCommand(action, options = {}) {
|
|
|
420
413
|
} else {
|
|
421
414
|
// Load spec for planning
|
|
422
415
|
const spec = await loadSpecForPlanning(specId);
|
|
423
|
-
if (!spec) {
|
|
424
|
-
throw new Error(`Spec '${specId}' not found`);
|
|
425
|
-
}
|
|
426
416
|
|
|
427
417
|
return await generateAndDisplayPlan(spec, specId, options);
|
|
428
418
|
}
|
|
@@ -12,6 +12,41 @@ const crypto = require('crypto');
|
|
|
12
12
|
const yaml = require('js-yaml');
|
|
13
13
|
const { execSync } = require('child_process');
|
|
14
14
|
const { commandWrapper } = require('../utils/command-wrapper');
|
|
15
|
+
const { resolveSpec } = require('../utils/spec-resolver');
|
|
16
|
+
|
|
17
|
+
async function resolveProvenanceSpec(options = {}) {
|
|
18
|
+
try {
|
|
19
|
+
return await resolveSpec({
|
|
20
|
+
specId: options.specId,
|
|
21
|
+
specFile: options.specFile,
|
|
22
|
+
warnLegacy: false,
|
|
23
|
+
});
|
|
24
|
+
} catch (error) {
|
|
25
|
+
const shouldFallbackToLegacy =
|
|
26
|
+
!options.specId &&
|
|
27
|
+
!options.specFile &&
|
|
28
|
+
error.message.includes('schema violations');
|
|
29
|
+
|
|
30
|
+
if (!shouldFallbackToLegacy) {
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const legacyPath = path.join(process.cwd(), '.caws', 'working-spec.yaml');
|
|
35
|
+
if (!(await fs.pathExists(legacyPath))) {
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const legacyContent = await fs.readFile(legacyPath, 'utf8');
|
|
40
|
+
const legacySpec = yaml.load(legacyContent);
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
path: legacyPath,
|
|
44
|
+
type: 'legacy',
|
|
45
|
+
spec: legacySpec,
|
|
46
|
+
degradedValidation: true,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
15
50
|
|
|
16
51
|
/**
|
|
17
52
|
* Get quality gates status from saved report
|
|
@@ -90,14 +125,8 @@ async function updateProvenance(options) {
|
|
|
90
125
|
// Ensure output directory exists
|
|
91
126
|
await fs.ensureDir(output);
|
|
92
127
|
|
|
93
|
-
|
|
94
|
-
const
|
|
95
|
-
if (!(await fs.pathExists(specPath))) {
|
|
96
|
-
throw new Error('Working spec not found - not in CAWS project');
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const specContent = await fs.readFile(specPath, 'utf8');
|
|
100
|
-
const spec = yaml.load(specContent);
|
|
128
|
+
const resolved = await resolveProvenanceSpec(options);
|
|
129
|
+
const spec = resolved.spec;
|
|
101
130
|
|
|
102
131
|
// Load existing provenance chain
|
|
103
132
|
const provenanceChain = await loadProvenanceChain(output);
|
|
@@ -116,6 +145,9 @@ async function updateProvenance(options) {
|
|
|
116
145
|
title: spec.title,
|
|
117
146
|
risk_tier: spec.risk_tier,
|
|
118
147
|
mode: spec.mode,
|
|
148
|
+
type: resolved.type,
|
|
149
|
+
path: resolved.path,
|
|
150
|
+
status: spec.status || null,
|
|
119
151
|
waiver_ids: spec.waiver_ids || [],
|
|
120
152
|
},
|
|
121
153
|
quality_gates: getQualityGatesStatus(),
|
|
@@ -148,6 +180,10 @@ async function updateProvenance(options) {
|
|
|
148
180
|
|
|
149
181
|
if (!quiet) {
|
|
150
182
|
console.log(`Provenance updated for commit ${commit.substring(0, 8)}`);
|
|
183
|
+
console.log(` Spec: ${spec.id} (${resolved.type}) -> ${resolved.path}`);
|
|
184
|
+
if (resolved.degradedValidation) {
|
|
185
|
+
console.log(' Note: using legacy spec metadata despite schema validation issues');
|
|
186
|
+
}
|
|
151
187
|
console.log(` Chain length: ${provenanceChain.length} entries`);
|
|
152
188
|
console.log(` Hash: ${newEntry.hash.substring(0, 16)}...`);
|
|
153
189
|
}
|
|
@@ -929,17 +965,12 @@ async function initProvenance(options) {
|
|
|
929
965
|
await fs.ensureDir(output);
|
|
930
966
|
console.log(`Created provenance directory: ${output}`);
|
|
931
967
|
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
if (
|
|
935
|
-
console.log('');
|
|
936
|
-
console.log('Not in a CAWS project - missing working spec');
|
|
937
|
-
console.log('Run "caws init" first to create a CAWS project');
|
|
938
|
-
process.exit(1);
|
|
968
|
+
const resolved = await resolveProvenanceSpec(options);
|
|
969
|
+
console.log(`Found CAWS spec: ${resolved.spec.id} (${resolved.type})`);
|
|
970
|
+
if (resolved.degradedValidation) {
|
|
971
|
+
console.log(' Proceeding with legacy spec metadata despite schema validation issues');
|
|
939
972
|
}
|
|
940
973
|
|
|
941
|
-
console.log('Found CAWS working spec');
|
|
942
|
-
|
|
943
974
|
// Initialize empty chain
|
|
944
975
|
const initialChain = [];
|
|
945
976
|
await saveProvenanceChain(initialChain, output);
|
|
@@ -947,6 +978,11 @@ async function initProvenance(options) {
|
|
|
947
978
|
|
|
948
979
|
// Create environment configuration hints
|
|
949
980
|
const envConfig = {
|
|
981
|
+
spec: {
|
|
982
|
+
id: resolved.spec.id,
|
|
983
|
+
path: resolved.path,
|
|
984
|
+
type: resolved.type,
|
|
985
|
+
},
|
|
950
986
|
cursor_tracking_api: cursorApi || process.env.CURSOR_TRACKING_API || 'not_configured',
|
|
951
987
|
cursor_checkpoint_api: process.env.CURSOR_CHECKPOINT_API || 'not_configured',
|
|
952
988
|
cursor_project_id: process.env.CURSOR_PROJECT_ID || 'not_configured',
|