Agent skill
sync-status
Detect and fix status desyncs between metadata.json and spec.md
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/sync-status
SKILL.md
Sync Status - Desync Detection & Recovery
CRITICAL: Detects and fixes status desyncs between metadata.json and spec.md to maintain source-of-truth integrity.
Overview
This command scans increments for status desyncs where metadata.json and spec.md have different status values. This violates CLAUDE.md Rule #7 (source-of-truth discipline) and causes:
- Status line showing wrong increment
- Commands operating on wrong data
- User confusion and broken trust
Incident Reference: 2025-11-20 - Silent failure in /sw:done caused increment 0047 to have metadata.json="completed" while spec.md="active", breaking status line.
Usage
# Scan all increments for desyncs
/sw:sync-status
# Check specific increment
/sw:sync-status 0047
# Auto-fix all desyncs (non-interactive)
/sw:sync-status --fix
# Scan and show detailed report
/sw:sync-status --verbose
Arguments
<increment-id>- Optional. Specific increment to check (e.g., "0047", "0001-test")--fix- Auto-fix all desyncs without prompting--verbose- Show detailed report including healthy increments
Workflow
Mode 1: Scan All Increments (Default)
When to use: Regular maintenance, pre-commit checks, incident investigation
Steps:
-
Scan all increments:
typescriptimport { DesyncDetector } from '../../../src/core/increment/desync-detector.js'; const detector = new DesyncDetector(); const report = await detector.scanAll(); -
Display report:
typescriptconsole.log(detector.formatReport(report)); -
Example output (desyncs found):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ STATUS DESYNC DETECTION REPORT ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Total Scanned: 47 increments Healthy: 46 Desyncs Found: 1 ⚠️ Errors: 0 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ DESYNCS DETECTED (CRITICAL!) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ❌ 0047-us-task-linkage metadata.json: completed spec.md: active Fix command: /sw:sync-status --fix ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -
If desyncs found, prompt user:
typescriptif (report.totalDesyncs > 0) { const shouldFix = await promptUser( `Found ${report.totalDesyncs} desync(s). Fix them? (y/n): ` ); if (shouldFix) { // Fix all desyncs for (const desync of report.desyncs) { const fixed = await detector.fixDesync(desync.incrementId); if (fixed) { console.log(`✅ Fixed ${desync.incrementId}`); } else { console.error(`❌ Failed to fix ${desync.incrementId}`); } } console.log(''); console.log('All desyncs fixed! Run /sw:sync-status to verify.'); } } -
Example output (no desyncs):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ STATUS DESYNC DETECTION REPORT ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Total Scanned: 47 increments Healthy: 47 Desyncs Found: 0 ⚠️ Errors: 0 ✅ All increments healthy - no desyncs detected! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mode 2: Check Specific Increment
When to use: Investigating specific increment, post-fix verification
Steps:
-
Check increment:
typescriptconst detector = new DesyncDetector(); const result = await detector.checkIncrement(incrementId); -
Display result:
typescriptif (result.error) { console.error(`❌ Error checking ${incrementId}: ${result.error}`); process.exit(1); } if (result.hasDesync) { console.log('━'.repeat(80)); console.log(`❌ DESYNC DETECTED: ${incrementId}`); console.log('━'.repeat(80)); console.log(''); console.log(`metadata.json: ${result.metadataStatus}`); console.log(`spec.md: ${result.specStatus}`); console.log(''); console.log('This violates source-of-truth discipline (CLAUDE.md Rule #7)'); console.log(''); console.log(`Fix: /sw:sync-status ${incrementId} --fix`); console.log('━'.repeat(80)); } else { console.log(`✅ ${incrementId} - No desync detected`); console.log(` Status: ${result.metadataStatus}`); } -
Example output (desync found):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ❌ DESYNC DETECTED: 0047-us-task-linkage ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ metadata.json: completed spec.md: active This violates source-of-truth discipline (CLAUDE.md Rule #7) Fix: /sw:sync-status 0047 --fix ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mode 3: Auto-Fix (Non-Interactive)
When to use: CI/CD pipelines, automated recovery, pre-commit hooks
Steps:
-
Scan and fix:
typescriptconst detector = new DesyncDetector(); const report = await detector.scanAll(); if (report.totalDesyncs > 0) { console.log(`Found ${report.totalDesyncs} desync(s) - fixing...`); console.log(''); for (const desync of report.desyncs) { const fixed = await detector.fixDesync(desync.incrementId); if (fixed) { console.log(`✅ Fixed ${desync.incrementId}: ${desync.specStatus} → ${desync.metadataStatus}`); } else { console.error(`❌ Failed to fix ${desync.incrementId}`); } } console.log(''); console.log('✅ All desyncs fixed!'); } else { console.log('✅ No desyncs found - all healthy'); } -
Example output:
Found 1 desync(s) - fixing... ✅ Fixed 0047-us-task-linkage: active → completed ✅ All desyncs fixed!
How Desyncs Are Fixed
Fix Strategy: metadata.json is considered the source of truth for status updates.
Rationale:
- metadata.json is updated atomically by CLI commands
- metadata.json is used for increment state management
- spec.md should mirror metadata.json for consistency
Fix Process:
- Read current status from metadata.json
- Read current status from spec.md
- Update spec.md frontmatter to match metadata.json
- Write spec.md atomically (temp file → rename)
- Verify fix by re-checking
What gets updated:
- ✅ spec.md YAML frontmatter
statusfield - ❌ metadata.json (already correct)
Example fix:
# Before (spec.md)
---
status: active
---
# After (spec.md)
---
status: completed
---
Post-Fix Actions
After fixing desyncs, the following actions happen automatically:
-
Status Line Cache Update:
bash# Automatically triggered by spec.md change bash plugins/specweave/hooks/lib/update-status-line.sh -
Git Status:
bash# spec.md will be modified - commit the fix git status git add .specweave/increments/*/spec.md git commit -m "fix: sync spec.md status with metadata.json" -
Verification:
bash# Verify no desyncs remain /sw:sync-status
Error Handling
Increment Not Found
❌ Error: Increment 0047-us-task-linkage not found
Check increment ID and try again.
File Permission Error
❌ Failed to fix desync for 0047-us-task-linkage
Error: EACCES: permission denied, open '.specweave/increments/0047-us-task-linkage/spec.md'
Fix permissions:
chmod u+w .specweave/increments/0047-us-task-linkage/spec.md
YAML Parse Error
❌ Failed to fix desync for 0047-us-task-linkage
Error: Invalid YAML frontmatter in spec.md
Check YAML syntax:
vim .specweave/increments/0047-us-task-linkage/spec.md
Prevention
To prevent future desyncs:
-
✅ Atomic transaction pattern in
metadata-manager.ts- Updates spec.md FIRST, then metadata.json
- If spec.md fails, metadata.json is never updated
- No silent failures
-
✅ Desync detection in
/sw:done- Validates before closing increment
- Blocks closure if desync detected
-
✅ Pre-commit hook validation
- Scans for desyncs before commit
- Blocks commit if desyncs found
- Auto-fix option available
-
✅ Comprehensive tests
- Unit tests for DesyncDetector
- Integration tests for status updates
- E2E tests for recovery scenarios
Related Commands
/sw:done- Close increment (includes desync validation)/sw:validate- Validate increment quality/sw:status- Show increment status overview
Related Files
src/core/increment/desync-detector.ts- Detection & fix logicsrc/core/increment/metadata-manager.ts- Atomic status updatessrc/core/increment/spec-frontmatter-updater.ts- spec.md updatesscripts/pre-commit-desync-check.sh- Pre-commit validation
Important: This command is part of the incident response to the 2025-11-20 silent failure bug. It ensures source-of-truth discipline is maintained across the entire increment lifecycle.
Best Practice: Run /sw:sync-status regularly (weekly or before releases) to catch any desyncs early.
Didn't find tool you were looking for?