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
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: specweave:sync-specs
|
|
3
|
-
description: Sync
|
|
3
|
+
description: Sync increment specifications to living docs structure. Auto-generates feature IDs for greenfield increments (FS-XXX). Use after completing an increment to make it visible in living docs.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Sync
|
|
6
|
+
# Sync Increment Specifications to Living Docs
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Syncs increment specs to living docs structure for stakeholder visibility. Auto-generates feature IDs for greenfield increments.
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
@@ -85,58 +85,30 @@ fi
|
|
|
85
85
|
|
|
86
86
|
---
|
|
87
87
|
|
|
88
|
-
## STEP 3: Execute Spec
|
|
88
|
+
## STEP 3: Execute Spec Sync
|
|
89
89
|
|
|
90
|
-
### 3.1 Run
|
|
90
|
+
### 3.1 Run Sync Command
|
|
91
91
|
|
|
92
|
-
**Execute the
|
|
92
|
+
**Execute the sync using the CLI command**:
|
|
93
93
|
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
node -e "
|
|
97
|
-
import('./dist/src/core/living-docs/spec-distributor.js').then(async ({ SpecDistributor }) => {
|
|
98
|
-
const distributor = new SpecDistributor(process.cwd());
|
|
94
|
+
```typescript
|
|
95
|
+
import { syncSpecs } from './dist/src/cli/commands/sync-specs.js';
|
|
99
96
|
|
|
100
|
-
|
|
101
|
-
|
|
97
|
+
// Parse arguments
|
|
98
|
+
const args = process.argv.slice(2); // e.g., ['0040', '--dry-run']
|
|
102
99
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
console.log('');
|
|
107
|
-
console.log('✅ Distribution successful!');
|
|
108
|
-
console.log(' 📊 Total stories: ' + result.totalStories);
|
|
109
|
-
console.log(' 📁 Total files created: ' + result.totalFiles);
|
|
110
|
-
console.log(' 🎯 Feature ID: ' + result.specId);
|
|
111
|
-
|
|
112
|
-
if (result.epicPath) {
|
|
113
|
-
console.log(' 📂 Feature path: ' + result.epicPath);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
if (result.userStoryPaths && result.userStoryPaths.length > 0) {
|
|
117
|
-
console.log(' 📝 User stories created:');
|
|
118
|
-
result.userStoryPaths.forEach(p => console.log(' • ' + p));
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (result.warnings && result.warnings.length > 0) {
|
|
122
|
-
console.log('');
|
|
123
|
-
console.log('⚠️ Warnings:');
|
|
124
|
-
result.warnings.forEach(w => console.log(' • ' + w));
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Update acceptance criteria status based on completed tasks
|
|
128
|
-
console.log('');
|
|
129
|
-
console.log('📊 Updating acceptance criteria status...');
|
|
130
|
-
await distributor.updateAcceptanceCriteriaStatus('${INCREMENT_ID}');
|
|
131
|
-
|
|
132
|
-
} catch (error) {
|
|
133
|
-
console.error('❌ Distribution failed:', error.message);
|
|
134
|
-
process.exit(1);
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
"
|
|
100
|
+
// Execute sync
|
|
101
|
+
await syncSpecs(args);
|
|
138
102
|
```
|
|
139
103
|
|
|
104
|
+
**This will**:
|
|
105
|
+
1. Auto-generate feature ID for greenfield increments (FS-040, FS-041, etc.)
|
|
106
|
+
2. Parse spec.md for user stories and acceptance criteria
|
|
107
|
+
3. Create living docs structure:
|
|
108
|
+
- `.specweave/docs/internal/specs/_features/FS-XXX/FEATURE.md`
|
|
109
|
+
- `.specweave/docs/internal/specs/specweave/FS-XXX/README.md`
|
|
110
|
+
- `.specweave/docs/internal/specs/specweave/FS-XXX/us-*.md`
|
|
111
|
+
|
|
140
112
|
---
|
|
141
113
|
|
|
142
114
|
## STEP 4: Report Distribution Results
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: specweave:update-status
|
|
3
|
+
description: Force-update status line cache with latest increment status
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Update Status Line
|
|
7
|
+
|
|
8
|
+
**Purpose**: Force-refresh status line cache when it appears stale or after making changes.
|
|
9
|
+
|
|
10
|
+
**Use When**:
|
|
11
|
+
- Status line doesn't reflect recent changes
|
|
12
|
+
- After completing tasks (want to see updated progress immediately)
|
|
13
|
+
- After status transitions (active → completed)
|
|
14
|
+
- Before checking progress with `/specweave:progress`
|
|
15
|
+
- When status line shows outdated information
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## How It Works
|
|
20
|
+
|
|
21
|
+
1. **Scan All Increments**
|
|
22
|
+
- Reads all spec.md files in `.specweave/increments/`
|
|
23
|
+
- Identifies open increments (status = active/planning/in-progress)
|
|
24
|
+
- Extracts creation dates from YAML frontmatter
|
|
25
|
+
|
|
26
|
+
2. **Select Current Increment**
|
|
27
|
+
- Sorts by creation date (oldest first)
|
|
28
|
+
- Takes first as current active increment
|
|
29
|
+
- Counts total open increments
|
|
30
|
+
|
|
31
|
+
3. **Parse Task Progress**
|
|
32
|
+
- Reads tasks.md from current increment
|
|
33
|
+
- Uses TaskCounter for accurate counting (no overcounting)
|
|
34
|
+
- Calculates: completed, total, percentage
|
|
35
|
+
|
|
36
|
+
4. **Update Cache**
|
|
37
|
+
- Writes `.specweave/state/status-line.json`
|
|
38
|
+
- Atomic write (temp file → rename)
|
|
39
|
+
- Runs SYNCHRONOUSLY (user waits ~50-100ms)
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Usage
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Force-update status line (no arguments)
|
|
47
|
+
/specweave:update-status
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Output**:
|
|
51
|
+
```
|
|
52
|
+
✓ Status line cache updated
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Example
|
|
58
|
+
|
|
59
|
+
**Before Update** (stale cache):
|
|
60
|
+
```
|
|
61
|
+
Status Line: [0043] ████░░░░ 5/8 tasks (2 open)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**After Update** (fresh cache):
|
|
65
|
+
```
|
|
66
|
+
Status Line: [0043] ████████ 8/8 tasks (1 open) ✓
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Integration with Other Commands
|
|
72
|
+
|
|
73
|
+
This command is automatically called by:
|
|
74
|
+
|
|
75
|
+
1. **`/specweave:progress`**
|
|
76
|
+
- Ensures status line is fresh before showing progress
|
|
77
|
+
- User always sees accurate completion percentages
|
|
78
|
+
|
|
79
|
+
2. **`/specweave:done`**
|
|
80
|
+
- Refreshes status line before PM validation
|
|
81
|
+
- Ensures final progress is accurate
|
|
82
|
+
|
|
83
|
+
3. **`/specweave:status`**
|
|
84
|
+
- Updates cache before showing increment list
|
|
85
|
+
- Shows current increment status
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Technical Details
|
|
90
|
+
|
|
91
|
+
**Performance**: ~50-100ms (synchronous execution)
|
|
92
|
+
|
|
93
|
+
**Cache Location**: `.specweave/state/status-line.json`
|
|
94
|
+
|
|
95
|
+
**Cache Format**:
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"current": {
|
|
99
|
+
"id": "0043-spec-md-desync-fix",
|
|
100
|
+
"name": "0043-spec-md-desync-fix",
|
|
101
|
+
"completed": 8,
|
|
102
|
+
"total": 8,
|
|
103
|
+
"percentage": 100
|
|
104
|
+
},
|
|
105
|
+
"openCount": 1,
|
|
106
|
+
"lastUpdate": "2025-11-18T15:30:00Z"
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Source of Truth**:
|
|
111
|
+
- Increment status: `spec.md` YAML frontmatter (NOT metadata.json)
|
|
112
|
+
- Task progress: `tasks.md` (TaskCounter for accuracy)
|
|
113
|
+
|
|
114
|
+
**Atomicity**: Uses temp file → rename pattern to prevent cache corruption
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Troubleshooting
|
|
119
|
+
|
|
120
|
+
**Status line still stale after update?**
|
|
121
|
+
1. Check if `.specweave/state/status-line.json` was modified
|
|
122
|
+
2. Verify spec.md has correct status in YAML frontmatter
|
|
123
|
+
3. Check tasks.md has proper task format (## T-001, etc.)
|
|
124
|
+
|
|
125
|
+
**Error: "Failed to update status line"**
|
|
126
|
+
- Ensure `.specweave/increments/` exists
|
|
127
|
+
- Check file permissions on `.specweave/state/`
|
|
128
|
+
- Verify spec.md has valid YAML frontmatter
|
|
129
|
+
|
|
130
|
+
**Cache shows wrong increment?**
|
|
131
|
+
- Status line shows oldest active increment by default
|
|
132
|
+
- Complete older increments first
|
|
133
|
+
- Or check `created` date in spec.md frontmatter
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Implementation
|
|
138
|
+
|
|
139
|
+
**CLI**: `src/cli/update-status-line.ts`
|
|
140
|
+
**Core Logic**: `src/core/status-line/status-line-updater.ts`
|
|
141
|
+
**Hook (async)**: `plugins/specweave/hooks/lib/update-status-line.sh`
|
|
142
|
+
|
|
143
|
+
**Difference from Hook**:
|
|
144
|
+
- **Command**: SYNCHRONOUS (user waits, sees immediate result)
|
|
145
|
+
- **Hook**: ASYNCHRONOUS (background refresh, no blocking)
|
|
146
|
+
|
|
147
|
+
Both use same logic, different execution model.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
**This command ensures status line is ALWAYS fresh when you need it!** ✓
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
#
|
|
3
|
-
# update-status-line.sh (
|
|
3
|
+
# update-status-line.sh (Enhanced with AC Metrics)
|
|
4
4
|
#
|
|
5
5
|
# Updates status line cache with current increment progress.
|
|
6
|
-
# Shows: [increment-name] ████░░░░ X/Y tasks (Z open)
|
|
6
|
+
# Shows: [increment-name] ████░░░░ X/Y tasks | A/B ACs (Z open)
|
|
7
7
|
#
|
|
8
8
|
# Logic:
|
|
9
|
-
# 1. Scan all
|
|
9
|
+
# 1. Scan all spec.md for status=active/planning (SOURCE OF TRUTH!)
|
|
10
10
|
# 2. Take first (oldest) as current increment
|
|
11
|
-
# 3. Count all active/
|
|
12
|
-
# 4. Parse current increment's tasks.md for progress
|
|
13
|
-
# 5.
|
|
11
|
+
# 3. Count all active/planning as openCount
|
|
12
|
+
# 4. Parse current increment's tasks.md for task progress
|
|
13
|
+
# 5. Parse current increment's spec.md for AC progress
|
|
14
|
+
# 6. Write to cache
|
|
14
15
|
#
|
|
15
16
|
# Performance: 50-100ms (runs async, user doesn't wait)
|
|
16
17
|
|
|
@@ -37,19 +38,24 @@ TMP_FILE="$PROJECT_ROOT/.specweave/state/.status-line-tmp.txt"
|
|
|
37
38
|
# Ensure state directory exists
|
|
38
39
|
mkdir -p "$PROJECT_ROOT/.specweave/state"
|
|
39
40
|
|
|
40
|
-
# Step 1: Find all open increments (active/
|
|
41
|
+
# Step 1: Find all open increments (active/planning)
|
|
42
|
+
# Read from spec.md (source of truth), not metadata.json
|
|
43
|
+
# ONLY accepts official IncrementStatus enum values
|
|
41
44
|
# Write to temp file: "timestamp increment_id"
|
|
42
45
|
> "$TMP_FILE"
|
|
43
46
|
|
|
44
47
|
if [[ -d "$INCREMENTS_DIR" ]]; then
|
|
45
|
-
for
|
|
46
|
-
if [[ -f "$
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
for spec_file in "$INCREMENTS_DIR"/*/spec.md; do
|
|
49
|
+
if [[ -f "$spec_file" ]]; then
|
|
50
|
+
# Parse YAML frontmatter for status (source of truth)
|
|
51
|
+
status=$(grep -m1 "^status:" "$spec_file" 2>/dev/null | cut -d: -f2 | tr -d ' ' || echo "")
|
|
52
|
+
|
|
53
|
+
# Check if increment is open (active, planning, or in-progress)
|
|
54
|
+
# ONLY accepts official IncrementStatus enum values
|
|
55
|
+
if [[ "$status" == "active" ]] || [[ "$status" == "planning" ]] || [[ "$status" == "in-progress" ]]; then
|
|
56
|
+
increment_id=$(basename "$(dirname "$spec_file")")
|
|
57
|
+
# Parse created date from spec.md YAML frontmatter
|
|
58
|
+
created=$(grep -m1 "^created:" "$spec_file" 2>/dev/null | cut -d: -f2- | tr -d ' ' || echo "1970-01-01")
|
|
53
59
|
|
|
54
60
|
# Write to temp file
|
|
55
61
|
echo "$created $increment_id" >> "$TMP_FILE"
|
|
@@ -85,41 +91,70 @@ COMPLETED_TASKS=0
|
|
|
85
91
|
PERCENTAGE=0
|
|
86
92
|
|
|
87
93
|
if [[ -f "$TASKS_FILE" ]]; then
|
|
88
|
-
#
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
94
|
+
# Use TaskCounter CLI for accurate counting (fixes overcounting bug)
|
|
95
|
+
COUNT_TASKS_CLI="$PROJECT_ROOT/dist/src/cli/count-tasks.js"
|
|
96
|
+
|
|
97
|
+
if [[ -f "$COUNT_TASKS_CLI" ]]; then
|
|
98
|
+
# Call CLI and parse JSON output
|
|
99
|
+
TASK_COUNTS=$(node "$COUNT_TASKS_CLI" "$TASKS_FILE" 2>/dev/null || echo '{"total":0,"completed":0,"percentage":0}')
|
|
100
|
+
TOTAL_TASKS=$(echo "$TASK_COUNTS" | jq -r '.total' 2>/dev/null || echo 0)
|
|
101
|
+
COMPLETED_TASKS=$(echo "$TASK_COUNTS" | jq -r '.completed' 2>/dev/null || echo 0)
|
|
102
|
+
PERCENTAGE=$(echo "$TASK_COUNTS" | jq -r '.percentage' 2>/dev/null || echo 0)
|
|
103
|
+
else
|
|
104
|
+
# Fallback to legacy counting if CLI not available (graceful degradation)
|
|
105
|
+
# Count total tasks (## T- or ### T- headings)
|
|
106
|
+
TOTAL_TASKS=$(grep -cE '^##+ T-' "$TASKS_FILE" 2>/dev/null || echo 0)
|
|
107
|
+
TOTAL_TASKS=$(echo "$TOTAL_TASKS" | tr -d '\n\r ' || echo 0)
|
|
108
|
+
|
|
109
|
+
# Count completed tasks - use most reliable single marker (**Completed**: format)
|
|
110
|
+
COMPLETED_TASKS=$(grep -c '\*\*Completed\*\*:' "$TASKS_FILE" 2>/dev/null || echo 0)
|
|
111
|
+
COMPLETED_TASKS=$(echo "$COMPLETED_TASKS" | tr -d '\n\r ' || echo 0)
|
|
112
|
+
|
|
113
|
+
# Calculate percentage
|
|
114
|
+
if [[ $TOTAL_TASKS -gt 0 ]]; then
|
|
115
|
+
PERCENTAGE=$((COMPLETED_TASKS * 100 / TOTAL_TASKS))
|
|
116
|
+
fi
|
|
110
117
|
fi
|
|
111
118
|
fi
|
|
112
119
|
|
|
113
|
-
# Step
|
|
114
|
-
|
|
120
|
+
# Step 4b: Parse spec.md for AC (Acceptance Criteria) progress
|
|
121
|
+
SPEC_FILE="$INCREMENTS_DIR/$CURRENT_INCREMENT/spec.md"
|
|
122
|
+
TOTAL_ACS=0
|
|
123
|
+
COMPLETED_ACS=0
|
|
124
|
+
OPEN_ACS=0
|
|
125
|
+
|
|
126
|
+
if [[ -f "$SPEC_FILE" ]]; then
|
|
127
|
+
# Count total ACs: both checked and unchecked
|
|
128
|
+
# Pattern: - [ ] **AC- OR - [x] **AC-
|
|
129
|
+
TOTAL_ACS=$(grep -cE '^- \[(x| )\] \*\*AC-' "$SPEC_FILE" 2>/dev/null || echo 0)
|
|
130
|
+
TOTAL_ACS=$(echo "$TOTAL_ACS" | tr -d '\n\r ' || echo 0)
|
|
131
|
+
|
|
132
|
+
# Count completed ACs (checked)
|
|
133
|
+
# Pattern: - [x] **AC-
|
|
134
|
+
COMPLETED_ACS=$(grep -cE '^- \[x\] \*\*AC-' "$SPEC_FILE" 2>/dev/null || echo 0)
|
|
135
|
+
COMPLETED_ACS=$(echo "$COMPLETED_ACS" | tr -d '\n\r ' || echo 0)
|
|
136
|
+
|
|
137
|
+
# Count open ACs (unchecked)
|
|
138
|
+
# Pattern: - [ ] **AC-
|
|
139
|
+
OPEN_ACS=$(grep -cE '^- \[ \] \*\*AC-' "$SPEC_FILE" 2>/dev/null || echo 0)
|
|
140
|
+
OPEN_ACS=$(echo "$OPEN_ACS" | tr -d '\n\r ' || echo 0)
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
# Step 5: Extract increment ID and name
|
|
144
|
+
# Format: XXXX-name where XXXX is 4-digit prefix (brackets added by manager)
|
|
145
|
+
INCREMENT_ID=$(echo "$CURRENT_INCREMENT" | grep -oE '^[0-9]{4}')
|
|
146
|
+
INCREMENT_NAME_ONLY=$(echo "$CURRENT_INCREMENT" | sed 's/^[0-9]\{4\}-//')
|
|
147
|
+
INCREMENT_NAME="$INCREMENT_ID-$INCREMENT_NAME_ONLY"
|
|
115
148
|
|
|
116
|
-
# Step 6: Write cache
|
|
149
|
+
# Step 6: Write cache (now includes AC metrics)
|
|
117
150
|
jq -n \
|
|
118
151
|
--arg id "$CURRENT_INCREMENT" \
|
|
119
152
|
--arg name "$INCREMENT_NAME" \
|
|
120
153
|
--argjson completed "$COMPLETED_TASKS" \
|
|
121
154
|
--argjson total "$TOTAL_TASKS" \
|
|
122
155
|
--argjson percentage "$PERCENTAGE" \
|
|
156
|
+
--argjson acsCompleted "$COMPLETED_ACS" \
|
|
157
|
+
--argjson acsTotal "$TOTAL_ACS" \
|
|
123
158
|
--argjson openCount "$OPEN_COUNT" \
|
|
124
159
|
'{
|
|
125
160
|
current: {
|
|
@@ -127,7 +162,9 @@ jq -n \
|
|
|
127
162
|
name: $name,
|
|
128
163
|
completed: $completed,
|
|
129
164
|
total: $total,
|
|
130
|
-
percentage: $percentage
|
|
165
|
+
percentage: $percentage,
|
|
166
|
+
acsCompleted: $acsCompleted,
|
|
167
|
+
acsTotal: $acsTotal
|
|
131
168
|
},
|
|
132
169
|
openCount: $openCount,
|
|
133
170
|
lastUpdate: (now | strftime("%Y-%m-%dT%H:%M:%SZ"))
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# validate-spec-status.sh
|
|
4
|
+
#
|
|
5
|
+
# Validates that spec.md status values match IncrementStatus enum.
|
|
6
|
+
# Prevents vocabulary drift and ensures status line hook compatibility.
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# bash validate-spec-status.sh <increment-id>
|
|
10
|
+
# bash validate-spec-status.sh --all # Validate all increments
|
|
11
|
+
#
|
|
12
|
+
# Exit codes:
|
|
13
|
+
# 0 = Valid
|
|
14
|
+
# 1 = Invalid status found
|
|
15
|
+
# 2 = Error (file not found, etc.)
|
|
16
|
+
#
|
|
17
|
+
# Requires: bash 4.0+ (for associative arrays)
|
|
18
|
+
|
|
19
|
+
set -euo pipefail
|
|
20
|
+
|
|
21
|
+
# Find project root
|
|
22
|
+
find_project_root() {
|
|
23
|
+
local dir="$PWD"
|
|
24
|
+
while [[ "$dir" != "/" ]]; do
|
|
25
|
+
if [[ -d "$dir/.specweave" ]]; then
|
|
26
|
+
echo "$dir"
|
|
27
|
+
return 0
|
|
28
|
+
fi
|
|
29
|
+
dir=$(dirname "$dir")
|
|
30
|
+
done
|
|
31
|
+
echo "$PWD"
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
PROJECT_ROOT=$(find_project_root)
|
|
35
|
+
INCREMENTS_DIR="$PROJECT_ROOT/.specweave/increments"
|
|
36
|
+
|
|
37
|
+
# Valid IncrementStatus enum values (from src/core/types/increment-metadata.ts)
|
|
38
|
+
VALID_STATUSES=("planning" "active" "backlog" "paused" "completed" "abandoned")
|
|
39
|
+
|
|
40
|
+
# Get suggested correction for invalid status
|
|
41
|
+
get_correction() {
|
|
42
|
+
local status="$1"
|
|
43
|
+
case "$status" in
|
|
44
|
+
"planned") echo "planning" ;;
|
|
45
|
+
"in-progress"|"in_progress") echo "active" ;;
|
|
46
|
+
"done") echo "completed" ;;
|
|
47
|
+
"cancelled"|"canceled") echo "abandoned" ;;
|
|
48
|
+
*) echo "" ;;
|
|
49
|
+
esac
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
# Validate a single spec file
|
|
53
|
+
validate_spec() {
|
|
54
|
+
local spec_file="$1"
|
|
55
|
+
local increment_id=$(basename "$(dirname "$spec_file")")
|
|
56
|
+
|
|
57
|
+
if [[ ! -f "$spec_file" ]]; then
|
|
58
|
+
echo "❌ Error: spec.md not found for increment $increment_id"
|
|
59
|
+
return 2
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# Extract status from YAML frontmatter
|
|
63
|
+
local status=$(grep -m1 "^status:" "$spec_file" 2>/dev/null | cut -d: -f2 | tr -d ' "' || echo "")
|
|
64
|
+
|
|
65
|
+
if [[ -z "$status" ]]; then
|
|
66
|
+
echo "⚠️ Warning: No status field in $increment_id/spec.md"
|
|
67
|
+
return 0 # Not an error, just a warning
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# Check if status is valid
|
|
71
|
+
local is_valid=0
|
|
72
|
+
for valid_status in "${VALID_STATUSES[@]}"; do
|
|
73
|
+
if [[ "$status" == "$valid_status" ]]; then
|
|
74
|
+
is_valid=1
|
|
75
|
+
break
|
|
76
|
+
fi
|
|
77
|
+
done
|
|
78
|
+
|
|
79
|
+
if [[ $is_valid -eq 1 ]]; then
|
|
80
|
+
echo "✅ $increment_id: status '$status' is valid"
|
|
81
|
+
return 0
|
|
82
|
+
else
|
|
83
|
+
# Invalid status found - suggest correction
|
|
84
|
+
echo ""
|
|
85
|
+
echo "❌ Invalid status in $increment_id/spec.md"
|
|
86
|
+
echo " Found: '$status'"
|
|
87
|
+
echo ""
|
|
88
|
+
|
|
89
|
+
# Check if we have a suggested correction
|
|
90
|
+
local correction=$(get_correction "$status")
|
|
91
|
+
if [[ -n "$correction" ]]; then
|
|
92
|
+
echo " 💡 Did you mean: '$correction'?"
|
|
93
|
+
echo ""
|
|
94
|
+
echo " Fix:"
|
|
95
|
+
echo " sed -i '' 's/^status: $status/status: $correction/' $spec_file"
|
|
96
|
+
else
|
|
97
|
+
echo " Valid statuses: ${VALID_STATUSES[*]}"
|
|
98
|
+
fi
|
|
99
|
+
echo ""
|
|
100
|
+
|
|
101
|
+
return 1
|
|
102
|
+
fi
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
# Validate all increments
|
|
106
|
+
validate_all() {
|
|
107
|
+
local exit_code=0
|
|
108
|
+
local total=0
|
|
109
|
+
local valid=0
|
|
110
|
+
local invalid=0
|
|
111
|
+
|
|
112
|
+
echo "Validating all increments in $INCREMENTS_DIR"
|
|
113
|
+
echo ""
|
|
114
|
+
|
|
115
|
+
for spec_file in "$INCREMENTS_DIR"/*/spec.md; do
|
|
116
|
+
if [[ -f "$spec_file" ]]; then
|
|
117
|
+
total=$((total + 1))
|
|
118
|
+
if validate_spec "$spec_file"; then
|
|
119
|
+
valid=$((valid + 1))
|
|
120
|
+
else
|
|
121
|
+
invalid=$((invalid + 1))
|
|
122
|
+
exit_code=1
|
|
123
|
+
fi
|
|
124
|
+
fi
|
|
125
|
+
done
|
|
126
|
+
|
|
127
|
+
echo ""
|
|
128
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
129
|
+
echo "Summary: $total increments checked"
|
|
130
|
+
echo " ✅ Valid: $valid"
|
|
131
|
+
echo " ❌ Invalid: $invalid"
|
|
132
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
133
|
+
|
|
134
|
+
if [[ $invalid -gt 0 ]]; then
|
|
135
|
+
echo ""
|
|
136
|
+
echo "⚠️ Please fix invalid status values to use official IncrementStatus enum."
|
|
137
|
+
echo ""
|
|
138
|
+
echo "Valid statuses:"
|
|
139
|
+
for status in "${VALID_STATUSES[@]}"; do
|
|
140
|
+
echo " - $status"
|
|
141
|
+
done
|
|
142
|
+
fi
|
|
143
|
+
|
|
144
|
+
return $exit_code
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
# Main logic
|
|
148
|
+
if [[ $# -eq 0 ]]; then
|
|
149
|
+
echo "Usage: $0 <increment-id> | --all"
|
|
150
|
+
echo ""
|
|
151
|
+
echo "Examples:"
|
|
152
|
+
echo " $0 0042-test-infrastructure-cleanup"
|
|
153
|
+
echo " $0 --all"
|
|
154
|
+
exit 2
|
|
155
|
+
fi
|
|
156
|
+
|
|
157
|
+
if [[ "$1" == "--all" ]]; then
|
|
158
|
+
validate_all
|
|
159
|
+
else
|
|
160
|
+
INCREMENT_ID="$1"
|
|
161
|
+
SPEC_FILE="$INCREMENTS_DIR/$INCREMENT_ID/spec.md"
|
|
162
|
+
validate_spec "$SPEC_FILE"
|
|
163
|
+
fi
|
|
@@ -303,44 +303,26 @@ if [[ -d ".specweave/increments" ]]; then
|
|
|
303
303
|
done)
|
|
304
304
|
|
|
305
305
|
if [[ -n "$ACTIVE_INCREMENT" ]]; then
|
|
306
|
-
#
|
|
307
|
-
|
|
308
|
-
if [[ -f "$
|
|
309
|
-
#
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
if [[ -n "$STATUS_LINE" ]]; then
|
|
323
|
-
CONTEXT="✓ $STATUS_LINE"
|
|
306
|
+
# Simple status: parse tasks.md for completion
|
|
307
|
+
TASKS_FILE=".specweave/increments/$ACTIVE_INCREMENT/tasks.md"
|
|
308
|
+
if [[ -f "$TASKS_FILE" ]]; then
|
|
309
|
+
# Count tasks (headers with T-NNN format - both ### and ####)
|
|
310
|
+
TOTAL_TASKS=$(grep -cE '^#{3,4}\s*T-[0-9]' "$TASKS_FILE" 2>/dev/null | tr -d '\n' || echo "0")
|
|
311
|
+
# Count completed (various formats)
|
|
312
|
+
COMPLETED_TASKS=$(grep -cE '(✅ COMPLETE|\[COMPLETED\]|\[x\] Completed)' "$TASKS_FILE" 2>/dev/null | tr -d '\n' || echo "0")
|
|
313
|
+
|
|
314
|
+
# Ensure valid numbers
|
|
315
|
+
TOTAL_TASKS=${TOTAL_TASKS:-0}
|
|
316
|
+
COMPLETED_TASKS=${COMPLETED_TASKS:-0}
|
|
317
|
+
|
|
318
|
+
if [[ "$TOTAL_TASKS" -gt 0 ]] 2>/dev/null; then
|
|
319
|
+
PERCENTAGE=$(( COMPLETED_TASKS * 100 / TOTAL_TASKS ))
|
|
320
|
+
CONTEXT="✓ Active: $ACTIVE_INCREMENT ($COMPLETED_TASKS/$TOTAL_TASKS tasks, $PERCENTAGE%)"
|
|
324
321
|
else
|
|
325
|
-
|
|
326
|
-
TASKS_FILE=".specweave/increments/$ACTIVE_INCREMENT/tasks.md"
|
|
327
|
-
if [[ -f "$TASKS_FILE" ]]; then
|
|
328
|
-
TASK_STATS=$(grep -E "^\s*-\s*\[[ x]\]" "$TASKS_FILE" 2>/dev/null | wc -l | xargs || echo "0")
|
|
329
|
-
COMPLETED_TASKS=$(grep -E "^\s*-\s*\[x\]" "$TASKS_FILE" 2>/dev/null | wc -l | xargs || echo "0")
|
|
330
|
-
|
|
331
|
-
if [[ "$TASK_STATS" -gt 0 ]]; then
|
|
332
|
-
PERCENTAGE=$(( COMPLETED_TASKS * 100 / TASK_STATS ))
|
|
333
|
-
CONTEXT="✓ Active Increment: $ACTIVE_INCREMENT ($PERCENTAGE% complete, $COMPLETED_TASKS/$TASK_STATS tasks)"
|
|
334
|
-
else
|
|
335
|
-
CONTEXT="✓ Active Increment: $ACTIVE_INCREMENT"
|
|
336
|
-
fi
|
|
337
|
-
else
|
|
338
|
-
CONTEXT="✓ Active Increment: $ACTIVE_INCREMENT"
|
|
339
|
-
fi
|
|
322
|
+
CONTEXT="✓ Active: $ACTIVE_INCREMENT"
|
|
340
323
|
fi
|
|
341
324
|
else
|
|
342
|
-
|
|
343
|
-
CONTEXT="✓ Active Increment: $ACTIVE_INCREMENT"
|
|
325
|
+
CONTEXT="✓ Active: $ACTIVE_INCREMENT"
|
|
344
326
|
fi
|
|
345
327
|
fi
|
|
346
328
|
fi
|
|
@@ -360,6 +342,27 @@ if echo "$PROMPT" | grep -qiE "(add|create|implement|build|develop)" && ! echo "
|
|
|
360
342
|
fi
|
|
361
343
|
fi
|
|
362
344
|
|
|
345
|
+
# ==============================================================================
|
|
346
|
+
# STATUS LINE REFRESH: Ensure cache is fresh before showing context
|
|
347
|
+
# ==============================================================================
|
|
348
|
+
# Performance: ~50-100ms (acceptable for UX)
|
|
349
|
+
# Frequency: Every user prompt (high coverage)
|
|
350
|
+
# Benefit: Catches ALL edge cases (manual edits, resume, direct changes)
|
|
351
|
+
#
|
|
352
|
+
# Why here? This hook runs on EVERY user prompt, ensuring status line
|
|
353
|
+
# is ALWAYS up-to-date before showing context to the user.
|
|
354
|
+
#
|
|
355
|
+
# Prevents desync scenarios:
|
|
356
|
+
# - Manual spec.md edits (status: planning → active)
|
|
357
|
+
# - /specweave:resume (status: paused → active)
|
|
358
|
+
# - Direct metadata changes (without hook triggers)
|
|
359
|
+
# - File system operations bypassing hooks
|
|
360
|
+
#
|
|
361
|
+
# Background execution: Runs async, doesn't block user prompt
|
|
362
|
+
|
|
363
|
+
HOOK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
364
|
+
bash "$HOOK_DIR/lib/update-status-line.sh" 2>/dev/null || true
|
|
365
|
+
|
|
363
366
|
# ==============================================================================
|
|
364
367
|
# OUTPUT: Approve with context or no context
|
|
365
368
|
# ==============================================================================
|