mcpField
B
blueprint-sync-ids

blueprint-sync-ids

github.com/laurigatesDocuments5951 installsUpdated 1d ago
Repository

About blueprint-sync-ids

A Blueprint documentation maintenance skill that scans PRDs, ADRs, PRPs, and work-orders, assigns missing IDs, and updates the manifest registry.

Key features

  1. 01Scan supported document types
  2. 02Assign IDs to documents
  3. 03Update the manifest registry
  4. 04Build a GitHub issue index
  5. 05Preview changes with dry-run
  6. 06Create issues for orphan documents

Use cases

  1. 01Organize documents missing identifiers
  2. 02Sync document IDs with the manifest
  3. 03Find GitHub issues linked to documents
  4. 04Create issues for unlinked documents

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/laurigates/claude-plugins --skill blueprint-sync-ids

After installing, type/blueprint-sync-idsin Claude Code to confirm it loaded.

Details

From the project README

Scan all PRDs, ADRs, PRPs, and work-orders, assign IDs to documents missing them, and update the manifest registry.

Flags

FlagDescription
--dry-runPreview changes without modifying files
--link-issuesAlso create GitHub issues for orphan documents

Prerequisites

  • Blueprint initialized (docs/blueprint/manifest.json exists)
  • At least one document exists in docs/prds/, docs/adrs/, docs/prps/, or docs/blueprint/work-orders/

Steps

Step 1: Initialize ID Registry

Check if id_registry exists in manifest:

jq -e '.id_registry' docs/blueprint/manifest.json >/dev/null 2>&1

If not, initialize it:

{
  "id_registry": {
    "last_prd": 0,
    "last_prp": 0,
    "documents": {},
    "github_issues": {}
  }
}
Step 2: Scan PRDs
for prd in docs/prds/*.md; do
  [ -f "$prd" ] || continue

  # Check for existing ID in frontmatter
  existing_id=$(head -50 "$prd" | grep -m1 "^id:" | sed 's/^id:[[:space:]]*//')

  if [ -z "$existing_id" ]; then
    echo "NEEDS_ID: $prd"
  else
    echo "HAS_ID: $prd ($existing_id)"
  fi
done
Step 3: Scan ADRs
for adr in docs/adrs/*.md; do
  [ -f "$adr" ] || continue

  # ADR ID derived from filename (0001-title.md → ADR-0001)
  filename=$(basename "$adr")
  num=$(echo "$filename" | grep -oE '^[0-9]{4}')

  if [ -n "$num" ]; then
    expected_id="ADR-$num"
    existing_id=$(head -50 "$adr" | grep -m1 "^id:" | sed 's/^id:[[:space:]]*//')

    if [ -z "$existing_id" ]; then
      echo "NEEDS_ID: $adr (should be $expected_id)"
    elif [ "$existing_id" != "$expected_id" ]; then
      echo "MISMATCH: $adr (has $existing_id, should be $expected_id)"
    else
      echo "HAS_ID: $adr ($existing_id)"
    fi
  fi
done
Step 4: Scan PRPs
for prp in docs/prps/*.md; do
  [ -f "$prp" ] || continue

  existing_id=$(head -50 "$prp" | grep -m1 "^id:" | sed 's/^id:[[:space:]]*//')

  if [ -z "$existing_id" ]; then
    echo "NEEDS_ID: $prp"
  else
    echo "HAS_ID: $prp ($existing_id)"
  fi
done
Step 5: Scan Work-Orders
for wo in docs/blueprint/work-orders/*.md; do
  [ -f "$wo" ] || continue

  # WO ID derived from filename (003-task.md → WO-003)
  filename=$(basename "$wo")
  num=$(echo "$filename" | grep -oE '^[0-9]{3}')

  if [ -n "$num" ]; then
    expected_id="WO-$num"
    existing_id=$(head -50 "$wo" | grep -m1 "^id:" | sed 's/^id:[[:space:]]*//')

    if [ -z "$existing_id" ]; then
      echo "NEEDS_ID: $wo (should be $expected_id)"
    else
      echo "HAS_ID: $wo ($existing_id)"
    fi
  fi
done
Step 6: Report Findings
Document ID Scan Results

PRDs:
- With IDs: X
- Missing IDs: Y
  - docs/prds/feature-a.md
  - docs/prds/feature-b.md

ADRs:
- With IDs: X
- Missing IDs: Y
- Mismatched IDs: Z

PRPs:
- With IDs: X
- Missing IDs: Y

Work-Orders:
- With IDs: X
- Missing IDs: Y

Total: X documents, Y need IDs
Step 7: Assign IDs (unless --dry-run)

For each document needing an ID:

PRDs:

  1. Get next PRD number: jq '.id_registry.last_prd' manifest.json + 1
  2. Generate ID: PRD-NNN (zero-padded)
  3. Insert into frontmatter after first ---:
    id: PRD-001
    
  4. Update manifest: increment last_prd, add to documents

ADRs:

  1. Derive ID from filename: 0003-title.md → ADR-0003
  2. Insert into frontmatter
  3. Add to manifest documents

PRPs:

  1. Get next PRP number: jq '.id_registry.last_prp' manifest.json + 1
  2. Generate ID: PRP-NNN
  3. Insert into frontmatter
  4. Update manifest: increment last_prp, add to documents

Work-Orders:

  1. Derive ID from filename: 003-task.md → WO-003
  2. Insert into frontmatter
  3. Add to manifest documents
Step 8: Extract Titles and Links

For each document, also extract:

  • Title: First # heading or frontmatter name/title field
  • Existing links: relates-to, implements, github-issues from frontmatter
  • Status: From frontmatter

Store in manifest registry:

{
  "documents": {
    "PRD-001": {
      "path": "docs/prds/user-auth.md",
      "title": "User Authentication",
      "status": "Active",
      "relates_to": ["ADR-0003"],
      "github_issues": [42],
      "created": "2026-01-15"
    }
  }
}
Step 9: Build GitHub Issue Index

Scan all documents for github-issues field and build reverse index:

{
  "github_issues": {
    "42": ["PRD-001", "PRP-002"],
    "45": ["WO-003"]
  }
}
Step 10: Create Issues for Orphans (if --link-issues)

For each document without github-issues:

question: "Create GitHub issue for {ID}: {title}?"
options:
  - label: "Yes, create issue"
    description: "Creates [{ID}] {title} issue"
  - label: "Skip this one"
    description: "Leave unlinked for now"
  - label: "Skip all remaining"
    description: "Don't prompt for more orphans"

If yes:

gh issue create \
  --title "[{ID}] {title}" \
  --body "## {Document Type}

**ID**: {ID}
**Document**: \`{path}\`

{Brief description from document}

---
*Auto-generated by /blueprint:sync-ids*" \
  --label "{type-label}"

Update document frontmatter and manifest with new issue number.

Step 11: Update task registry

Update the task registry entry in docs/blueprint/manifest.json:

jq --arg now "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
  --argjson processed "${DOCS_CHECKED:-0}" \
  --argjson created "${IDS_ASSIGNED:-0}" \
  '.task_registry["sync-ids"].last_completed_at = $now |
   .task_registry["sync-ids"].last_result = "success" |
   .task_registry["sync-ids"].stats.runs_total = ((.task_registry["sync-ids"].stats.runs_total // 0) + 1) |
   .task_registry["sync-ids"].stats.items_processed = $processed |
   .task_registry["sync-ids"].stats.items_created = $created' \
  docs/blueprint/manifest.json > tmp.json && mv tmp.json docs/blueprint/manifest.json
Step 12: Final Report
ID Sync Complete

Assigned IDs:
- PRD-003: docs/prds/payment-flow.md
- PRD-004: docs/prds/notifications.md
- PRP-005: docs/prps/stripe-integration.md

Updated Manifest:
- last_prd: 4
- last_prp: 5
- documents: 22 entries
- github_issues: 18 mappings

{If --link-issues:}
Created GitHub Issues:
- #52: [PRD-003] Payment Flow
- #53: [PRP-005] Stripe Integration

Still orphaned (no GitHub issues):
- ADR-0004: Database Migration Strategy
- WO-008: Add error handling

Run `/blueprint:status` to see full traceability report.

Error Handling

ConditionAction
No manifestError: Run /blueprint:init first
No documents foundWarning: No documents to scan
Frontmatter parse errorWarning: Skip file, report for manual fix
gh not availableSkip issue creation, warn user
Write permission deniedError: Check file permissions

Manifest Schema

After sync, manifest includes:

{
  "id_registry": {
    "last_prd": 4,
    "last_prp": 5,
    "documents": {
      "PRD-001": {
        "path": "docs/prds/user-auth.md",
        "title": "User Authentication",
        "status": "Active",
        "relates_to": ["ADR-0003"],
        "implements": [],
        "github_issues": [42],
        "created": "2026-01-10"
      },
      "ADR-0003": {
        "path": "docs/adrs/0003-session-storage.md",
        "title": "Session Storage Strategy",
        "status": "Accepted",
        "domain": "authentication",
        "relates_to": ["PRD-001"],
        "github_issues": [],
        "created": "2026-01-12"
      }
    },
    "github_issues": {
      "42": ["PRD-001", "PRP-002"],
      "45": ["WO-003"]
    }
  }
}

Comments

Markdown supported