specweave 0.22.0 → 0.22.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.
- package/CLAUDE.md +373 -13
- package/README.md +5 -5
- package/bin/specweave.js +5 -8
- package/dist/plugins/specweave-github/lib/CodeValidator.d.ts +1 -1
- package/dist/plugins/specweave-github/lib/CodeValidator.js +1 -1
- package/dist/plugins/specweave-github/lib/github-client-v2.d.ts +10 -0
- package/dist/plugins/specweave-github/lib/github-client-v2.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-client-v2.js +26 -0
- package/dist/plugins/specweave-github/lib/github-client-v2.js.map +1 -1
- package/dist/plugins/specweave-github/lib/task-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/task-sync.js +7 -0
- package/dist/plugins/specweave-github/lib/task-sync.js.map +1 -1
- package/dist/src/cli/commands/migrate-to-profiles.d.ts +1 -0
- package/dist/src/cli/commands/migrate-to-profiles.d.ts.map +1 -1
- package/dist/src/cli/commands/migrate-to-profiles.js +12 -1
- package/dist/src/cli/commands/migrate-to-profiles.js.map +1 -1
- package/dist/src/cli/commands/next-command.d.ts +52 -0
- package/dist/src/cli/commands/next-command.d.ts.map +1 -0
- package/dist/src/cli/commands/next-command.js +204 -0
- package/dist/src/cli/commands/next-command.js.map +1 -0
- package/dist/src/cli/commands/repair-status-desync.d.ts +69 -0
- package/dist/src/cli/commands/repair-status-desync.d.ts.map +1 -0
- package/dist/src/cli/commands/repair-status-desync.js +221 -0
- package/dist/src/cli/commands/repair-status-desync.js.map +1 -0
- package/dist/src/cli/commands/sync-specs.d.ts +16 -0
- package/dist/src/cli/commands/sync-specs.d.ts.map +1 -0
- package/dist/src/cli/commands/sync-specs.js +130 -0
- package/dist/src/cli/commands/sync-specs.js.map +1 -0
- package/dist/src/cli/commands/validate-status-sync.d.ts +52 -0
- package/dist/src/cli/commands/validate-status-sync.d.ts.map +1 -0
- package/dist/src/cli/commands/validate-status-sync.js +176 -0
- package/dist/src/cli/commands/validate-status-sync.js.map +1 -0
- package/dist/src/cli/count-tasks.d.ts +20 -0
- package/dist/src/cli/count-tasks.d.ts.map +1 -0
- package/dist/src/cli/count-tasks.js +50 -0
- package/dist/src/cli/count-tasks.js.map +1 -0
- package/dist/src/cli/update-status-line.d.ts +16 -0
- package/dist/src/cli/update-status-line.d.ts.map +1 -0
- package/dist/src/cli/update-status-line.js +44 -0
- package/dist/src/cli/update-status-line.js.map +1 -0
- package/dist/src/config/ConfigManager.d.ts.map +1 -1
- package/dist/src/config/ConfigManager.js +2 -1
- package/dist/src/config/ConfigManager.js.map +1 -1
- package/dist/src/config/types.d.ts +50 -50
- package/dist/src/core/cicd/state-manager.d.ts +8 -0
- package/dist/src/core/cicd/state-manager.d.ts.map +1 -1
- package/dist/src/core/cicd/state-manager.js +60 -15
- package/dist/src/core/cicd/state-manager.js.map +1 -1
- package/dist/src/core/cost-tracker.d.ts.map +1 -1
- package/dist/src/core/cost-tracker.js +2 -1
- package/dist/src/core/cost-tracker.js.map +1 -1
- package/dist/src/core/iac/template-engine.d.ts.map +1 -1
- package/dist/src/core/iac/template-engine.js +28 -0
- package/dist/src/core/iac/template-engine.js.map +1 -1
- package/dist/src/core/iac/template-generator.d.ts +53 -0
- package/dist/src/core/iac/template-generator.d.ts.map +1 -0
- package/dist/src/core/iac/template-generator.js +125 -0
- package/dist/src/core/iac/template-generator.js.map +1 -0
- package/dist/src/core/increment/completion-validator.d.ts +56 -0
- package/dist/src/core/increment/completion-validator.d.ts.map +1 -0
- package/dist/src/core/increment/completion-validator.js +102 -0
- package/dist/src/core/increment/completion-validator.js.map +1 -0
- package/dist/src/core/increment/metadata-manager.d.ts.map +1 -1
- package/dist/src/core/increment/metadata-manager.js +10 -0
- package/dist/src/core/increment/metadata-manager.js.map +1 -1
- package/dist/src/core/increment/spec-frontmatter-updater.d.ts +78 -0
- package/dist/src/core/increment/spec-frontmatter-updater.d.ts.map +1 -0
- package/dist/src/core/increment/spec-frontmatter-updater.js +152 -0
- package/dist/src/core/increment/spec-frontmatter-updater.js.map +1 -0
- package/dist/src/core/increment/status-auto-transition.js +3 -3
- package/dist/src/core/increment/status-auto-transition.js.map +1 -1
- package/dist/src/core/living-docs/CodeValidator.js +1 -1
- package/dist/src/core/living-docs/CodeValidator.js.map +1 -1
- package/dist/src/core/living-docs/content-distributor.d.ts.map +1 -1
- package/dist/src/core/living-docs/content-distributor.js +11 -1
- package/dist/src/core/living-docs/content-distributor.js.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.d.ts +166 -0
- package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -0
- package/dist/src/core/living-docs/living-docs-sync.js +727 -0
- package/dist/src/core/living-docs/living-docs-sync.js.map +1 -0
- package/dist/src/core/living-docs/task-project-specific-generator.d.ts +7 -3
- package/dist/src/core/living-docs/task-project-specific-generator.d.ts.map +1 -1
- package/dist/src/core/living-docs/task-project-specific-generator.js +40 -24
- package/dist/src/core/living-docs/task-project-specific-generator.js.map +1 -1
- package/dist/src/core/plugin-loader.d.ts +7 -0
- package/dist/src/core/plugin-loader.d.ts.map +1 -1
- package/dist/src/core/plugin-loader.js +18 -1
- package/dist/src/core/plugin-loader.js.map +1 -1
- package/dist/src/core/serverless/platform-data-loader.d.ts +8 -0
- package/dist/src/core/serverless/platform-data-loader.d.ts.map +1 -1
- package/dist/src/core/serverless/platform-data-loader.js +14 -0
- package/dist/src/core/serverless/platform-data-loader.js.map +1 -1
- package/dist/src/core/serverless/types.d.ts +1 -1
- package/dist/src/core/serverless/types.d.ts.map +1 -1
- package/dist/src/core/status-line/status-line-manager.d.ts +7 -2
- package/dist/src/core/status-line/status-line-manager.d.ts.map +1 -1
- package/dist/src/core/status-line/status-line-manager.js +47 -18
- package/dist/src/core/status-line/status-line-manager.js.map +1 -1
- package/dist/src/core/status-line/status-line-updater.d.ts +67 -0
- package/dist/src/core/status-line/status-line-updater.d.ts.map +1 -0
- package/dist/src/core/status-line/status-line-updater.js +203 -0
- package/dist/src/core/status-line/status-line-updater.js.map +1 -0
- package/dist/src/core/status-line/task-counter.d.ts +69 -0
- package/dist/src/core/status-line/task-counter.d.ts.map +1 -0
- package/dist/src/core/status-line/task-counter.js +107 -0
- package/dist/src/core/status-line/task-counter.js.map +1 -0
- package/dist/src/core/status-line/types.d.ts +19 -5
- package/dist/src/core/status-line/types.d.ts.map +1 -1
- package/dist/src/core/status-line/types.js +3 -3
- package/dist/src/core/status-line/types.js.map +1 -1
- package/dist/src/core/workflow/autonomous-executor.d.ts +111 -0
- package/dist/src/core/workflow/autonomous-executor.d.ts.map +1 -0
- package/dist/src/core/workflow/autonomous-executor.js +275 -0
- package/dist/src/core/workflow/autonomous-executor.js.map +1 -0
- package/dist/src/core/workflow/backlog-scanner.d.ts +94 -0
- package/dist/src/core/workflow/backlog-scanner.d.ts.map +1 -0
- package/dist/src/core/workflow/backlog-scanner.js +170 -0
- package/dist/src/core/workflow/backlog-scanner.js.map +1 -0
- package/dist/src/core/workflow/command-invoker.d.ts +86 -0
- package/dist/src/core/workflow/command-invoker.d.ts.map +1 -0
- package/dist/src/core/workflow/command-invoker.js +131 -0
- package/dist/src/core/workflow/command-invoker.js.map +1 -0
- package/dist/src/core/workflow/cost-estimator.d.ts +120 -0
- package/dist/src/core/workflow/cost-estimator.d.ts.map +1 -0
- package/dist/src/core/workflow/cost-estimator.js +222 -0
- package/dist/src/core/workflow/cost-estimator.js.map +1 -0
- package/dist/src/core/workflow/index.d.ts +20 -0
- package/dist/src/core/workflow/index.d.ts.map +1 -0
- package/dist/src/core/workflow/index.js +24 -0
- package/dist/src/core/workflow/index.js.map +1 -0
- package/dist/src/core/workflow/state-manager.d.ts +107 -0
- package/dist/src/core/workflow/state-manager.d.ts.map +1 -0
- package/dist/src/core/workflow/state-manager.js +126 -0
- package/dist/src/core/workflow/state-manager.js.map +1 -0
- package/dist/src/core/workflow/workflow-orchestrator.d.ts +93 -0
- package/dist/src/core/workflow/workflow-orchestrator.d.ts.map +1 -0
- package/dist/src/core/workflow/workflow-orchestrator.js +195 -0
- package/dist/src/core/workflow/workflow-orchestrator.js.map +1 -0
- package/dist/src/init/architecture/types.d.ts +10 -10
- package/dist/src/metrics/dora-calculator.js +2 -2
- package/dist/src/metrics/dora-calculator.js.map +1 -1
- package/dist/src/utils/pricing-constants.d.ts +5 -2
- package/dist/src/utils/pricing-constants.d.ts.map +1 -1
- package/dist/src/utils/pricing-constants.js +3 -2
- package/dist/src/utils/pricing-constants.js.map +1 -1
- package/package.json +4 -4
- package/plugins/specweave/agents/infrastructure/AGENT.md +88 -46
- package/plugins/specweave/agents/pm/AGENT.md +58 -1
- package/plugins/specweave/commands/specweave-archive-features.md +1 -1
- package/plugins/specweave/commands/specweave-archive-increments.md +1 -1
- package/plugins/specweave/commands/specweave-check-hooks.md +5 -0
- package/plugins/specweave/commands/specweave-done.md +72 -4
- package/plugins/specweave/commands/specweave-plan.md +1 -1
- package/plugins/specweave/commands/specweave-progress.md +108 -379
- package/plugins/specweave/commands/specweave-reopen.md +30 -3
- package/plugins/specweave/commands/specweave-restore-feature.md +1 -1
- package/plugins/specweave/commands/specweave-sync-docs.md +71 -4
- package/plugins/specweave/commands/specweave-sync-specs.md +20 -48
- package/plugins/specweave/commands/specweave-update-status.md +151 -0
- package/plugins/specweave/hooks/lib/update-status-line.sh +78 -41
- package/plugins/specweave/hooks/lib/validate-spec-status.sh +163 -0
- package/plugins/specweave/hooks/user-prompt-submit.sh +38 -35
- package/plugins/specweave/hooks/validate-increment-completion.sh +113 -0
- package/plugins/specweave/lib/hooks/update-tasks-md.js +52 -9
- package/plugins/specweave/lib/hooks/update-tasks-md.ts +77 -16
- package/plugins/specweave/templates/iac/aws-lambda/defaults.json +24 -0
- package/plugins/specweave/templates/iac/aws-lambda/templates/README.md.hbs +260 -0
- package/plugins/specweave/templates/iac/aws-lambda/templates/environments/dev.tfvars.hbs +34 -0
- package/plugins/specweave/templates/iac/aws-lambda/templates/environments/prod.tfvars.hbs +37 -0
- package/plugins/specweave/templates/iac/aws-lambda/templates/environments/staging.tfvars.hbs +35 -0
- package/plugins/specweave/templates/iac/aws-lambda/templates/outputs.tf.hbs +77 -0
- package/plugins/specweave/templates/iac/aws-lambda/templates/providers.tf.hbs +36 -0
- package/plugins/specweave/templates/iac/aws-lambda/templates/variables.tf.hbs +115 -0
- package/plugins/specweave/templates/iac/azure-functions/defaults.json +25 -0
- package/plugins/specweave/templates/iac/azure-functions/templates/README.md.hbs +268 -0
- package/plugins/specweave/templates/iac/azure-functions/templates/environments/dev.tfvars.hbs +34 -0
- package/plugins/specweave/templates/iac/azure-functions/templates/environments/prod.tfvars.hbs +46 -0
- package/plugins/specweave/templates/iac/azure-functions/templates/environments/staging.tfvars.hbs +34 -0
- package/plugins/specweave/templates/iac/azure-functions/templates/main.tf.hbs +225 -0
- package/plugins/specweave/templates/iac/azure-functions/templates/outputs.tf.hbs +89 -0
- package/plugins/specweave/templates/iac/azure-functions/templates/provider.tf.hbs +27 -0
- package/plugins/specweave/templates/iac/azure-functions/templates/providers.tf.hbs +35 -0
- package/plugins/specweave/templates/iac/azure-functions/templates/variables.tf.hbs +124 -0
- package/plugins/specweave/templates/iac/firebase/defaults.json +29 -0
- package/plugins/specweave/templates/iac/firebase/templates/README.md.hbs +35 -0
- package/plugins/specweave/templates/iac/firebase/templates/environments/dev.tfvars.hbs +7 -0
- package/plugins/specweave/templates/iac/firebase/templates/environments/prod.tfvars.hbs +7 -0
- package/plugins/specweave/templates/iac/firebase/templates/environments/staging.tfvars.hbs +7 -0
- package/plugins/specweave/templates/iac/firebase/templates/main.tf.hbs +90 -0
- package/plugins/specweave/templates/iac/firebase/templates/outputs.tf.hbs +15 -0
- package/plugins/specweave/templates/iac/firebase/templates/providers.tf.hbs +23 -0
- package/plugins/specweave/templates/iac/firebase/templates/variables.tf.hbs +42 -0
- package/plugins/specweave/templates/iac/gcp-cloud-functions/defaults.json +26 -0
- package/plugins/specweave/templates/iac/gcp-cloud-functions/templates/README.md.hbs +299 -0
- package/plugins/specweave/templates/iac/gcp-cloud-functions/templates/environments/dev.tfvars.hbs +36 -0
- package/plugins/specweave/templates/iac/gcp-cloud-functions/templates/environments/prod.tfvars.hbs +48 -0
- package/plugins/specweave/templates/iac/gcp-cloud-functions/templates/environments/staging.tfvars.hbs +41 -0
- package/plugins/specweave/templates/iac/gcp-cloud-functions/templates/main.tf.hbs +192 -0
- package/plugins/specweave/templates/iac/gcp-cloud-functions/templates/outputs.tf.hbs +66 -0
- package/plugins/specweave/templates/iac/gcp-cloud-functions/templates/providers.tf.hbs +25 -0
- package/plugins/specweave/templates/iac/gcp-cloud-functions/templates/variables.tf.hbs +119 -0
- package/plugins/specweave/templates/iac/supabase/defaults.json +15 -0
- package/plugins/specweave/templates/iac/supabase/templates/README.md.hbs +46 -0
- package/plugins/specweave/templates/iac/supabase/templates/main.tf.hbs +50 -0
- package/plugins/specweave-ado/lib/ado-multi-project-sync.js +0 -1
- package/plugins/specweave-github/agents/github-manager/AGENT.md +39 -7
- package/plugins/specweave-github/commands/specweave-github-cleanup-duplicates.md +21 -0
- package/plugins/specweave-github/commands/specweave-github-create-issue.md +5 -5
- package/plugins/specweave-github/lib/CodeValidator.ts +1 -1
- package/plugins/specweave-github/lib/github-client-v2.js +29 -0
- package/plugins/specweave-github/lib/github-client-v2.ts +30 -0
- package/plugins/specweave-github/lib/task-sync.js +4 -0
- package/plugins/specweave-github/lib/task-sync.ts +7 -0
- package/src/templates/CLAUDE.md.template +31 -0
- package/dist/src/core/living-docs/ThreeLayerSyncManager.d.ts +0 -116
- package/dist/src/core/living-docs/ThreeLayerSyncManager.d.ts.map +0 -1
- package/dist/src/core/living-docs/ThreeLayerSyncManager.js +0 -356
- package/dist/src/core/living-docs/ThreeLayerSyncManager.js.map +0 -1
- package/plugins/specweave-ado/lib/enhanced-ado-sync.js +0 -170
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +0 -1200
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { validateStatusSync } from './validate-status-sync.js';
|
|
3
|
+
import { SpecFrontmatterUpdater } from '../../core/increment/spec-frontmatter-updater.js';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import fs from 'fs-extra';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
/**
|
|
8
|
+
* Create backup of spec.md before repair
|
|
9
|
+
*/
|
|
10
|
+
export async function createBackup(incrementId) {
|
|
11
|
+
const specPath = path.join(process.cwd(), '.specweave', 'increments', incrementId, 'spec.md');
|
|
12
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
13
|
+
const backupPath = `${specPath}.backup-${timestamp}`;
|
|
14
|
+
await fs.copyFile(specPath, backupPath);
|
|
15
|
+
return backupPath;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Repair a single desync
|
|
19
|
+
*/
|
|
20
|
+
export async function repairDesync(desync, options = {}) {
|
|
21
|
+
const { dryRun = false, createBackup: shouldBackup = true } = options;
|
|
22
|
+
// Dry-run: preview only
|
|
23
|
+
if (dryRun) {
|
|
24
|
+
return {
|
|
25
|
+
incrementId: desync.incrementId,
|
|
26
|
+
oldStatus: desync.specStatus,
|
|
27
|
+
newStatus: desync.metadataStatus,
|
|
28
|
+
success: true,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
// Create backup if enabled
|
|
33
|
+
let backupPath;
|
|
34
|
+
if (shouldBackup) {
|
|
35
|
+
backupPath = await createBackup(desync.incrementId);
|
|
36
|
+
}
|
|
37
|
+
// Update spec.md to match metadata.json
|
|
38
|
+
await SpecFrontmatterUpdater.updateStatus(desync.incrementId, desync.metadataStatus);
|
|
39
|
+
return {
|
|
40
|
+
incrementId: desync.incrementId,
|
|
41
|
+
oldStatus: desync.specStatus,
|
|
42
|
+
newStatus: desync.metadataStatus,
|
|
43
|
+
success: true,
|
|
44
|
+
backupPath,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
return {
|
|
49
|
+
incrementId: desync.incrementId,
|
|
50
|
+
oldStatus: desync.specStatus,
|
|
51
|
+
newStatus: desync.metadataStatus,
|
|
52
|
+
success: false,
|
|
53
|
+
error: error instanceof Error ? error.message : String(error),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Repair all desyncs or a specific increment
|
|
59
|
+
*/
|
|
60
|
+
export async function repairStatusDesync(options = {}) {
|
|
61
|
+
const { all = false, incrementId, dryRun = false } = options;
|
|
62
|
+
// Get desyncs from validation
|
|
63
|
+
const validation = await validateStatusSync();
|
|
64
|
+
let desyncsToRepair = [];
|
|
65
|
+
if (incrementId) {
|
|
66
|
+
// Repair specific increment
|
|
67
|
+
const desync = validation.desyncs.find((d) => d.incrementId === incrementId);
|
|
68
|
+
if (!desync) {
|
|
69
|
+
throw new Error(`No desync found for increment ${incrementId}`);
|
|
70
|
+
}
|
|
71
|
+
desyncsToRepair = [desync];
|
|
72
|
+
}
|
|
73
|
+
else if (all) {
|
|
74
|
+
// Repair all desyncs
|
|
75
|
+
desyncsToRepair = validation.desyncs;
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
throw new Error('Must specify either --all or <incrementId>');
|
|
79
|
+
}
|
|
80
|
+
const results = [];
|
|
81
|
+
for (const desync of desyncsToRepair) {
|
|
82
|
+
const result = await repairDesync(desync, options);
|
|
83
|
+
results.push(result);
|
|
84
|
+
}
|
|
85
|
+
const repaired = results.filter((r) => r.success).length;
|
|
86
|
+
const failed = results.filter((r) => !r.success).length;
|
|
87
|
+
return {
|
|
88
|
+
total: results.length,
|
|
89
|
+
repaired,
|
|
90
|
+
failed,
|
|
91
|
+
results,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Write audit log
|
|
96
|
+
*/
|
|
97
|
+
export async function writeAuditLog(results) {
|
|
98
|
+
const logsDir = path.join(process.cwd(), '.specweave', 'logs');
|
|
99
|
+
await fs.ensureDir(logsDir);
|
|
100
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
101
|
+
const logPath = path.join(logsDir, `status-desync-repair-${timestamp}.json`);
|
|
102
|
+
const entries = results.map((result) => ({
|
|
103
|
+
timestamp: new Date().toISOString(),
|
|
104
|
+
incrementId: result.incrementId,
|
|
105
|
+
oldStatus: result.oldStatus,
|
|
106
|
+
newStatus: result.newStatus,
|
|
107
|
+
success: result.success,
|
|
108
|
+
error: result.error,
|
|
109
|
+
backupPath: result.backupPath,
|
|
110
|
+
}));
|
|
111
|
+
await fs.writeFile(logPath, JSON.stringify(entries, null, 2), 'utf-8');
|
|
112
|
+
return logPath;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Format repair report
|
|
116
|
+
*/
|
|
117
|
+
export function formatRepairReport(result, dryRun = false) {
|
|
118
|
+
const lines = [];
|
|
119
|
+
lines.push('');
|
|
120
|
+
lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
121
|
+
if (dryRun) {
|
|
122
|
+
lines.push(chalk.cyan('DRY RUN: Status Desync Repair Preview'));
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
lines.push('Status Desync Repair Report');
|
|
126
|
+
}
|
|
127
|
+
lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
128
|
+
lines.push('');
|
|
129
|
+
lines.push(`Total desyncs: ${result.total}`);
|
|
130
|
+
if (dryRun) {
|
|
131
|
+
lines.push(chalk.cyan(`Would repair: ${result.repaired}`));
|
|
132
|
+
if (result.failed > 0) {
|
|
133
|
+
lines.push(chalk.yellow(`Would fail: ${result.failed}`));
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
lines.push(chalk.green(`Repaired: ${result.repaired}`));
|
|
138
|
+
if (result.failed > 0) {
|
|
139
|
+
lines.push(chalk.red(`Failed: ${result.failed}`));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
lines.push('');
|
|
143
|
+
for (const repair of result.results) {
|
|
144
|
+
if (dryRun) {
|
|
145
|
+
lines.push(chalk.cyan(`DRY RUN: Would update ${chalk.bold(repair.incrementId)} from "${repair.oldStatus}" to "${repair.newStatus}"`));
|
|
146
|
+
}
|
|
147
|
+
else if (repair.success) {
|
|
148
|
+
lines.push(chalk.green(`✅ Repaired ${chalk.bold(repair.incrementId)}: "${repair.oldStatus}" → "${repair.newStatus}"`));
|
|
149
|
+
if (repair.backupPath) {
|
|
150
|
+
lines.push(` Backup: ${repair.backupPath}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
lines.push(chalk.red(`❌ Failed ${chalk.bold(repair.incrementId)}: "${repair.oldStatus}" → "${repair.newStatus}"`));
|
|
155
|
+
if (repair.error) {
|
|
156
|
+
lines.push(` Error: ${repair.error}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
lines.push('');
|
|
161
|
+
if (!dryRun && result.repaired > 0) {
|
|
162
|
+
lines.push(chalk.green(`✅ ${result.repaired} desync(s) repaired successfully!`));
|
|
163
|
+
lines.push('');
|
|
164
|
+
lines.push('To verify:');
|
|
165
|
+
lines.push(chalk.cyan(' npx specweave validate-status-sync'));
|
|
166
|
+
}
|
|
167
|
+
else if (dryRun) {
|
|
168
|
+
lines.push(chalk.cyan('To apply these changes:'));
|
|
169
|
+
lines.push(chalk.cyan(' npx specweave repair-status-desync --all'));
|
|
170
|
+
}
|
|
171
|
+
lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
172
|
+
lines.push('');
|
|
173
|
+
return lines.join('\n');
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Main CLI entry point
|
|
177
|
+
*/
|
|
178
|
+
export async function main(argv = process.argv) {
|
|
179
|
+
try {
|
|
180
|
+
// Parse CLI arguments
|
|
181
|
+
const args = argv.slice(2);
|
|
182
|
+
const options = {
|
|
183
|
+
all: args.includes('--all'),
|
|
184
|
+
dryRun: args.includes('--dry-run'),
|
|
185
|
+
createBackup: !args.includes('--no-backup'),
|
|
186
|
+
};
|
|
187
|
+
// Check for increment ID (non-flag argument)
|
|
188
|
+
const incrementIdArg = args.find((arg) => !arg.startsWith('--'));
|
|
189
|
+
if (incrementIdArg) {
|
|
190
|
+
options.incrementId = incrementIdArg;
|
|
191
|
+
}
|
|
192
|
+
if (options.dryRun) {
|
|
193
|
+
console.log(chalk.cyan('🔍 DRY RUN MODE: No files will be modified\n'));
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
console.log('🔧 Repairing status desyncs...\n');
|
|
197
|
+
}
|
|
198
|
+
const result = await repairStatusDesync(options);
|
|
199
|
+
const report = formatRepairReport(result, options.dryRun);
|
|
200
|
+
console.log(report);
|
|
201
|
+
// Write audit log (skip in dry-run mode)
|
|
202
|
+
if (!options.dryRun && result.total > 0) {
|
|
203
|
+
const logPath = await writeAuditLog(result.results);
|
|
204
|
+
console.log(chalk.gray(`Audit log: ${logPath}\n`));
|
|
205
|
+
}
|
|
206
|
+
// Exit with error code if any repairs failed
|
|
207
|
+
if (result.failed > 0 && !options.dryRun) {
|
|
208
|
+
process.exit(1);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
console.error(chalk.red('Error during repair:'));
|
|
213
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
// Run if called directly
|
|
218
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
219
|
+
main();
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=repair-status-desync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repair-status-desync.js","sourceRoot":"","sources":["../../../../src/cli/commands/repair-status-desync.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Command: sync-specs
|
|
3
|
+
*
|
|
4
|
+
* Syncs increment specifications to living docs structure
|
|
5
|
+
*/
|
|
6
|
+
export interface SyncSpecsArgs {
|
|
7
|
+
incrementId?: string;
|
|
8
|
+
all?: boolean;
|
|
9
|
+
force?: boolean;
|
|
10
|
+
dryRun?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Sync specs command entry point
|
|
14
|
+
*/
|
|
15
|
+
export declare function syncSpecs(args: string[]): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=sync-specs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-specs.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/sync-specs.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAiE7D"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Command: sync-specs
|
|
3
|
+
*
|
|
4
|
+
* Syncs increment specifications to living docs structure
|
|
5
|
+
*/
|
|
6
|
+
import fs from 'fs-extra';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import { LivingDocsSync } from '../../core/living-docs/living-docs-sync.js';
|
|
9
|
+
/**
|
|
10
|
+
* Sync specs command entry point
|
|
11
|
+
*/
|
|
12
|
+
export async function syncSpecs(args) {
|
|
13
|
+
const parsedArgs = parseArgs(args);
|
|
14
|
+
const projectRoot = process.cwd();
|
|
15
|
+
const sync = new LivingDocsSync(projectRoot);
|
|
16
|
+
try {
|
|
17
|
+
if (parsedArgs.all) {
|
|
18
|
+
// Sync all completed increments
|
|
19
|
+
console.log('🔄 Syncing all completed increments...\n');
|
|
20
|
+
const increments = await findCompletedIncrements(projectRoot);
|
|
21
|
+
let successCount = 0;
|
|
22
|
+
let failCount = 0;
|
|
23
|
+
for (const incrementId of increments) {
|
|
24
|
+
try {
|
|
25
|
+
const result = await sync.syncIncrement(incrementId, {
|
|
26
|
+
dryRun: parsedArgs.dryRun,
|
|
27
|
+
force: parsedArgs.force
|
|
28
|
+
});
|
|
29
|
+
if (result.success) {
|
|
30
|
+
successCount++;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
failCount++;
|
|
34
|
+
console.error(` ❌ Failed: ${result.errors.join(', ')}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
failCount++;
|
|
39
|
+
console.error(` ❌ Failed to sync ${incrementId}:`, error);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
console.log(`\n✅ Sync complete: ${successCount} succeeded, ${failCount} failed`);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
// Sync single increment
|
|
46
|
+
const incrementId = parsedArgs.incrementId || await findLatestCompletedIncrement(projectRoot);
|
|
47
|
+
if (!incrementId) {
|
|
48
|
+
console.error('❌ No increment specified and no completed increments found');
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
const result = await sync.syncIncrement(incrementId, {
|
|
52
|
+
dryRun: parsedArgs.dryRun,
|
|
53
|
+
force: parsedArgs.force
|
|
54
|
+
});
|
|
55
|
+
if (!result.success) {
|
|
56
|
+
console.error('❌ Sync failed:', result.errors.join(', '));
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
console.log('\n✅ Sync complete!');
|
|
60
|
+
if (parsedArgs.dryRun) {
|
|
61
|
+
console.log(' (Dry run - no files were actually created)');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
console.error('❌ Sync failed:', error);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Parse command-line arguments
|
|
72
|
+
*/
|
|
73
|
+
function parseArgs(args) {
|
|
74
|
+
const parsed = {};
|
|
75
|
+
for (let i = 0; i < args.length; i++) {
|
|
76
|
+
const arg = args[i];
|
|
77
|
+
if (arg === '--all') {
|
|
78
|
+
parsed.all = true;
|
|
79
|
+
}
|
|
80
|
+
else if (arg === '--force') {
|
|
81
|
+
parsed.force = true;
|
|
82
|
+
}
|
|
83
|
+
else if (arg === '--dry-run') {
|
|
84
|
+
parsed.dryRun = true;
|
|
85
|
+
}
|
|
86
|
+
else if (!arg.startsWith('--')) {
|
|
87
|
+
// Assume it's the increment ID
|
|
88
|
+
parsed.incrementId = arg;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return parsed;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Find all completed increments
|
|
95
|
+
*/
|
|
96
|
+
async function findCompletedIncrements(projectRoot) {
|
|
97
|
+
const incrementsDir = path.join(projectRoot, '.specweave/increments');
|
|
98
|
+
if (!await fs.pathExists(incrementsDir)) {
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
const entries = await fs.readdir(incrementsDir);
|
|
102
|
+
const completed = [];
|
|
103
|
+
for (const entry of entries) {
|
|
104
|
+
if (!entry.match(/^\d{4}-/))
|
|
105
|
+
continue;
|
|
106
|
+
const metadataPath = path.join(incrementsDir, entry, 'metadata.json');
|
|
107
|
+
const specPath = path.join(incrementsDir, entry, 'spec.md');
|
|
108
|
+
// Skip if no spec.md
|
|
109
|
+
if (!await fs.pathExists(specPath)) {
|
|
110
|
+
console.log(` ⚠️ Skipping ${entry} (no spec.md)`);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
// Check if completed
|
|
114
|
+
if (await fs.pathExists(metadataPath)) {
|
|
115
|
+
const metadata = await fs.readJson(metadataPath);
|
|
116
|
+
if (metadata.status === 'completed') {
|
|
117
|
+
completed.push(entry);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return completed.sort();
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Find latest completed increment
|
|
125
|
+
*/
|
|
126
|
+
async function findLatestCompletedIncrement(projectRoot) {
|
|
127
|
+
const completed = await findCompletedIncrements(projectRoot);
|
|
128
|
+
return completed.length > 0 ? completed[completed.length - 1] : null;
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=sync-specs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-specs.js","sourceRoot":"","sources":["../../../../src/cli/commands/sync-specs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { IncrementStatus } from '../../core/types/increment-metadata.js';
|
|
3
|
+
/**
|
|
4
|
+
* Severity levels for status desyncs
|
|
5
|
+
*/
|
|
6
|
+
export declare enum DesyncSeverity {
|
|
7
|
+
CRITICAL = "CRITICAL",
|
|
8
|
+
HIGH = "HIGH",
|
|
9
|
+
MEDIUM = "MEDIUM",
|
|
10
|
+
LOW = "LOW"
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Desync detection result
|
|
14
|
+
*/
|
|
15
|
+
export interface DesyncResult {
|
|
16
|
+
incrementId: string;
|
|
17
|
+
metadataStatus: IncrementStatus;
|
|
18
|
+
specStatus: IncrementStatus;
|
|
19
|
+
severity: DesyncSeverity;
|
|
20
|
+
impact: string;
|
|
21
|
+
fix: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Calculate severity of a status desync
|
|
25
|
+
*/
|
|
26
|
+
export declare function calculateSeverity(metadataStatus: IncrementStatus, specStatus: IncrementStatus): {
|
|
27
|
+
severity: DesyncSeverity;
|
|
28
|
+
impact: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Validate status sync across all increments
|
|
32
|
+
*/
|
|
33
|
+
export declare function validateStatusSync(): Promise<{
|
|
34
|
+
total: number;
|
|
35
|
+
synced: number;
|
|
36
|
+
desynced: number;
|
|
37
|
+
desyncs: DesyncResult[];
|
|
38
|
+
}>;
|
|
39
|
+
/**
|
|
40
|
+
* Format and print validation report
|
|
41
|
+
*/
|
|
42
|
+
export declare function formatReport(result: {
|
|
43
|
+
total: number;
|
|
44
|
+
synced: number;
|
|
45
|
+
desynced: number;
|
|
46
|
+
desyncs: DesyncResult[];
|
|
47
|
+
}): string;
|
|
48
|
+
/**
|
|
49
|
+
* Main CLI entry point
|
|
50
|
+
*/
|
|
51
|
+
export declare function main(): Promise<void>;
|
|
52
|
+
//# sourceMappingURL=validate-status-sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-status-sync.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/validate-status-sync.ts"],"names":[],"mappings":";AAIA,OAAO,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAC;AAGzE;;GAEG;AACH,oBAAY,cAAc;IACxB,QAAQ,aAAa;IACrB,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,GAAG,QAAQ;CACZ;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,eAAe,CAAC;IAChC,UAAU,EAAE,eAAe,CAAC;IAC5B,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,cAAc,EAAE,eAAe,EAC/B,UAAU,EAAE,eAAe,GAC1B;IAAE,QAAQ,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CA6C9C;AAED;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB,CAAC,CAqDD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB,GAAG,MAAM,CAiDT;AAED;;GAEG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAkB1C"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { MetadataManager } from '../../core/increment/metadata-manager.js';
|
|
3
|
+
import { SpecFrontmatterUpdater } from '../../core/increment/spec-frontmatter-updater.js';
|
|
4
|
+
import { IncrementStatus } from '../../core/types/increment-metadata.js';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
/**
|
|
7
|
+
* Severity levels for status desyncs
|
|
8
|
+
*/
|
|
9
|
+
export var DesyncSeverity;
|
|
10
|
+
(function (DesyncSeverity) {
|
|
11
|
+
DesyncSeverity["CRITICAL"] = "CRITICAL";
|
|
12
|
+
DesyncSeverity["HIGH"] = "HIGH";
|
|
13
|
+
DesyncSeverity["MEDIUM"] = "MEDIUM";
|
|
14
|
+
DesyncSeverity["LOW"] = "LOW";
|
|
15
|
+
})(DesyncSeverity || (DesyncSeverity = {}));
|
|
16
|
+
/**
|
|
17
|
+
* Calculate severity of a status desync
|
|
18
|
+
*/
|
|
19
|
+
export function calculateSeverity(metadataStatus, specStatus) {
|
|
20
|
+
// CRITICAL: Status line will show wrong increment (completed marked as active in spec.md)
|
|
21
|
+
if ((metadataStatus === IncrementStatus.COMPLETED ||
|
|
22
|
+
metadataStatus === IncrementStatus.PAUSED ||
|
|
23
|
+
metadataStatus === IncrementStatus.ABANDONED) &&
|
|
24
|
+
specStatus === IncrementStatus.ACTIVE) {
|
|
25
|
+
return {
|
|
26
|
+
severity: DesyncSeverity.CRITICAL,
|
|
27
|
+
impact: 'Status line shows completed/paused/abandoned increment as active. Developers see wrong current work.',
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
// HIGH: Inverse desync - metadata says active but spec says completed
|
|
31
|
+
if (metadataStatus === IncrementStatus.ACTIVE &&
|
|
32
|
+
(specStatus === IncrementStatus.COMPLETED ||
|
|
33
|
+
specStatus === IncrementStatus.PAUSED ||
|
|
34
|
+
specStatus === IncrementStatus.ABANDONED)) {
|
|
35
|
+
return {
|
|
36
|
+
severity: DesyncSeverity.HIGH,
|
|
37
|
+
impact: 'Active increment appears completed/paused in spec.md. External tools may close issue prematurely.',
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
// MEDIUM: Paused/completed confusion
|
|
41
|
+
if (metadataStatus === IncrementStatus.PAUSED &&
|
|
42
|
+
(specStatus === IncrementStatus.COMPLETED || specStatus === IncrementStatus.ACTIVE)) {
|
|
43
|
+
return {
|
|
44
|
+
severity: DesyncSeverity.MEDIUM,
|
|
45
|
+
impact: 'Workflow state confusion. Increment may appear in wrong status.',
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
// LOW: Other combinations (rare, minimal impact)
|
|
49
|
+
return {
|
|
50
|
+
severity: DesyncSeverity.LOW,
|
|
51
|
+
impact: 'Minor status inconsistency. Limited user impact.',
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Validate status sync across all increments
|
|
56
|
+
*/
|
|
57
|
+
export async function validateStatusSync() {
|
|
58
|
+
const allIncrements = MetadataManager.getAll();
|
|
59
|
+
const desyncs = [];
|
|
60
|
+
let syncedCount = 0;
|
|
61
|
+
for (const metadata of allIncrements) {
|
|
62
|
+
try {
|
|
63
|
+
const specStatus = await SpecFrontmatterUpdater.readStatus(metadata.id);
|
|
64
|
+
// Skip if spec.md missing or status field missing (graceful degradation)
|
|
65
|
+
if (!specStatus) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
// Check for desync
|
|
69
|
+
if (specStatus !== metadata.status) {
|
|
70
|
+
const { severity, impact } = calculateSeverity(metadata.status, specStatus);
|
|
71
|
+
desyncs.push({
|
|
72
|
+
incrementId: metadata.id,
|
|
73
|
+
metadataStatus: metadata.status,
|
|
74
|
+
specStatus: specStatus,
|
|
75
|
+
severity,
|
|
76
|
+
impact,
|
|
77
|
+
fix: `Run: npx specweave repair-status-desync ${metadata.id}`,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
syncedCount++; // Only count as synced if we validated AND they match
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
// Skip increments with read errors (e.g., corrupted spec.md)
|
|
86
|
+
console.warn(`Warning: Could not read spec.md for ${metadata.id}: ${error instanceof Error ? error.message : String(error)}`);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
total: allIncrements.length, // All increments scanned
|
|
92
|
+
synced: syncedCount, // Only increments where spec.md exists AND matches
|
|
93
|
+
desynced: desyncs.length,
|
|
94
|
+
desyncs: desyncs.sort((a, b) => {
|
|
95
|
+
// Sort by severity: CRITICAL > HIGH > MEDIUM > LOW
|
|
96
|
+
const severityOrder = {
|
|
97
|
+
[DesyncSeverity.CRITICAL]: 0,
|
|
98
|
+
[DesyncSeverity.HIGH]: 1,
|
|
99
|
+
[DesyncSeverity.MEDIUM]: 2,
|
|
100
|
+
[DesyncSeverity.LOW]: 3,
|
|
101
|
+
};
|
|
102
|
+
return severityOrder[a.severity] - severityOrder[b.severity];
|
|
103
|
+
}),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Format and print validation report
|
|
108
|
+
*/
|
|
109
|
+
export function formatReport(result) {
|
|
110
|
+
const lines = [];
|
|
111
|
+
lines.push('');
|
|
112
|
+
lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
113
|
+
lines.push('Status Sync Validation Report');
|
|
114
|
+
lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
115
|
+
lines.push('');
|
|
116
|
+
lines.push(`Total increments scanned: ${result.total}`);
|
|
117
|
+
lines.push(`Synced (✅): ${result.synced}`);
|
|
118
|
+
lines.push(`Desynced (❌): ${result.desynced}`);
|
|
119
|
+
lines.push('');
|
|
120
|
+
if (result.desynced === 0) {
|
|
121
|
+
lines.push(chalk.green('✅ All increments in sync! No desyncs detected.'));
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
lines.push(chalk.red(`❌ ${result.desynced} desync(s) detected:`));
|
|
125
|
+
lines.push('');
|
|
126
|
+
for (const desync of result.desyncs) {
|
|
127
|
+
const severityColor = desync.severity === DesyncSeverity.CRITICAL
|
|
128
|
+
? chalk.red
|
|
129
|
+
: desync.severity === DesyncSeverity.HIGH
|
|
130
|
+
? chalk.yellow
|
|
131
|
+
: desync.severity === DesyncSeverity.MEDIUM
|
|
132
|
+
? chalk.blue
|
|
133
|
+
: chalk.gray;
|
|
134
|
+
lines.push(`Increment: ${chalk.bold(desync.incrementId)}`);
|
|
135
|
+
lines.push(` Severity: ${severityColor(desync.severity)}`);
|
|
136
|
+
lines.push(` metadata.json: "${desync.metadataStatus}"`);
|
|
137
|
+
lines.push(` spec.md: "${desync.specStatus}"`);
|
|
138
|
+
lines.push(` Impact: ${desync.impact}`);
|
|
139
|
+
lines.push(` Fix: ${chalk.cyan(desync.fix)}`);
|
|
140
|
+
lines.push('');
|
|
141
|
+
}
|
|
142
|
+
lines.push('To repair all desyncs:');
|
|
143
|
+
lines.push(chalk.cyan(' npx specweave repair-status-desync --all'));
|
|
144
|
+
lines.push('');
|
|
145
|
+
lines.push('To preview changes without modifying files:');
|
|
146
|
+
lines.push(chalk.cyan(' npx specweave repair-status-desync --all --dry-run'));
|
|
147
|
+
}
|
|
148
|
+
lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
149
|
+
lines.push('');
|
|
150
|
+
return lines.join('\n');
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Main CLI entry point
|
|
154
|
+
*/
|
|
155
|
+
export async function main() {
|
|
156
|
+
try {
|
|
157
|
+
console.log('🔍 Validating status sync across all increments...\n');
|
|
158
|
+
const result = await validateStatusSync();
|
|
159
|
+
const report = formatReport(result);
|
|
160
|
+
console.log(report);
|
|
161
|
+
// Exit with error code if desyncs found
|
|
162
|
+
if (result.desynced > 0) {
|
|
163
|
+
process.exit(1);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
console.error(chalk.red('Error during validation:'));
|
|
168
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// Run if called directly
|
|
173
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
174
|
+
main();
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=validate-status-sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-status-sync.js","sourceRoot":"","sources":["../../../../src/cli/commands/validate-status-sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Count Tasks CLI
|
|
4
|
+
*
|
|
5
|
+
* CLI utility for counting tasks in tasks.md files.
|
|
6
|
+
* Used by status line hook to get accurate task counts.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* count-tasks <path-to-tasks.md>
|
|
10
|
+
*
|
|
11
|
+
* Output (JSON):
|
|
12
|
+
* {"total": 23, "completed": 15, "percentage": 65}
|
|
13
|
+
*
|
|
14
|
+
* Exit codes:
|
|
15
|
+
* 0 - Success
|
|
16
|
+
* 1 - File not found or read error
|
|
17
|
+
* 2 - Invalid arguments
|
|
18
|
+
*/
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=count-tasks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"count-tasks.d.ts","sourceRoot":"","sources":["../../../src/cli/count-tasks.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;GAgBG"}
|