- created
- 2026-01-20T00:00:00.000Z
- modified
- 2026-05-09T00:00:00.000Z
- reviewed
- 2026-04-25T00:00:00.000Z
- name
- document-linking
- description
- Unified ID system for PRDs, ADRs, PRPs, and GitHub issues with bidirectional links. Use when linking docs, finding orphans, auto-assigning IDs, or validating cross-doc references.
- user-invocable
- false
- allowed-tools
- Read, Write, Edit, Grep, Glob, Bash, TodoWrite
# Document Linking
Provides a unified ID system connecting PRDs, ADRs, PRPs, work-orders, GitHub issues, commits, and PRs. IDs are project-scoped, auto-generated on first access, and maintained bidirectionally.
## When to Use This Skill
| Use this skill when... | Use blueprint-sync-ids instead when... |
|---|---|
| You need bidirectional links between PRD/ADR/PRP/issue at runtime | You're doing a one-shot bulk ID assignment for docs missing IDs |
| You're auto-assigning an ID on first document access | You want a `--dry-run` preview of bulk ID changes |
| You want to validate broken cross-document references | Use blueprint-adr-validate instead for ADR-only relationship checks |
| You need to find orphan docs/issues across the project | Use document-detection instead when capturing a brand-new doc |
## ID Format
| Document Type | Format | Example | Notes |
|---------------|--------|---------|-------|
| PRD | `PRD-NNN` | `PRD-001` | 3-digit, zero-padded |
| ADR | `ADR-NNNN` | `ADR-0003` | 4-digit (matches existing convention) |
| PRP | `PRP-NNN` | `PRP-007` | 3-digit, zero-padded |
| Work-Order | `WO-NNN` | `WO-042` | 3-digit, matches work-order number |
## Frontmatter Schema
All blueprint documents should include these fields:
```yaml
---
id: PRD-001 # Unique identifier (auto-generated if missing)
relates-to: # Cross-document references (optional)
- ADR-0003
- PRP-002
github-issues: # Linked GitHub issues (optional)
- 42
- 87
implements: # For PRPs: source PRD (optional)
- PRD-001
# ... existing fields (created, modified, status, etc.)
---
```
## ID Registry (manifest.json)
IDs are tracked in `docs/blueprint/manifest.json`:
```json
{
"id_registry": {
"last_prd": 3,
"last_prp": 7,
"documents": {
"PRD-001": {
"path": "docs/prds/user-authentication.md",
"github_issues": [42, 87],
"title": "User Authentication"
},
"ADR-0003": {
"path": "docs/adrs/0003-database-choice.md",
"github_issues": [],
"title": "Database Choice"
},
"PRP-002": {
"path": "docs/prps/oauth-integration.md",
"github_issues": [45],
"implements": ["PRD-001"],
"title": "OAuth Integration"
}
},
"github_issues": {
"42": ["PRD-001", "PRP-002"],
"45": ["PRP-002"],
"87": ["PRD-001"]
}
}
}
```
## Auto-ID Generation
### When Triggered
IDs are automatically generated when:
1. **Creating documents** - `/blueprint:derive-plans`, `/blueprint:prp-create`
2. **Accessing documents without IDs** - Any command reading PRD/ADR/PRP files
3. **Batch sync** - `/blueprint:sync-ids` assigns IDs to all documents
### Generation Algorithm
```bash
# Get next PRD ID
get_next_prd_id() {
local manifest="docs/blueprint/manifest.json"
local last=$(jq -r '.id_registry.last_prd // 0' "$manifest")
local next=$((last + 1))
printf "PRD-%03d" "$next"
}
# Get next PRP ID
get_next_prp_id() {
local manifest="docs/blueprint/manifest.json"
local last=$(jq -r '.id_registry.last_prp // 0' "$manifest")
local next=$((last + 1))
printf "PRP-%03d" "$next"
}
# ADR IDs use existing 4-digit number from filename
get_adr_id() {
local filename="$1"
local num=$(basename "$filename" | grep -oE '^[0-9]{4}')
printf "ADR-%s" "$num"
}
```
### Auto-Assignment on Access
When reading a document without an ID:
1. **Check frontmatter** for existing `id` field
2. **If missing**: Generate next available ID
3. **Update document** frontmatter with new ID
4. **Update manifest** ID registry
5. **Continue** with original operation
```bash
# Check if document has ID
ensure_document_id() {
local file="$1"
local type="$2" # PRD, ADR, PRP
# Extract existing ID from frontmatter
local existing_id=$(head -50 "$file" | grep -m1 "^id:" | sed 's/^id:[[:space:]]*//')
if [ -z "$existing_id" ]; then
# Generate and assign new ID
case "$type" in
PRD) new_id=$(get_next_prd_id) ;;
PRP) new_id=$(get_next_prp_id) ;;
ADR) new_id=$(get_adr_id "$file") ;;
esac
# Insert ID into frontmatter (after first ---)
# Update manifest registry
# Return new ID
fi
echo "${existing_id:-$new_id}"
}
```
## GitHub Integration
### Issue Title Format
When creating GitHub issues from documents:
```
[PRD-001] User authentication feature
[PRP-002] Implement OAuth integration
[WO-042] Add JWT token generation
```
### Issue Body Format
```markdown
## Related Documents
- PRD-001: User Authentication
- ADR-0003: Database Choice
## Traceability
- **Implements**: PRD-001
- **Related ADRs**: ADR-0003, ADR-0005
- **Work Orders**: WO-042, WO-043
---
*Auto-linked by Blueprint. Update document frontmatter to modify links.*
```
### Commit Message Format
```
feat(PRD-001): add login form component
Implements requirement FR-003 from PRD-001.
Related: ADR-0003 (session storage decision)
```
### PR Title/Body Format
**Title**: `[PRD-001] Implement user authentication`
**Body**:
```markdown
## Summary
Implements user authentication as specified in PRD-001.
## Related Documents
- PRD-001: User Authentication
- ADR-0003: Database Choice
- PRP-002: OAuth Integration
## Closes
- Fixes #42
- Fixes #87
```
## Bidirectional Link Maintenance
### When Creating Links
1. **Document → GitHub Issue**
- Add issue number to document's `github-issues` array
- Add document ID to issue body (comment or edit)
- Update manifest registry
2. **Document → Document**
- Add target ID to source's `relates-to` array
- Add source ID to target's `relates-to` array (bidirectional)
- Update manifest registry
3. **PRP → PRD (implements)**
- Add PRD ID to PRP's `implements` field
- Add PRP ID to PRD's `implemented-by` tracking in manifest
### Link Validation
Check for broken links during `/blueprint:status`:
```bash
# Validate all links in manifest
validate_links() {
local manifest="docs/blueprint/manifest.json"
# Check each document exists
jq -r '.id_registry.documents | to_entries[] | "\(.key) \(.value.path)"' "$manifest" | \
while read id path; do
if [ ! -f "$path" ]; then
echo "BROKEN: $id -> $path (file missing)"
fi
done
# Check GitHub issues exist (if gh available)
if command -v gh &>/dev/null; then
jq -r '.id_registry.github_issues | keys[]' "$manifest" | \
while read issue; do
if ! gh issue view "$issue" &>/dev/null; then
echo "BROKEN: GitHub issue #$issue (not found or closed)"
fi
done
fi
}
```
## Traceability Queries
`get_related` (all documents linked to an ID) and `get_implementation_chain` (PRD → PRPs → work-orders → GitHub issues): [references/traceability-queries.md](references/traceability-queries.md).
## Orphan Detection
`find_orphan_documents` (documents without GitHub issues) and `find_orphan_issues` (issues with no registry entry and no ID in the title): [references/orphan-and-duplicate-detection.md](references/orphan-and-duplicate-detection.md).
## Duplicate Detection
Before creating a GitHub issue, run `check_for_duplicates` from [references/orphan-and-duplicate-detection.md](references/orphan-and-duplicate-detection.md) against registry titles and open issues.
## Integration Points
### /blueprint:derive-plans (PRDs)
After creating PRD:
1. Generate `PRD-NNN` ID
2. Add to frontmatter
3. Update manifest registry
4. Prompt: "Create GitHub issue for tracking?"
### /blueprint:derive-plans (ADRs)
After creating ADR:
1. Extract `ADR-NNNN` from filename
2. Add to frontmatter (if missing)
3. Update manifest registry
4. Link to related PRDs if applicable
### /blueprint:prp-create
After creating PRP:
1. Generate `PRP-NNN` ID
2. Prompt: "Which PRD does this implement?"
3. Add `implements` field
4. Update manifest registry with bidirectional link
### /blueprint:work-order
After creating work-order:
1. Assign `WO-NNN` ID
2. Auto-link to source PRP/PRD
3. Create GitHub issue with ID in title
4. Update manifest registry
### /blueprint:status
Show traceability section:
```
Traceability:
- Documents: 15 total (3 PRDs, 5 ADRs, 7 PRPs)
- Linked to GitHub: 12/15 (80%)
- Orphan documents: 3 (PRD-002, ADR-0004, PRP-006)
- Orphan issues: 2 (#23, #45)
- Broken links: 0
```
## Quick Reference
| Operation | Command |
|-----------|---------|
| Assign IDs to all docs | `/blueprint:sync-ids` |
| Link doc to issue | Update `github-issues` in frontmatter |
| Link doc to doc | Update `relates-to` in frontmatter |
| View traceability | `/blueprint:status` |
| Find orphans | `/blueprint:status` (included) |
| GitHub Format | Example |
|---------------|---------|
| Issue title | `[PRD-001] Feature name` |
| Commit scope | `feat(PRD-001): description` |
| PR reference | `Implements PRD-001, Fixes #42` |
View on GitHub