@leeovery/claude-technical-workflows 2.0.42 → 2.0.44

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.
@@ -0,0 +1,186 @@
1
+ #!/bin/bash
2
+ #
3
+ # Discovers the current state of specifications and plans
4
+ # for the /start-planning command.
5
+ #
6
+ # Outputs structured YAML that the command can consume directly.
7
+ #
8
+
9
+ set -eo pipefail
10
+
11
+ SPEC_DIR="docs/workflow/specification"
12
+ PLAN_DIR="docs/workflow/planning"
13
+
14
+ # Helper: Extract a frontmatter field value from a file
15
+ # Usage: extract_field <file> <field_name>
16
+ extract_field() {
17
+ local file="$1"
18
+ local field="$2"
19
+ local value=""
20
+
21
+ # Extract from YAML frontmatter (file must start with ---)
22
+ if head -1 "$file" 2>/dev/null | grep -q "^---$"; then
23
+ value=$(sed -n '2,/^---$/p' "$file" 2>/dev/null | \
24
+ grep -i -m1 "^${field}:" | \
25
+ sed -E "s/^${field}:[[:space:]]*//i" || true)
26
+ fi
27
+
28
+ echo "$value"
29
+ }
30
+
31
+ # Start YAML output
32
+ echo "# Planning Command State Discovery"
33
+ echo "# Generated: $(date -Iseconds)"
34
+ echo ""
35
+
36
+ #
37
+ # SPECIFICATIONS
38
+ #
39
+ echo "specifications:"
40
+
41
+ feature_count=0
42
+ feature_ready_count=0
43
+ crosscutting_count=0
44
+
45
+ if [ -d "$SPEC_DIR" ] && [ -n "$(ls -A "$SPEC_DIR" 2>/dev/null)" ]; then
46
+ echo " exists: true"
47
+ echo " feature:"
48
+
49
+ # First pass: feature specifications
50
+ for file in "$SPEC_DIR"/*.md; do
51
+ [ -f "$file" ] || continue
52
+
53
+ name=$(basename "$file" .md)
54
+ status=$(extract_field "$file" "status")
55
+ status=${status:-"active"}
56
+ spec_type=$(extract_field "$file" "type")
57
+ spec_type=${spec_type:-"feature"}
58
+
59
+ # Skip cross-cutting specs in this pass
60
+ [ "$spec_type" = "cross-cutting" ] && continue
61
+
62
+ # Check if plan exists
63
+ has_plan="false"
64
+ if [ -f "$PLAN_DIR/${name}.md" ]; then
65
+ has_plan="true"
66
+ fi
67
+
68
+ echo " - name: \"$name\""
69
+ echo " status: \"$status\""
70
+ echo " has_plan: $has_plan"
71
+
72
+ feature_count=$((feature_count + 1))
73
+ # "concluded" specs without plans are ready for planning
74
+ if [ "$status" = "concluded" ] && [ "$has_plan" = "false" ]; then
75
+ feature_ready_count=$((feature_ready_count + 1))
76
+ fi
77
+ done
78
+
79
+ if [ "$feature_count" -eq 0 ]; then
80
+ echo " [] # No feature specifications"
81
+ fi
82
+
83
+ echo " crosscutting:"
84
+
85
+ # Second pass: cross-cutting specifications
86
+ for file in "$SPEC_DIR"/*.md; do
87
+ [ -f "$file" ] || continue
88
+
89
+ name=$(basename "$file" .md)
90
+ spec_type=$(extract_field "$file" "type")
91
+ spec_type=${spec_type:-"feature"}
92
+
93
+ # Only cross-cutting specs in this pass
94
+ [ "$spec_type" != "cross-cutting" ] && continue
95
+
96
+ status=$(extract_field "$file" "status")
97
+ status=${status:-"active"}
98
+
99
+ echo " - name: \"$name\""
100
+ echo " status: \"$status\""
101
+
102
+ crosscutting_count=$((crosscutting_count + 1))
103
+ done
104
+
105
+ if [ "$crosscutting_count" -eq 0 ]; then
106
+ echo " [] # No cross-cutting specifications"
107
+ fi
108
+
109
+ echo " counts:"
110
+ echo " feature: $feature_count"
111
+ echo " feature_ready: $feature_ready_count"
112
+ echo " crosscutting: $crosscutting_count"
113
+ else
114
+ echo " exists: false"
115
+ echo " feature: []"
116
+ echo " crosscutting: []"
117
+ echo " counts:"
118
+ echo " feature: 0"
119
+ echo " feature_ready: 0"
120
+ echo " crosscutting: 0"
121
+ fi
122
+
123
+ echo ""
124
+
125
+ #
126
+ # PLANS
127
+ #
128
+ echo "plans:"
129
+
130
+ if [ -d "$PLAN_DIR" ] && [ -n "$(ls -A "$PLAN_DIR" 2>/dev/null)" ]; then
131
+ echo " exists: true"
132
+ echo " files:"
133
+
134
+ for file in "$PLAN_DIR"/*.md; do
135
+ [ -f "$file" ] || continue
136
+
137
+ name=$(basename "$file" .md)
138
+ format=$(extract_field "$file" "format")
139
+ format=${format:-"MISSING"}
140
+ status=$(extract_field "$file" "status")
141
+ status=${status:-"unknown"}
142
+ plan_id=$(extract_field "$file" "plan_id")
143
+
144
+ echo " - name: \"$name\""
145
+ echo " format: \"$format\""
146
+ echo " status: \"$status\""
147
+ if [ -n "$plan_id" ]; then
148
+ echo " plan_id: \"$plan_id\""
149
+ fi
150
+ done
151
+ else
152
+ echo " exists: false"
153
+ echo " files: []"
154
+ fi
155
+
156
+ echo ""
157
+
158
+ #
159
+ # WORKFLOW STATE SUMMARY
160
+ #
161
+ echo "state:"
162
+
163
+ specs_exist="false"
164
+ plans_exist="false"
165
+
166
+ if [ -d "$SPEC_DIR" ] && [ -n "$(ls -A "$SPEC_DIR" 2>/dev/null)" ]; then
167
+ specs_exist="true"
168
+ fi
169
+
170
+ if [ -d "$PLAN_DIR" ] && [ -n "$(ls -A "$PLAN_DIR" 2>/dev/null)" ]; then
171
+ plans_exist="true"
172
+ fi
173
+
174
+ echo " has_specifications: $specs_exist"
175
+ echo " has_plans: $plans_exist"
176
+
177
+ # Determine workflow state for routing
178
+ if [ "$specs_exist" = "false" ]; then
179
+ echo " scenario: \"no_specs\""
180
+ elif [ "$feature_ready_count" -eq 0 ]; then
181
+ echo " scenario: \"no_ready_specs\""
182
+ elif [ "$feature_ready_count" -eq 1 ]; then
183
+ echo " scenario: \"single_ready_spec\""
184
+ else
185
+ echo " scenario: \"multiple_ready_specs\""
186
+ fi
@@ -1,7 +1,5 @@
1
1
  #!/bin/bash
2
2
  #
3
- # discover-spec-state.sh
4
- #
5
3
  # Discovers the current state of discussions, specifications, and cache
6
4
  # for the /start-specification command.
7
5
  #
@@ -68,13 +66,20 @@ if [ -d "$DISCUSSION_DIR" ] && [ -n "$(ls -A "$DISCUSSION_DIR" 2>/dev/null)" ];
68
66
 
69
67
  # Check if this discussion has a corresponding individual spec
70
68
  has_individual_spec="false"
69
+ spec_status=""
71
70
  if [ -f "$SPEC_DIR/${name}.md" ]; then
72
71
  has_individual_spec="true"
72
+ # Extract spec status in real-time (not from cache)
73
+ spec_status=$(extract_field "$SPEC_DIR/${name}.md" "status")
74
+ spec_status=${spec_status:-"in-progress"}
73
75
  fi
74
76
 
75
77
  echo " - name: \"$name\""
76
78
  echo " status: \"$status\""
77
79
  echo " has_individual_spec: $has_individual_spec"
80
+ if [ "$has_individual_spec" = "true" ]; then
81
+ echo " spec_status: \"$spec_status\""
82
+ fi
78
83
  done
79
84
  else
80
85
  echo " [] # No discussions found"
@@ -0,0 +1,207 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # 002-specification-frontmatter.sh
4
+ #
5
+ # Migrates specification documents from legacy markdown header format to YAML frontmatter.
6
+ #
7
+ # Legacy format:
8
+ # # Specification: {Topic}
9
+ #
10
+ # **Status**: Building specification | Complete
11
+ # **Type**: feature | cross-cutting
12
+ # **Last Updated**: YYYY-MM-DD
13
+ #
14
+ # New format:
15
+ # ---
16
+ # topic: {topic-name}
17
+ # status: in-progress | concluded
18
+ # type: feature | cross-cutting | (empty if unknown)
19
+ # date: YYYY-MM-DD
20
+ # sources: # Optional - only if Sources field exists
21
+ # - discussion-one
22
+ # - discussion-two
23
+ # ---
24
+ #
25
+ # # Specification: {Topic}
26
+ #
27
+ # Status mapping (normalized across all document types):
28
+ # Building specification, Building, Draft → in-progress
29
+ # Complete, Completed, Done → concluded
30
+ #
31
+ # Type handling:
32
+ # feature → feature
33
+ # cross-cutting → cross-cutting
34
+ # (not found or unrecognized) → empty (requires manual review)
35
+ #
36
+ # This script is sourced by migrate.sh and has access to:
37
+ # - is_migrated "filepath" "migration_id"
38
+ # - record_migration "filepath" "migration_id"
39
+ # - report_update "filepath" "description"
40
+ # - report_skip "filepath"
41
+ #
42
+
43
+ MIGRATION_ID="002"
44
+ SPEC_DIR="docs/workflow/specification"
45
+
46
+ # Skip if no specification directory
47
+ if [ ! -d "$SPEC_DIR" ]; then
48
+ return 0
49
+ fi
50
+
51
+ # Process each specification file
52
+ for file in "$SPEC_DIR"/*.md; do
53
+ [ -f "$file" ] || continue
54
+
55
+ # Check if already migrated via tracking
56
+ if is_migrated "$file" "$MIGRATION_ID"; then
57
+ report_skip "$file"
58
+ continue
59
+ fi
60
+
61
+ # Check if file already has YAML frontmatter
62
+ if head -1 "$file" 2>/dev/null | grep -q "^---$"; then
63
+ # Already has frontmatter - just record and skip
64
+ record_migration "$file" "$MIGRATION_ID"
65
+ report_skip "$file"
66
+ continue
67
+ fi
68
+
69
+ # Check if file has legacy format (look for **Status**: or **Status:** or **Type**: or **Last Updated**:)
70
+ if ! grep -q '^\*\*Status\*\*:\|^\*\*Status:\*\*\|^\*\*Type\*\*:\|^\*\*Last Updated\*\*:' "$file" 2>/dev/null; then
71
+ # No legacy format found - might be malformed, skip
72
+ record_migration "$file" "$MIGRATION_ID"
73
+ report_skip "$file"
74
+ continue
75
+ fi
76
+
77
+ #
78
+ # Extract values from legacy format
79
+ #
80
+
81
+ # Use filename as topic (canonical identifier throughout the workflow)
82
+ topic_kebab=$(basename "$file" .md)
83
+
84
+ # Extract status from **Status**: Value or **Status:** Value
85
+ # Handle variations: "Building specification", "Building", "Complete", "Completed", etc.
86
+ status_raw=$(grep -m1 '^\*\*Status\*\*:\|^\*\*Status:\*\*' "$file" | \
87
+ sed 's/^\*\*Status\*\*:[[:space:]]*//' | \
88
+ sed 's/^\*\*Status:\*\*[[:space:]]*//' | \
89
+ tr '[:upper:]' '[:lower:]' | \
90
+ xargs)
91
+
92
+ # Map legacy status to normalized values (consistent across all document types)
93
+ case "$status_raw" in
94
+ "building specification"|"building"|"draft"|"in progress"|"in-progress"|"exploring"|"deciding")
95
+ status_new="in-progress"
96
+ ;;
97
+ "complete"|"completed"|"done"|"finished"|"concluded")
98
+ status_new="concluded"
99
+ ;;
100
+ *)
101
+ status_new="in-progress" # Default for unknown
102
+ ;;
103
+ esac
104
+
105
+ # Extract type from **Type**: Value (may not exist in legacy files)
106
+ type_raw=$(grep -m1 '^\*\*Type\*\*:\|^\*\*Type:\*\*' "$file" 2>/dev/null | \
107
+ sed 's/^\*\*Type\*\*:[[:space:]]*//' | \
108
+ sed 's/^\*\*Type:\*\*[[:space:]]*//' | \
109
+ tr '[:upper:]' '[:lower:]' | \
110
+ xargs || echo "")
111
+
112
+ # Normalize type (leave empty if not found or unrecognized - requires manual review)
113
+ case "$type_raw" in
114
+ "feature")
115
+ type_new="feature"
116
+ ;;
117
+ "cross-cutting"|"crosscutting"|"cross cutting")
118
+ type_new="cross-cutting"
119
+ ;;
120
+ *)
121
+ type_new="" # Empty - requires manual classification
122
+ ;;
123
+ esac
124
+
125
+ # Extract date from **Last Updated**: YYYY-MM-DD or **Date**: YYYY-MM-DD
126
+ date_value=$(grep -m1 '^\*\*Last Updated\*\*:\|^\*\*Date\*\*:' "$file" | \
127
+ grep -oE '[0-9]{4}-[0-9]{2}-[0-9]{2}' || echo "")
128
+
129
+ # Use today's date if none found
130
+ if [ -z "$date_value" ]; then
131
+ date_value=$(date +%Y-%m-%d)
132
+ fi
133
+
134
+ # Extract sources from **Sources**: source1, source2, ... (comma-separated list of discussion names)
135
+ # These link the specification back to the discussions that informed it
136
+ sources_raw=$(grep -m1 '^\*\*Sources\*\*:' "$file" 2>/dev/null | \
137
+ sed 's/^\*\*Sources\*\*:[[:space:]]*//' | \
138
+ xargs || echo "")
139
+
140
+ # Convert comma-separated list to array
141
+ sources_array=()
142
+ if [ -n "$sources_raw" ]; then
143
+ IFS=',' read -ra sources_parts <<< "$sources_raw"
144
+ for src in "${sources_parts[@]}"; do
145
+ # Trim whitespace
146
+ src=$(echo "$src" | xargs)
147
+ if [ -n "$src" ]; then
148
+ sources_array+=("$src")
149
+ fi
150
+ done
151
+ fi
152
+
153
+ #
154
+ # Build new file content
155
+ #
156
+
157
+ # Create frontmatter (conditionally include sources if present)
158
+ if [ ${#sources_array[@]} -gt 0 ]; then
159
+ sources_yaml=""
160
+ for src in "${sources_array[@]}"; do
161
+ sources_yaml="${sources_yaml}
162
+ - $src"
163
+ done
164
+ frontmatter="---
165
+ topic: $topic_kebab
166
+ status: $status_new
167
+ type: $type_new
168
+ date: $date_value
169
+ sources:$sources_yaml
170
+ ---"
171
+ else
172
+ frontmatter="---
173
+ topic: $topic_kebab
174
+ status: $status_new
175
+ type: $type_new
176
+ date: $date_value
177
+ ---"
178
+ fi
179
+
180
+ # Extract H1 heading (preserve original)
181
+ h1_heading=$(grep -m1 "^# " "$file")
182
+
183
+ # Find line number of first ## heading (start of real content after metadata)
184
+ first_section_line=$(grep -n "^## " "$file" | head -1 | cut -d: -f1)
185
+
186
+ # Get content from first ## onwards (preserves all content)
187
+ if [ -n "$first_section_line" ]; then
188
+ content=$(tail -n +$first_section_line "$file")
189
+ else
190
+ # No ## found - take everything after the metadata block
191
+ # Find first blank line after the metadata, then take from there
192
+ content=""
193
+ fi
194
+
195
+ # Write new content: frontmatter + H1 + blank line + content
196
+ {
197
+ echo "$frontmatter"
198
+ echo ""
199
+ echo "$h1_heading"
200
+ echo ""
201
+ echo "$content"
202
+ } > "$file"
203
+
204
+ # Record and report
205
+ record_migration "$file" "$MIGRATION_ID"
206
+ report_update "$file" "added frontmatter (status: $status_new, type: $type_new)"
207
+ done
@@ -0,0 +1,191 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # 003-planning-frontmatter.sh
4
+ #
5
+ # Migrates plan documents from legacy format to full YAML frontmatter.
6
+ #
7
+ # Legacy format (partial frontmatter + inline metadata):
8
+ # ---
9
+ # format: {format}
10
+ # ---
11
+ #
12
+ # # Implementation Plan: {Feature/Project Name}
13
+ #
14
+ # **Date**: YYYY-MM-DD
15
+ # **Status**: Draft | Ready | In Progress | Completed
16
+ # **Specification**: `docs/workflow/specification/{topic}.md`
17
+ #
18
+ # New format (all metadata in frontmatter):
19
+ # ---
20
+ # topic: {topic-name}
21
+ # status: in-progress | concluded
22
+ # date: YYYY-MM-DD
23
+ # format: {format} # Required - no default, MISSING if not present
24
+ # specification: {topic}.md
25
+ # plan_id: {id} # Optional - migrated from 'epic' or 'project' fields
26
+ # ---
27
+ #
28
+ # # Implementation Plan: {Feature/Project Name}
29
+ #
30
+ # Status mapping (normalized across all document types):
31
+ # Draft, Ready, In Progress → in-progress
32
+ # Completed, Done → concluded
33
+ #
34
+ # This script is sourced by migrate.sh and has access to:
35
+ # - is_migrated "filepath" "migration_id"
36
+ # - record_migration "filepath" "migration_id"
37
+ # - report_update "filepath" "description"
38
+ # - report_skip "filepath"
39
+ #
40
+
41
+ MIGRATION_ID="003"
42
+ PLAN_DIR="docs/workflow/planning"
43
+
44
+ # Skip if no planning directory
45
+ if [ ! -d "$PLAN_DIR" ]; then
46
+ return 0
47
+ fi
48
+
49
+ # Process each plan file
50
+ for file in "$PLAN_DIR"/*.md; do
51
+ [ -f "$file" ] || continue
52
+
53
+ # Check if already migrated via tracking
54
+ if is_migrated "$file" "$MIGRATION_ID"; then
55
+ report_skip "$file"
56
+ continue
57
+ fi
58
+
59
+ # Check if file already has full frontmatter (topic field present)
60
+ if head -10 "$file" 2>/dev/null | grep -q "^topic:"; then
61
+ # Already has full frontmatter - just record and skip
62
+ record_migration "$file" "$MIGRATION_ID"
63
+ report_skip "$file"
64
+ continue
65
+ fi
66
+
67
+ # Check if file has legacy format indicators
68
+ # Legacy format has partial frontmatter (format:) OR inline **Date**/**Status**/**Specification**
69
+ has_partial_frontmatter=$(head -5 "$file" 2>/dev/null | grep -c "^format:" || true)
70
+ has_inline_metadata=$(grep -c '^\*\*Date\*\*:\|^\*\*Status\*\*:\|^\*\*Specification\*\*:' "$file" 2>/dev/null || true)
71
+
72
+ if [ "${has_partial_frontmatter:-0}" = "0" ] && [ "${has_inline_metadata:-0}" = "0" ]; then
73
+ # No legacy format found - might be malformed, skip
74
+ record_migration "$file" "$MIGRATION_ID"
75
+ report_skip "$file"
76
+ continue
77
+ fi
78
+
79
+ #
80
+ # Extract values from legacy format
81
+ #
82
+
83
+ # Use filename as topic (canonical identifier throughout the workflow)
84
+ topic_kebab=$(basename "$file" .md)
85
+
86
+ # Extract format from existing frontmatter (if present)
87
+ format_value=$(sed -n '/^---$/,/^---$/p' "$file" 2>/dev/null | grep "^format:" | sed 's/^format:[[:space:]]*//' | xargs || echo "")
88
+ if [ -z "$format_value" ]; then
89
+ format_value="MISSING" # No default - missing format is an error
90
+ fi
91
+
92
+ # Extract plan_id from existing frontmatter - could be 'epic' (beads) or 'project' (linear/backlog)
93
+ # These are migrated to a unified 'plan_id' field
94
+ plan_id_value=$(sed -n '/^---$/,/^---$/p' "$file" 2>/dev/null | grep "^epic:" | sed 's/^epic:[[:space:]]*//' | xargs || echo "")
95
+ if [ -z "$plan_id_value" ]; then
96
+ plan_id_value=$(sed -n '/^---$/,/^---$/p' "$file" 2>/dev/null | grep "^project:" | sed 's/^project:[[:space:]]*//' | xargs || echo "")
97
+ fi
98
+
99
+ # Extract status from **Status**: Value
100
+ status_raw=$(grep -m1 '^\*\*Status\*\*:' "$file" 2>/dev/null | \
101
+ sed 's/^\*\*Status\*\*:[[:space:]]*//' | \
102
+ tr '[:upper:]' '[:lower:]' | \
103
+ xargs || echo "")
104
+
105
+ # Map legacy status to normalized values
106
+ case "$status_raw" in
107
+ "draft"|"ready"|"in progress"|"in-progress")
108
+ status_new="in-progress"
109
+ ;;
110
+ "completed"|"complete"|"done"|"concluded")
111
+ status_new="concluded"
112
+ ;;
113
+ *)
114
+ status_new="in-progress" # Default for unknown
115
+ ;;
116
+ esac
117
+
118
+ # Extract date from **Date**: YYYY-MM-DD or **Created**: YYYY-MM-DD
119
+ date_value=$(grep -m1 '^\*\*Date\*\*:\|^\*\*Created\*\*:' "$file" 2>/dev/null | \
120
+ grep -oE '[0-9]{4}-[0-9]{2}-[0-9]{2}' || echo "")
121
+
122
+ # Use today's date if none found
123
+ if [ -z "$date_value" ]; then
124
+ date_value=$(date +%Y-%m-%d)
125
+ fi
126
+
127
+ # Extract specification from **Specification**: `docs/workflow/specification/{topic}.md`
128
+ # We just want the filename, not the full path
129
+ spec_raw=$(grep -m1 '^\*\*Specification\*\*:' "$file" 2>/dev/null | \
130
+ sed 's/^\*\*Specification\*\*:[[:space:]]*//' | \
131
+ sed 's/`//g' | \
132
+ xargs || echo "")
133
+
134
+ # Extract just the filename from the path
135
+ if [ -n "$spec_raw" ]; then
136
+ spec_value=$(basename "$spec_raw")
137
+ else
138
+ spec_value="${topic_kebab}.md" # Default to topic name
139
+ fi
140
+
141
+ #
142
+ # Build new file content
143
+ #
144
+
145
+ # Create frontmatter (conditionally include plan_id if present)
146
+ if [ -n "$plan_id_value" ]; then
147
+ frontmatter="---
148
+ topic: $topic_kebab
149
+ status: $status_new
150
+ date: $date_value
151
+ format: $format_value
152
+ specification: $spec_value
153
+ plan_id: $plan_id_value
154
+ ---"
155
+ else
156
+ frontmatter="---
157
+ topic: $topic_kebab
158
+ status: $status_new
159
+ date: $date_value
160
+ format: $format_value
161
+ specification: $spec_value
162
+ ---"
163
+ fi
164
+
165
+ # Extract H1 heading (preserve original)
166
+ h1_heading=$(grep -m1 "^# " "$file")
167
+
168
+ # Find line number of first ## heading (start of real content after metadata)
169
+ first_section_line=$(grep -n "^## " "$file" | head -1 | cut -d: -f1)
170
+
171
+ # Get content from first ## onwards (preserves all content)
172
+ if [ -n "$first_section_line" ]; then
173
+ content=$(tail -n +$first_section_line "$file")
174
+ else
175
+ # No ## found - might be empty or malformed
176
+ content=""
177
+ fi
178
+
179
+ # Write new content: frontmatter + H1 + blank line + content
180
+ {
181
+ echo "$frontmatter"
182
+ echo ""
183
+ echo "$h1_heading"
184
+ echo ""
185
+ echo "$content"
186
+ } > "$file"
187
+
188
+ # Record and report
189
+ record_migration "$file" "$MIGRATION_ID"
190
+ report_update "$file" "added full frontmatter (status: $status_new, format: $format_value)"
191
+ done
@@ -53,7 +53,7 @@ The plan file in `docs/workflow/planning/{topic}.md` serves as the reference poi
53
53
  ```markdown
54
54
  ---
55
55
  format: backlog-md
56
- project: {TOPIC_NAME}
56
+ plan_id: {TOPIC_NAME}
57
57
  ---
58
58
 
59
59
  # Plan Reference: {Topic Name}
@@ -240,7 +240,7 @@ Create `docs/workflow/planning/{topic}.md`:
240
240
  ```markdown
241
241
  ---
242
242
  format: beads
243
- epic: bd-{EPIC_ID}
243
+ plan_id: bd-{EPIC_ID}
244
244
  ---
245
245
 
246
246
  # Plan Reference: {Topic Name}
@@ -304,7 +304,7 @@ The `format: beads` frontmatter tells implementation to use beads CLI:
304
304
  ```yaml
305
305
  ---
306
306
  format: beads
307
- epic: bd-a3f8
307
+ plan_id: bd-a3f8
308
308
  ---
309
309
  ```
310
310
 
@@ -327,7 +327,7 @@ In the task body:
327
327
 
328
328
  ### Reading Plans
329
329
 
330
- 1. Extract `epic` ID from frontmatter
330
+ 1. Extract `plan_id` (beads epic ID) from frontmatter
331
331
  2. Check `.beads/config.yaml` for `no-db` setting
332
332
  3. Run `bd ready` to get unblocked tasks
333
333
  4. View task details with `bd show bd-{id}`
@@ -148,7 +148,7 @@ Create `docs/workflow/planning/{topic}.md`:
148
148
  ```markdown
149
149
  ---
150
150
  format: linear
151
- project: {PROJECT_NAME}
151
+ plan_id: {PROJECT_NAME}
152
152
  project_id: {ID from MCP response}
153
153
  team: {TEAM_NAME}
154
154
  ---
@@ -207,7 +207,7 @@ The frontmatter contains all information needed to query Linear:
207
207
  ```yaml
208
208
  ---
209
209
  format: linear
210
- project: USER-AUTH-FEATURE
210
+ plan_id: USER-AUTH-FEATURE
211
211
  project_id: abc123-def456
212
212
  team: Engineering
213
213
  ---
@@ -257,7 +257,7 @@ Linear:
257
257
 
258
258
  ### Reading Plans
259
259
 
260
- 1. Extract `project_id` from frontmatter
260
+ 1. Extract `plan_id` (Linear project name) from frontmatter
261
261
  2. Query Linear MCP for project issues
262
262
  3. Filter issues by phase label (e.g., `phase-1`, `phase-2`)
263
263
  4. Process in phase order