@leeovery/claude-technical-workflows 2.0.51 → 2.0.52

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.
@@ -65,13 +65,13 @@ Stop here.
65
65
 
66
66
  ## Step 3: Extract External Dependencies
67
67
 
68
- For each plan, find the External Dependencies section:
68
+ For each plan, read the `external_dependencies` field from the frontmatter:
69
69
 
70
- 1. **Read the External Dependencies section** from each plan index file
71
- 2. **Categorize each dependency**:
72
- - **Unresolved**: `- {topic}: {description}` (no arrow, no task ID)
73
- - **Resolved**: `- {topic}: {description} → {task-id}` (has task ID)
74
- - **Satisfied externally**: `- ~~{topic}: {description}~~ → satisfied externally`
70
+ 1. **Read `external_dependencies`** from each plan index file's frontmatter
71
+ 2. **Categorize each dependency** by its `state` field:
72
+ - **Unresolved**: `state: unresolved` (no task linked)
73
+ - **Resolved**: `state: resolved` (has `task_id`)
74
+ - **Satisfied externally**: `state: satisfied_externally`
75
75
 
76
76
  3. **Build a summary**:
77
77
 
@@ -84,7 +84,7 @@ Plan: authentication (format: {format})
84
84
 
85
85
  Plan: billing-system (format: {format})
86
86
  - authentication: User context (unresolved)
87
- - ~~payment-gateway: Payment processing~~ satisfied externally
87
+ - payment-gateway: Payment processing (satisfied externally)
88
88
 
89
89
  Plan: notifications (format: {format})
90
90
  - authentication: User lookup (unresolved)
@@ -111,8 +111,8 @@ For each unresolved dependency:
111
111
 
112
112
  For each resolved match:
113
113
 
114
- 1. **Update the plan index file**:
115
- - Change `- {topic}: {description}` to `- {topic}: {description} {task-id}`
114
+ 1. **Update the plan index file's frontmatter**:
115
+ - Change the dependency's `state: unresolved` to `state: resolved` and add `task_id: {task-id}`
116
116
 
117
117
  2. **Create dependency in output format**:
118
118
  - Load `skills/technical-planning/references/output-formats/output-{format}.md`
@@ -123,7 +123,7 @@ For each resolved match:
123
123
  For each plan that was a dependency target (i.e., other plans depend on it):
124
124
 
125
125
  1. **Check reverse dependencies**: Are there other plans that should have this wired up?
126
- 2. **Offer to update**: "Plan X depends on tasks you just linked. Update its External Dependencies section?"
126
+ 2. **Offer to update**: "Plan X depends on tasks you just linked. Update its `external_dependencies` frontmatter?"
127
127
 
128
128
  ## Step 7: Report Results
129
129
 
@@ -61,14 +61,30 @@ This outputs structured YAML. Parse it to understand:
61
61
  **From `plans` section:**
62
62
  - `exists` - whether any plans exist
63
63
  - `files` - list of plans with: name, topic, status, date, format, specification, specification_exists, plan_id (if present)
64
+ - Per plan `external_deps` - array of dependencies with topic, state, task_id
65
+ - Per plan `has_unresolved_deps` - whether plan has unresolved dependencies
66
+ - Per plan `unresolved_dep_count` - count of unresolved dependencies
64
67
  - `count` - total number of plans
65
68
 
69
+ **From `implementation` section:**
70
+ - `exists` - whether any implementation tracking files exist
71
+ - `files` - list of tracking files with: topic, status, current_phase, completed_phases, completed_tasks
72
+
73
+ **From `dependency_resolution` section:**
74
+ - Per plan `deps_satisfied` - whether all resolved deps have their tasks completed
75
+ - Per plan `deps_blocking` - list of deps not yet satisfied with reason
76
+
66
77
  **From `environment` section:**
67
78
  - `setup_file_exists` - whether environment-setup.md exists
68
79
  - `requires_setup` - true, false, or unknown
69
80
 
70
81
  **From `state` section:**
71
82
  - `scenario` - one of: `"no_plans"`, `"single_plan"`, `"multiple_plans"`
83
+ - `plans_concluded_count` - plans with status concluded
84
+ - `plans_with_unresolved_deps` - plans with unresolved external deps
85
+ - `plans_ready_count` - concluded plans with all deps satisfied
86
+ - `plans_in_progress_count` - implementations in progress
87
+ - `plans_completed_count` - implementations completed
72
88
 
73
89
  **IMPORTANT**: Use ONLY this script for discovery. Do NOT run additional bash commands (ls, head, cat, etc.) to gather state - the script provides everything needed.
74
90
 
@@ -102,66 +118,137 @@ Plans exist.
102
118
 
103
119
  ## Step 3: Present Plans and Select
104
120
 
105
- Present all discovered plans to help the user make an informed choice.
121
+ Present all discovered plans using the icon system below. Classify each plan into one of three sections based on its state.
122
+
123
+ **Classification logic:**
124
+
125
+ A plan is **Implementable** if:
126
+ - It has `status: concluded` AND all deps are satisfied (`deps_satisfied: true` or no deps) AND no tracking file or tracking `status: not-started`, OR
127
+ - It has an implementation tracking file with `status: in-progress`
128
+
129
+ A plan is **Implemented** if:
130
+ - It has an implementation tracking file with `status: completed`
131
+
132
+ A plan is **Not implementable** if:
133
+ - It has `status: concluded` but deps are NOT satisfied (blocking deps exist)
134
+ - It has `status: planning` or other non-concluded status
135
+ - It has unresolved deps (`has_unresolved_deps: true`)
106
136
 
107
137
  **Present the full state:**
108
138
 
109
139
  ```
110
- Available Plans:
140
+ Implementation Phase
141
+
142
+ Implementable:
143
+ 1. ▶ billing - continue [Phase 2, Task 3]
144
+ 2. + core-features - start
111
145
 
112
- 1. {topic-1} (in-progress) - format: {format}
113
- 2. {topic-2} (concluded) - format: {format}
114
- 3. {topic-3} (in-progress) - format: {format}
146
+ Implemented:
147
+ 3. > user-auth
115
148
 
116
- Which plan would you like to implement? (Enter a number or name)
149
+ Not implementable:
150
+ · advanced-features [blocked: core-features task core-2-3 not completed]
151
+ · reporting [planning]
117
152
  ```
118
153
 
119
- **Legend:**
120
- - `in-progress` = implementation ongoing or not started
121
- - `concluded` = implementation complete (can still be selected for review/continuation)
154
+ **Formatting rules:**
155
+
156
+ Implementable (numbered, selectable):
157
+ - **`▶`** — implementation `status: in-progress`, show current position `[Phase N, Task M]`
158
+ - **`+`** — concluded plan, deps met, no tracking file or tracking `status: not-started`
159
+
160
+ Implemented (numbered, selectable):
161
+ - **`>`** — implementation `status: completed`
162
+
163
+ Not implementable (not numbered, not selectable):
164
+ - **`·`** — blocked or plan not concluded
165
+ - `[blocked: {topic} task {id} not completed]` — resolved dep, task not done
166
+ - `[blocked: unresolved dep on {topic}]` — no task linked
167
+ - `[planning]` — plan status is not `concluded`
168
+
169
+ **Ordering:**
170
+ 1. Implementable first: `▶` in-progress, then `+` new (foundational before dependent)
171
+ 2. Implemented next: `>` completed
172
+ 3. Not implementable last
173
+
174
+ Numbering is sequential across Implementable and Implemented. Omit any section entirely if it has no entries.
175
+
176
+ **If Not implementable section is shown**, append after the presentation:
122
177
 
123
- **If single plan exists (auto-select):**
124
178
  ```
125
- Auto-selecting: {topic} (only available plan)
179
+ If a blocked dependency has been resolved outside this workflow, name the plan and the dependency to unblock it.
180
+ ```
181
+
182
+ **Then prompt based on what's actionable:**
183
+
184
+ **If single implementable plan and no implemented plans (auto-select):**
185
+ ```
186
+ Auto-selecting: {topic} (only implementable plan)
126
187
  ```
127
188
  → Proceed directly to **Step 4**.
128
189
 
129
- **If multiple plans exist:**
190
+ **If nothing selectable (no implementable or implemented):**
191
+ Show Not implementable section only (with unblock hint above).
192
+
193
+ ```
194
+ No implementable plans.
195
+
196
+ To proceed:
197
+ - Complete blocking dependencies first
198
+ - Or finish plans still in progress with /start-planning
199
+ ```
130
200
 
131
201
  **STOP.** Wait for user response.
132
202
 
203
+ **Otherwise (multiple selectable plans, or implemented plans exist):**
204
+ ```
205
+ Select a plan (enter number):
206
+ ```
207
+
208
+ **STOP.** Wait for user response.
209
+
210
+ #### If the user requests an unblock
211
+
212
+ 1. Identify the plan and the specific dependency
213
+ 2. Confirm with the user which dependency to mark as satisfied
214
+ 3. Update the plan's `external_dependencies` frontmatter: set `state` to `satisfied_externally`
215
+ 4. Commit the change
216
+ 5. Re-run classification and re-present Step 3
217
+
133
218
  → Based on user choice, proceed to **Step 4**.
134
219
 
135
220
  ---
136
221
 
137
222
  ## Step 4: Check External Dependencies
138
223
 
139
- **This step is a gate.** Implementation cannot proceed if dependencies are not satisfied.
140
-
141
- See **[dependencies.md](../../skills/technical-planning/references/dependencies.md)** for dependency format and states.
224
+ **This step is a confirmation gate.** Dependencies have been pre-analyzed by the discovery script.
142
225
 
143
226
  After the plan is selected:
144
227
 
145
- 1. **Read the External Dependencies section** from the plan file
146
- 2. **Check each dependency** according to its state:
147
- - **Unresolved**: Block
148
- - **Resolved**: Check if task is complete (load output format reference, follow "Querying Dependencies" section)
149
- - **Satisfied externally**: Proceed
228
+ 1. **Check the plan's `external_deps` and `dependency_resolution`** from the discovery output
229
+
230
+ #### If all deps satisfied (or no deps)
231
+
232
+ ```
233
+ External dependencies satisfied.
234
+ ```
235
+
236
+ → Proceed to **Step 5**.
150
237
 
151
- ### Blocking Behavior
238
+ #### If any deps are blocking
152
239
 
153
- If ANY dependency is unresolved or incomplete, **stop and present**:
240
+ This should not normally happen for plans classified as "Implementable" in Step 3. However, as an escape hatch:
154
241
 
155
242
  ```
156
- ⚠️ Implementation blocked. Missing dependencies:
243
+ Missing dependencies:
157
244
 
158
245
  UNRESOLVED (not yet planned):
159
- - billing-system: Invoice generation for order completion
160
- No plan exists for this topic. Create with /start-planning or mark as satisfied externally.
246
+ - {topic}: {description}
247
+ -> No plan exists for this topic. Create with /start-planning or mark as satisfied externally.
161
248
 
162
249
  INCOMPLETE (planned but not implemented):
163
- - authentication: User context retrieval
164
- Status: in-progress. This task must be completed first.
250
+ - {topic}: task {task_id} not yet completed
251
+ -> This task must be completed first.
165
252
 
166
253
  OPTIONS:
167
254
  1. Implement the blocking dependencies first
@@ -171,23 +258,15 @@ OPTIONS:
171
258
 
172
259
  **STOP.** Wait for user response.
173
260
 
174
- ### Escape Hatch
261
+ #### Escape Hatch
175
262
 
176
263
  If the user says a dependency has been implemented outside the workflow:
177
264
 
178
265
  1. Ask which dependency to mark as satisfied
179
- 2. Update the plan file: Change `- {topic}: {description}` to `- ~~{topic}: {description}~~ → satisfied externally`
266
+ 2. Update the plan frontmatter: Change the dependency's `state` to `satisfied_externally`
180
267
  3. Commit the change
181
268
  4. Re-check dependencies
182
269
 
183
- ### All Dependencies Satisfied
184
-
185
- If all dependencies are resolved and complete (or satisfied externally), proceed to Step 5.
186
-
187
- ```
188
- ✅ External dependencies satisfied.
189
- ```
190
-
191
270
  → Proceed to **Step 5**.
192
271
 
193
272
  ---
@@ -227,32 +306,7 @@ Are there any environment setup instructions I should follow before implementati
227
306
 
228
307
  ---
229
308
 
230
- ## Step 6: Ask About Scope
231
-
232
- Ask the user about implementation scope:
233
-
234
- ```
235
- How would you like to proceed?
236
-
237
- 1. Implement all phases - Work through the entire plan sequentially
238
- 2. Implement specific phase - Focus on one phase (e.g., "Phase 1")
239
- 3. Implement specific task - Focus on a single task
240
- 4. Next available task - Auto-discover the next incomplete task
241
-
242
- Which approach?
243
- ```
244
-
245
- **STOP.** Wait for user response.
246
-
247
- If they choose a specific phase or task, ask them to specify which one.
248
-
249
- > **Note:** Do NOT verify that the phase or task exists at this stage. Record the user's answer in the handoff context. Validation happens when the skill is invoked.
250
-
251
- → Proceed to **Step 7**.
252
-
253
- ---
254
-
255
- ## Step 7: Invoke the Skill
309
+ ## Step 6: Invoke the Skill
256
310
 
257
311
  After completing the steps above, this command's purpose is fulfilled.
258
312
 
@@ -265,9 +319,9 @@ Plan: docs/workflow/planning/{topic}.md
265
319
  Format: {format}
266
320
  Plan ID: {plan_id} (if applicable)
267
321
  Specification: {specification} (exists: {true|false})
268
- Scope: {all phases | Phase N | Task N.M | next-available}
322
+ Implementation tracking: {exists | new} (status: {in-progress | not-started | completed})
269
323
 
270
- Dependencies: {All satisfied | List any notes}
324
+ Dependencies: {All satisfied | List any notes}
271
325
  Environment: {Setup required | No special setup required}
272
326
 
273
327
  Invoke the technical-implementation skill.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leeovery/claude-technical-workflows",
3
- "version": "2.0.51",
3
+ "version": "2.0.52",
4
4
  "description": "Technical workflow skills & commands for Claude Code",
5
5
  "license": "MIT",
6
6
  "author": "Lee Overy <me@leeovery.com>",
@@ -9,6 +9,7 @@ set -eo pipefail
9
9
 
10
10
  PLAN_DIR="docs/workflow/planning"
11
11
  SPEC_DIR="docs/workflow/specification"
12
+ IMPL_DIR="docs/workflow/implementation"
12
13
  ENVIRONMENT_FILE="docs/workflow/environment-setup.md"
13
14
 
14
15
  # Helper: Extract a frontmatter field value from a file
@@ -28,6 +29,117 @@ extract_field() {
28
29
  echo "$value"
29
30
  }
30
31
 
32
+ # Helper: Extract frontmatter content (between first pair of --- delimiters)
33
+ extract_frontmatter() {
34
+ local file="$1"
35
+ awk 'BEGIN{c=0} /^---$/{c++; if(c==2) exit; next} c==1{print}' "$file" 2>/dev/null
36
+ }
37
+
38
+ # Helper: Extract external_dependencies from plan frontmatter
39
+ # Outputs individual dep entries as: topic|description|state|task_id
40
+ extract_external_deps() {
41
+ local file="$1"
42
+ local frontmatter
43
+ frontmatter=$(extract_frontmatter "$file")
44
+
45
+ # Check if external_dependencies exists and is not empty array
46
+ if ! echo "$frontmatter" | grep -q "^external_dependencies:" 2>/dev/null; then
47
+ return 0
48
+ fi
49
+
50
+ # Check for empty array format
51
+ if echo "$frontmatter" | grep -q "^external_dependencies:[[:space:]]*\[\]" 2>/dev/null; then
52
+ return 0
53
+ fi
54
+
55
+ # Extract the external_dependencies block
56
+ echo "$frontmatter" | awk '
57
+ /^external_dependencies:/ { in_block=1; next }
58
+ in_block && /^[a-z_]+:/ && !/^[[:space:]]/ { exit }
59
+ in_block && /^[[:space:]]*- topic:/ {
60
+ # Print previous entry if we have one
61
+ if (topic != "" && state != "") {
62
+ print topic "|" desc "|" state "|" task_id
63
+ }
64
+ # Start new entry
65
+ line=$0; gsub(/^[[:space:]]*- topic:[[:space:]]*/, "", line)
66
+ topic=line; desc=""; state=""; task_id=""
67
+ next
68
+ }
69
+ in_block && /^[[:space:]]*description:/ {
70
+ line=$0; gsub(/^[[:space:]]*description:[[:space:]]*/, "", line)
71
+ desc=line; next
72
+ }
73
+ in_block && /^[[:space:]]*state:/ {
74
+ line=$0; gsub(/^[[:space:]]*state:[[:space:]]*/, "", line)
75
+ state=line; next
76
+ }
77
+ in_block && /^[[:space:]]*task_id:/ {
78
+ line=$0; gsub(/^[[:space:]]*task_id:[[:space:]]*/, "", line)
79
+ task_id=line; next
80
+ }
81
+ END {
82
+ if (topic != "" && state != "") {
83
+ print topic "|" desc "|" state "|" task_id
84
+ }
85
+ }
86
+ '
87
+ }
88
+
89
+ # Helper: Extract completed_tasks from implementation tracking file
90
+ # Returns space-separated list of task IDs
91
+ extract_completed_tasks() {
92
+ local file="$1"
93
+ local frontmatter
94
+ frontmatter=$(extract_frontmatter "$file")
95
+
96
+ # Check for empty array
97
+ if echo "$frontmatter" | grep -q "^completed_tasks:[[:space:]]*\[\]" 2>/dev/null; then
98
+ return 0
99
+ fi
100
+
101
+ echo "$frontmatter" | awk '
102
+ /^completed_tasks:/ { in_block=1; next }
103
+ in_block && /^[a-z_]+:/ { exit }
104
+ in_block && /^[[:space:]]*-[[:space:]]/ {
105
+ gsub(/^[[:space:]]*-[[:space:]]*/, "")
106
+ gsub(/"/, "")
107
+ print
108
+ }
109
+ '
110
+ }
111
+
112
+ # Helper: Extract completed_phases from implementation tracking file
113
+ # Returns space-separated list of phase numbers
114
+ extract_completed_phases() {
115
+ local file="$1"
116
+ local frontmatter
117
+ frontmatter=$(extract_frontmatter "$file")
118
+
119
+ # Check for inline array format: [1, 2, 3]
120
+ local inline
121
+ inline=$(echo "$frontmatter" | grep "^completed_phases:" | sed 's/^completed_phases:[[:space:]]*//' || true)
122
+ if echo "$inline" | grep -q '^\['; then
123
+ echo "$inline" | tr -d '[]' | tr ',' '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | grep -v '^$'
124
+ return 0
125
+ fi
126
+
127
+ # Check for empty array
128
+ if echo "$frontmatter" | grep -q "^completed_phases:[[:space:]]*\[\]" 2>/dev/null; then
129
+ return 0
130
+ fi
131
+
132
+ echo "$frontmatter" | awk '
133
+ /^completed_phases:/ { in_block=1; next }
134
+ in_block && /^[a-z_]+:/ { exit }
135
+ in_block && /^[[:space:]]*-[[:space:]]/ {
136
+ gsub(/^[[:space:]]*-[[:space:]]*/, "")
137
+ print
138
+ }
139
+ '
140
+ }
141
+
142
+
31
143
  # Start YAML output
32
144
  echo "# Implementation Command State Discovery"
33
145
  echo "# Generated: $(date -Iseconds)"
@@ -39,6 +151,12 @@ echo ""
39
151
  echo "plans:"
40
152
 
41
153
  plan_count=0
154
+ plans_concluded_count=0
155
+ plans_with_unresolved_deps=0
156
+
157
+ # Arrays to store plan data for cross-referencing
158
+ declare -a plan_names=()
159
+ declare -a plan_statuses=()
42
160
 
43
161
  if [ -d "$PLAN_DIR" ] && [ -n "$(ls -A "$PLAN_DIR" 2>/dev/null)" ]; then
44
162
  echo " exists: true"
@@ -60,6 +178,14 @@ if [ -d "$PLAN_DIR" ] && [ -n "$(ls -A "$PLAN_DIR" 2>/dev/null)" ]; then
60
178
  specification=${specification:-"${name}.md"}
61
179
  plan_id=$(extract_field "$file" "plan_id")
62
180
 
181
+ # Track plan data
182
+ plan_names+=("$name")
183
+ plan_statuses+=("$status")
184
+
185
+ if [ "$status" = "concluded" ]; then
186
+ plans_concluded_count=$((plans_concluded_count + 1))
187
+ fi
188
+
63
189
  # Check if linked specification exists
64
190
  spec_exists="false"
65
191
  spec_file="$SPEC_DIR/$specification"
@@ -78,6 +204,39 @@ if [ -d "$PLAN_DIR" ] && [ -n "$(ls -A "$PLAN_DIR" 2>/dev/null)" ]; then
78
204
  echo " plan_id: \"$plan_id\""
79
205
  fi
80
206
 
207
+ #
208
+ # External dependencies from frontmatter
209
+ #
210
+ deps_output=$(extract_external_deps "$file")
211
+ has_unresolved="false"
212
+ unresolved_count=0
213
+ dep_count=0
214
+
215
+ echo " external_deps:"
216
+ if [ -z "$deps_output" ]; then
217
+ echo " []"
218
+ else
219
+ while IFS='|' read -r dep_topic dep_desc dep_state dep_task_id; do
220
+ [ -z "$dep_topic" ] && continue
221
+ dep_count=$((dep_count + 1))
222
+ echo " - topic: \"$dep_topic\""
223
+ echo " state: \"$dep_state\""
224
+ if [ -n "$dep_task_id" ]; then
225
+ echo " task_id: \"$dep_task_id\""
226
+ fi
227
+ if [ "$dep_state" = "unresolved" ]; then
228
+ has_unresolved="true"
229
+ unresolved_count=$((unresolved_count + 1))
230
+ fi
231
+ done <<< "$deps_output"
232
+ fi
233
+ echo " has_unresolved_deps: $has_unresolved"
234
+ echo " unresolved_dep_count: $unresolved_count"
235
+
236
+ if [ "$has_unresolved" = "true" ]; then
237
+ plans_with_unresolved_deps=$((plans_with_unresolved_deps + 1))
238
+ fi
239
+
81
240
  plan_count=$((plan_count + 1))
82
241
  done
83
242
 
@@ -90,6 +249,145 @@ fi
90
249
 
91
250
  echo ""
92
251
 
252
+ #
253
+ # IMPLEMENTATION TRACKING
254
+ #
255
+ echo "implementation:"
256
+
257
+ impl_count=0
258
+ plans_in_progress_count=0
259
+ plans_completed_count=0
260
+
261
+ if [ -d "$IMPL_DIR" ] && [ -n "$(ls -A "$IMPL_DIR" 2>/dev/null)" ]; then
262
+ echo " exists: true"
263
+ echo " files:"
264
+
265
+ for file in "$IMPL_DIR"/*.md; do
266
+ [ -f "$file" ] || continue
267
+
268
+ impl_name=$(basename "$file" .md)
269
+ impl_status=$(extract_field "$file" "status")
270
+ impl_status=${impl_status:-"unknown"}
271
+ current_phase=$(extract_field "$file" "current_phase")
272
+ current_task=$(extract_field "$file" "current_task")
273
+
274
+ echo " - topic: \"$impl_name\""
275
+ echo " status: \"$impl_status\""
276
+
277
+ if [ -n "$current_phase" ] && [ "$current_phase" != "~" ]; then
278
+ echo " current_phase: $current_phase"
279
+ fi
280
+
281
+ # Completed phases
282
+ completed_phases_list=$(extract_completed_phases "$file")
283
+ if [ -n "$completed_phases_list" ]; then
284
+ phases_inline=$(echo "$completed_phases_list" | tr '\n' ',' | sed 's/,$//' | sed 's/,/, /g')
285
+ echo " completed_phases: [$phases_inline]"
286
+ else
287
+ echo " completed_phases: []"
288
+ fi
289
+
290
+ # Completed tasks
291
+ completed_tasks_list=$(extract_completed_tasks "$file")
292
+ if [ -n "$completed_tasks_list" ]; then
293
+ echo " completed_tasks:"
294
+ while IFS= read -r task_id; do
295
+ [ -z "$task_id" ] && continue
296
+ echo " - \"$task_id\""
297
+ done <<< "$completed_tasks_list"
298
+ else
299
+ echo " completed_tasks: []"
300
+ fi
301
+
302
+ # Track counts
303
+ if [ "$impl_status" = "in-progress" ]; then
304
+ plans_in_progress_count=$((plans_in_progress_count + 1))
305
+ elif [ "$impl_status" = "completed" ]; then
306
+ plans_completed_count=$((plans_completed_count + 1))
307
+ fi
308
+
309
+ impl_count=$((impl_count + 1))
310
+ done
311
+ else
312
+ echo " exists: false"
313
+ echo " files: []"
314
+ fi
315
+
316
+ echo ""
317
+
318
+ #
319
+ # DEPENDENCY RESOLUTION (cross-reference resolved deps against tracking files)
320
+ #
321
+ # For each plan with resolved deps, check if the referenced tasks are actually completed
322
+ # by reading the dependency topic's tracking file
323
+ #
324
+ echo "dependency_resolution:"
325
+
326
+ if [ "$plan_count" -gt 0 ] && [ -d "$PLAN_DIR" ]; then
327
+ has_resolution_data=false
328
+
329
+ for file in "$PLAN_DIR"/*.md; do
330
+ [ -f "$file" ] || continue
331
+
332
+ name=$(basename "$file" .md)
333
+ deps_output=$(extract_external_deps "$file")
334
+ [ -z "$deps_output" ] && continue
335
+
336
+ all_satisfied=true
337
+ has_resolved_deps=false
338
+ blocking_entries=""
339
+
340
+ while IFS='|' read -r dep_topic dep_desc dep_state dep_task_id; do
341
+ [ -z "$dep_topic" ] && continue
342
+
343
+ if [ "$dep_state" = "resolved" ] && [ -n "$dep_task_id" ]; then
344
+ has_resolved_deps=true
345
+ # Check if the dependency topic has a tracking file
346
+ tracking_file="$IMPL_DIR/${dep_topic}.md"
347
+ task_completed=false
348
+
349
+ if [ -f "$tracking_file" ]; then
350
+ # Check if task_id is in completed_tasks
351
+ completed=$(extract_completed_tasks "$tracking_file")
352
+ if echo "$completed" | grep -qx "$dep_task_id" 2>/dev/null; then
353
+ task_completed=true
354
+ fi
355
+ fi
356
+
357
+ if ! $task_completed; then
358
+ all_satisfied=false
359
+ blocking_entries="${blocking_entries} - topic: \"$dep_topic\"\n task_id: \"$dep_task_id\"\n reason: \"task not yet completed\"\n"
360
+ fi
361
+ elif [ "$dep_state" = "unresolved" ]; then
362
+ has_resolved_deps=true
363
+ all_satisfied=false
364
+ blocking_entries="${blocking_entries} - topic: \"$dep_topic\"\n reason: \"dependency unresolved\"\n"
365
+ fi
366
+ # satisfied_externally deps don't block
367
+ done <<< "$deps_output"
368
+
369
+ if $has_resolved_deps || [ -n "$blocking_entries" ]; then
370
+ if ! $has_resolution_data; then
371
+ has_resolution_data=true
372
+ fi
373
+ echo " - plan: \"$name\""
374
+ echo " deps_satisfied: $all_satisfied"
375
+ if [ -n "$blocking_entries" ]; then
376
+ echo " deps_blocking:"
377
+ echo -e "$blocking_entries" | sed '/^$/d'
378
+ fi
379
+ fi
380
+ done
381
+
382
+ if ! $has_resolution_data; then
383
+ echo " []"
384
+ fi
385
+ else
386
+ echo " []"
387
+ fi
388
+
389
+ echo ""
390
+
93
391
  #
94
392
  # ENVIRONMENT
95
393
  #
@@ -120,6 +418,54 @@ echo "state:"
120
418
 
121
419
  echo " has_plans: $([ "$plan_count" -gt 0 ] && echo "true" || echo "false")"
122
420
  echo " plan_count: $plan_count"
421
+ echo " plans_concluded_count: $plans_concluded_count"
422
+ echo " plans_with_unresolved_deps: $plans_with_unresolved_deps"
423
+
424
+ # Plans ready = concluded + all deps satisfied (no unresolved, all resolved tasks completed)
425
+ plans_ready_count=0
426
+ if [ "$plan_count" -gt 0 ] && [ -d "$PLAN_DIR" ]; then
427
+ for file in "$PLAN_DIR"/*.md; do
428
+ [ -f "$file" ] || continue
429
+ name=$(basename "$file" .md)
430
+ status=$(extract_field "$file" "status")
431
+
432
+ if [ "$status" = "concluded" ]; then
433
+ deps_output=$(extract_external_deps "$file")
434
+ is_ready=true
435
+
436
+ if [ -n "$deps_output" ]; then
437
+ while IFS='|' read -r dep_topic dep_desc dep_state dep_task_id; do
438
+ [ -z "$dep_topic" ] && continue
439
+
440
+ if [ "$dep_state" = "unresolved" ]; then
441
+ is_ready=false
442
+ break
443
+ elif [ "$dep_state" = "resolved" ] && [ -n "$dep_task_id" ]; then
444
+ tracking_file="$IMPL_DIR/${dep_topic}.md"
445
+ if [ -f "$tracking_file" ]; then
446
+ completed=$(extract_completed_tasks "$tracking_file")
447
+ if ! echo "$completed" | grep -qx "$dep_task_id" 2>/dev/null; then
448
+ is_ready=false
449
+ break
450
+ fi
451
+ else
452
+ is_ready=false
453
+ break
454
+ fi
455
+ fi
456
+ done <<< "$deps_output"
457
+ fi
458
+
459
+ if $is_ready; then
460
+ plans_ready_count=$((plans_ready_count + 1))
461
+ fi
462
+ fi
463
+ done
464
+ fi
465
+
466
+ echo " plans_ready_count: $plans_ready_count"
467
+ echo " plans_in_progress_count: $plans_in_progress_count"
468
+ echo " plans_completed_count: $plans_completed_count"
123
469
 
124
470
  # Determine workflow state for routing
125
471
  if [ "$plan_count" -eq 0 ]; then
@@ -0,0 +1,231 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # 005-plan-external-deps-frontmatter.sh
4
+ #
5
+ # Migrates external dependencies from body markdown section to plan frontmatter.
6
+ #
7
+ # Previous format (body section):
8
+ # ## External Dependencies
9
+ #
10
+ # - billing-system: Invoice generation for order completion
11
+ # - user-authentication: User context for permissions → auth-1-3 (resolved)
12
+ # - ~~payment-gateway: Payment processing~~ → satisfied externally
13
+ #
14
+ # New format (frontmatter):
15
+ # external_dependencies:
16
+ # - topic: billing-system
17
+ # description: Invoice generation for order completion
18
+ # state: unresolved
19
+ # - topic: user-authentication
20
+ # description: User context for permissions
21
+ # state: resolved
22
+ # task_id: auth-1-3
23
+ # - topic: payment-gateway
24
+ # description: Payment processing
25
+ # state: satisfied_externally
26
+ #
27
+ # Body formats handled:
28
+ # - "- {topic}: {description}" → state: unresolved
29
+ # - "- {topic}: {description} → {task-id}" or with "(resolved)" → state: resolved, task_id
30
+ # - "- ~~{topic}: {description}~~ → satisfied externally" → state: satisfied_externally
31
+ #
32
+ # This script is sourced by migrate.sh and has access to:
33
+ # - is_migrated "filepath" "migration_id"
34
+ # - record_migration "filepath" "migration_id"
35
+ # - report_update "filepath" "description"
36
+ # - report_skip "filepath"
37
+ #
38
+
39
+ MIGRATION_ID="005"
40
+ PLAN_DIR="docs/workflow/planning"
41
+
42
+ # Skip if no planning directory
43
+ if [ ! -d "$PLAN_DIR" ]; then
44
+ return 0
45
+ fi
46
+
47
+ # Helper: Extract ONLY the frontmatter content (between first pair of --- delimiters)
48
+ extract_frontmatter_005() {
49
+ local file="$1"
50
+ awk 'BEGIN{c=0} /^---$/{c++; if(c==2) exit; next} c==1{print}' "$file" 2>/dev/null
51
+ }
52
+
53
+ # Helper: Extract content after frontmatter (preserving all body ---)
54
+ extract_body_005() {
55
+ local file="$1"
56
+ awk '/^---$/ && c<2 {c++; next} c>=2 {print}' "$file"
57
+ }
58
+
59
+ # Helper: Extract the External Dependencies section from body content
60
+ # Returns only the direct content (list items, "None." text) — stops at subsections (###) or next section (##)
61
+ extract_ext_deps_section() {
62
+ local body="$1"
63
+ echo "$body" | awk '
64
+ /^## External Dependencies/ { found=1; next }
65
+ found && /^## [^#]/ { exit }
66
+ found && /^### / { exit }
67
+ found { print }
68
+ '
69
+ }
70
+
71
+ # Helper: Parse a single dependency line into topic, description, state, task_id
72
+ # Sets global variables: DEP_TOPIC, DEP_DESC, DEP_STATE, DEP_TASK_ID
73
+ parse_dep_line() {
74
+ local line="$1"
75
+ DEP_TOPIC=""
76
+ DEP_DESC=""
77
+ DEP_STATE=""
78
+ DEP_TASK_ID=""
79
+
80
+ # Strip leading "- " or " - "
81
+ line=$(echo "$line" | sed 's/^[[:space:]]*-[[:space:]]*//')
82
+
83
+ # Check for satisfied_externally: ~~{topic}: {description}~~ → satisfied externally
84
+ if echo "$line" | grep -q '^\~\~.*\~\~.*satisfied externally'; then
85
+ # Remove ~~ markers
86
+ local inner
87
+ inner=$(echo "$line" | sed 's/^\~\~//' | sed 's/\~\~.*//')
88
+ DEP_TOPIC=$(echo "$inner" | sed 's/:.*//' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
89
+ DEP_DESC=$(echo "$inner" | sed 's/^[^:]*:[[:space:]]*//' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
90
+ DEP_STATE="satisfied_externally"
91
+ return 0
92
+ fi
93
+
94
+ # Check for resolved: {topic}: {description} → {task-id} (with optional "(resolved)")
95
+ if echo "$line" | grep -qE '→|->'; then
96
+ local before_arrow after_arrow
97
+ # Split on → or ->
98
+ before_arrow=$(echo "$line" | sed -E 's/[[:space:]]*(→|->).*//')
99
+ after_arrow=$(echo "$line" | sed -E 's/.*[[:space:]]*(→|->)[[:space:]]*//')
100
+ # Remove "(resolved)" suffix if present
101
+ after_arrow=$(echo "$after_arrow" | sed 's/[[:space:]]*(resolved)[[:space:]]*$//' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
102
+ DEP_TOPIC=$(echo "$before_arrow" | sed 's/:.*//' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
103
+ DEP_DESC=$(echo "$before_arrow" | sed 's/^[^:]*:[[:space:]]*//' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
104
+ DEP_STATE="resolved"
105
+ DEP_TASK_ID="$after_arrow"
106
+ return 0
107
+ fi
108
+
109
+ # Unresolved: {topic}: {description}
110
+ DEP_TOPIC=$(echo "$line" | sed 's/:.*//' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
111
+ DEP_DESC=$(echo "$line" | sed 's/^[^:]*:[[:space:]]*//' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
112
+ DEP_STATE="unresolved"
113
+ return 0
114
+ }
115
+
116
+ # Process each plan file
117
+ for file in "$PLAN_DIR"/*.md; do
118
+ [ -f "$file" ] || continue
119
+
120
+ # Check if already migrated via tracking
121
+ if is_migrated "$file" "$MIGRATION_ID"; then
122
+ report_skip "$file"
123
+ continue
124
+ fi
125
+
126
+ # Check if file has YAML frontmatter
127
+ if ! head -1 "$file" 2>/dev/null | grep -q "^---$"; then
128
+ record_migration "$file" "$MIGRATION_ID"
129
+ report_skip "$file"
130
+ continue
131
+ fi
132
+
133
+ # Check if external_dependencies already exists in frontmatter
134
+ frontmatter=$(extract_frontmatter_005 "$file")
135
+ if echo "$frontmatter" | grep -q "^external_dependencies:"; then
136
+ record_migration "$file" "$MIGRATION_ID"
137
+ report_skip "$file"
138
+ continue
139
+ fi
140
+
141
+ # Extract body and look for External Dependencies section
142
+ body=$(extract_body_005 "$file")
143
+ deps_section=$(extract_ext_deps_section "$body")
144
+
145
+ # Build the new frontmatter field
146
+ new_deps_block=""
147
+ has_deps=false
148
+
149
+ # Check if section exists and has content beyond "No external dependencies."
150
+ if [ -n "$deps_section" ]; then
151
+ # Get only lines that look like list items
152
+ dep_lines=$(echo "$deps_section" | grep -E '^[[:space:]]*-[[:space:]]' || true)
153
+
154
+ if [ -n "$dep_lines" ]; then
155
+ new_deps_block="external_dependencies:"
156
+ while IFS= read -r dep_line; do
157
+ [ -z "$dep_line" ] && continue
158
+ parse_dep_line "$dep_line"
159
+ if [ -n "$DEP_TOPIC" ]; then
160
+ has_deps=true
161
+ new_deps_block="${new_deps_block}
162
+ - topic: $DEP_TOPIC
163
+ description: $DEP_DESC
164
+ state: $DEP_STATE"
165
+ if [ -n "$DEP_TASK_ID" ]; then
166
+ new_deps_block="${new_deps_block}
167
+ task_id: $DEP_TASK_ID"
168
+ fi
169
+ fi
170
+ done <<< "$dep_lines"
171
+ fi
172
+ fi
173
+
174
+ # If no deps found, use empty array
175
+ if ! $has_deps; then
176
+ new_deps_block="external_dependencies: []"
177
+ fi
178
+
179
+ # Remove the External Dependencies body section
180
+ # Only remove the h2 heading and its direct content (list items, "None."/"No external dependencies.")
181
+ # Preserve any subsections (### headings) that may follow within the section
182
+ new_body=$(echo "$body" | awk '
183
+ /^## External Dependencies/ { skip=1; next }
184
+ skip && /^## [^#]/ { skip=0 }
185
+ skip && /^### / { skip=0 }
186
+ skip { next }
187
+ { print }
188
+ ')
189
+
190
+ # Clean up: remove consecutive blank lines left from section removal (keep max 1)
191
+ new_body=$(echo "$new_body" | awk '
192
+ /^$/ { blank++; if (blank <= 1) print; next }
193
+ { blank=0; print }
194
+ ')
195
+
196
+ # Remove existing external_dependencies from frontmatter if somehow partially there
197
+ new_frontmatter=$(echo "$frontmatter" | awk '
198
+ /^external_dependencies:/ { skip=1; next }
199
+ /^[a-z_]+:/ && skip { skip=0 }
200
+ skip == 0 { print }
201
+ ')
202
+
203
+ # Insert external_dependencies before the planning: block (or at end if no planning:)
204
+ if echo "$new_frontmatter" | grep -q "^planning:"; then
205
+ # Split at planning: line, insert deps block before it
206
+ before_planning=$(echo "$new_frontmatter" | sed -n '/^planning:/q;p')
207
+ planning_block=$(echo "$new_frontmatter" | sed -n '/^planning:/,$ p')
208
+ final_frontmatter="${before_planning}
209
+ ${new_deps_block}
210
+ ${planning_block}"
211
+ else
212
+ final_frontmatter="${new_frontmatter}
213
+ ${new_deps_block}"
214
+ fi
215
+
216
+ # Write the updated file
217
+ {
218
+ echo "---"
219
+ echo "$final_frontmatter"
220
+ echo "---"
221
+ echo "$new_body"
222
+ } > "$file"
223
+
224
+ record_migration "$file" "$MIGRATION_ID"
225
+
226
+ if $has_deps; then
227
+ report_update "$file" "migrated external dependencies to frontmatter"
228
+ else
229
+ report_update "$file" "added empty external_dependencies to frontmatter"
230
+ fi
231
+ done
@@ -29,6 +29,21 @@ Either way: Capture decisions, rationale, competing approaches, and edge cases.
29
29
  - **Topic is broad or ambiguous?**
30
30
  > "You mentioned {topic}. To keep the discussion focused, is there a specific aspect or decision you want to work through first?"
31
31
 
32
+ ---
33
+
34
+ ## Resuming After Context Refresh
35
+
36
+ Context refresh (compaction) summarizes the conversation, losing procedural detail. When you detect a context refresh has occurred — the conversation feels abruptly shorter, you lack memory of recent steps, or a summary precedes this message — follow this recovery protocol:
37
+
38
+ 1. **Re-read this skill file completely.** Do not rely on your summary of it. The full process, steps, and rules must be reloaded.
39
+ 2. **Read all tracking and state files** for the current topic — plan index files, review tracking files, implementation tracking files, or any working documents this skill creates. These are your source of truth for progress.
40
+ 3. **Check git state.** Run `git status` and `git log --oneline -10` to see recent commits. Commit messages follow a conventional pattern that reveals what was completed.
41
+ 4. **Announce your position** to the user before continuing: what step you believe you're at, what's been completed, and what comes next. Wait for confirmation.
42
+
43
+ Do not guess at progress or continue from memory. The files on disk and git history are authoritative — your recollection is not.
44
+
45
+ ---
46
+
32
47
  ## What to Capture
33
48
 
34
49
  - **Back-and-forth debates**: Challenging, prolonged discussions show how we decided X over Y
@@ -23,7 +23,6 @@ Either way: Execute via strict TDD - tests first, implementation second.
23
23
  - **Plan format** (required) - How to parse tasks (from plan frontmatter)
24
24
  - **Specification content** (optional) - For context when task rationale is unclear
25
25
  - **Environment setup** (optional) - First-time setup instructions
26
- - **Scope** (optional) - Specific phase/task to work on
27
26
 
28
27
  **Before proceeding**, verify all required inputs are available and unambiguous. If anything is missing or unclear, **STOP** — do not proceed until resolved.
29
28
 
@@ -38,6 +37,21 @@ Either way: Execute via strict TDD - tests first, implementation second.
38
37
 
39
38
  If no specification is available, the plan becomes the sole authority for design decisions.
40
39
 
40
+ ---
41
+
42
+ ## Resuming After Context Refresh
43
+
44
+ Context refresh (compaction) summarizes the conversation, losing procedural detail. When you detect a context refresh has occurred — the conversation feels abruptly shorter, you lack memory of recent steps, or a summary precedes this message — follow this recovery protocol:
45
+
46
+ 1. **Re-read this skill file completely.** Do not rely on your summary of it. The full process, steps, and rules must be reloaded.
47
+ 2. **Read all tracking and state files** for the current topic — plan index files, review tracking files, implementation tracking files, or any working documents this skill creates. These are your source of truth for progress.
48
+ 3. **Check git state.** Run `git status` and `git log --oneline -10` to see recent commits. Commit messages follow a conventional pattern that reveals what was completed.
49
+ 4. **Announce your position** to the user before continuing: what step you believe you're at, what's been completed, and what comes next. Wait for confirmation.
50
+
51
+ Do not guess at progress or continue from memory. The files on disk and git history are authoritative — your recollection is not.
52
+
53
+ ---
54
+
41
55
  ## Hard Rules
42
56
 
43
57
  **MANDATORY. No exceptions. Violating these rules invalidates the work.**
@@ -77,19 +91,90 @@ Complete ALL setup steps before proceeding to implementation work.
77
91
 
78
92
  3. **Read the TDD workflow** - Load **[tdd-workflow.md](references/tdd-workflow.md)** before writing any code. This is mandatory.
79
93
 
80
- 4. **Validate scope** (if specific phase or task was requested)
81
- - If the requested phase or task doesn't exist in the plan, STOP immediately
82
- - Ask the user for clarification - don't assume or proceed with a different scope
83
- - Wait for the user to either correct the scope or ask you to stop
94
+ 4. **Initialize or resume implementation tracking**
95
+ - Check if `docs/workflow/implementation/{topic}.md` exists
96
+ - **If not**: Create it with the initial tracking frontmatter (see [Implementation Tracking](#implementation-tracking) below), set `status: in-progress`, `started: {today}`. Commit: `impl({topic}): start implementation`
97
+ - **If exists**: Read it to determine current position (see [Resuming After Context Refresh](#resuming-after-context-refresh) below)
84
98
 
85
- 5. **For each phase**:
99
+ 5. **For each phase** (working through phases and tasks in plan order):
86
100
  - Announce phase start and review acceptance criteria
87
101
  - For each task: follow the TDD cycle loaded in step 3
102
+ - After each task completes: update progress in **both** the output format (as loaded in step 2) **and** the implementation tracking file (see below)
88
103
  - Verify all phase acceptance criteria met
89
104
  - **Ask user before proceeding to next phase**
90
105
 
91
106
  6. **Reference specification** when rationale unclear
92
107
 
108
+ ## Implementation Tracking
109
+
110
+ Each topic has a tracking file at `docs/workflow/implementation/{topic}.md` that records progress programmatically (frontmatter) and as a human-readable summary (body).
111
+
112
+ ### Initial Tracking File
113
+
114
+ When starting implementation for a topic, create:
115
+
116
+ ```yaml
117
+ ---
118
+ topic: {topic}
119
+ plan: ../planning/{topic}.md
120
+ format: {format from plan}
121
+ status: in-progress
122
+ current_phase: 1
123
+ current_task: ~
124
+ completed_phases: []
125
+ completed_tasks: []
126
+ started: YYYY-MM-DD
127
+ updated: YYYY-MM-DD
128
+ completed: ~
129
+ ---
130
+
131
+ # Implementation: {Topic Name}
132
+
133
+ Implementation started.
134
+ ```
135
+
136
+ ### Updating Progress
137
+
138
+ When a task or phase completes, update **two** things:
139
+
140
+ 1. **Output format progress** — Follow the output adapter's Implementation section (loaded in workflow step 2) to mark tasks/phases complete in the plan index file and any format-specific files. This is the plan's own progress tracking.
141
+
142
+ 2. **Implementation tracking file** — Update `docs/workflow/implementation/{topic}.md` as described below. This enables cross-topic dependency resolution and resume detection.
143
+
144
+ **After each task completes (tracking file):**
145
+ - Append the task ID to `completed_tasks`
146
+ - Update `current_task` to the next task (or `~` if phase done)
147
+ - Update `updated` date
148
+ - Update the body progress section
149
+
150
+ **After each phase completes (tracking file):**
151
+ - Append the phase number to `completed_phases`
152
+ - Update `current_phase` to the next phase (or leave as last)
153
+ - Update the body progress section
154
+
155
+ **On implementation completion (tracking file):**
156
+ - Set `status: completed`
157
+ - Set `completed: {today}`
158
+ - Commit: `impl({topic}): complete implementation`
159
+
160
+ Task IDs in `completed_tasks` use whatever ID format the output format assigns -- the same IDs used in dependency references.
161
+
162
+ ### Body Progress Section
163
+
164
+ The body provides a human-readable summary for context refresh:
165
+
166
+ ```markdown
167
+ # Implementation: {Topic Name}
168
+
169
+ ## Phase 1: Foundation
170
+ All tasks completed.
171
+
172
+ ## Phase 2: Core Logic (current)
173
+ - Task 2.1: Service layer - done
174
+ - Task 2.2: Validation - done
175
+ - Task 2.3: Controllers (next)
176
+ ```
177
+
93
178
  ## Progress Announcements
94
179
 
95
180
  Keep user informed of progress:
@@ -35,6 +35,19 @@ Either way: Transform specifications into actionable phases, tasks, and acceptan
35
35
 
36
36
  ---
37
37
 
38
+ ## Resuming After Context Refresh
39
+
40
+ Context refresh (compaction) summarizes the conversation, losing procedural detail. When you detect a context refresh has occurred — the conversation feels abruptly shorter, you lack memory of recent steps, or a summary precedes this message — follow this recovery protocol:
41
+
42
+ 1. **Re-read this skill file completely.** Do not rely on your summary of it. The full process, steps, and rules must be reloaded.
43
+ 2. **Read all tracking and state files** for the current topic — plan index files, review tracking files, implementation tracking files, or any working documents this skill creates. These are your source of truth for progress.
44
+ 3. **Check git state.** Run `git status` and `git log --oneline -10` to see recent commits. Commit messages follow a conventional pattern that reveals what was completed.
45
+ 4. **Announce your position** to the user before continuing: what step you believe you're at, what's been completed, and what comes next. Wait for confirmation.
46
+
47
+ Do not guess at progress or continue from memory. The files on disk and git history are authoritative — your recollection is not.
48
+
49
+ ---
50
+
38
51
  ## The Process
39
52
 
40
53
  This process constructs a plan from a specification. A plan consists of:
@@ -133,6 +146,7 @@ cross_cutting_specs: # Omit if none
133
146
  spec_commit: {output of git rev-parse HEAD}
134
147
  created: YYYY-MM-DD # Use today's actual date
135
148
  updated: YYYY-MM-DD # Use today's actual date
149
+ external_dependencies: []
136
150
  planning:
137
151
  phase: 1
138
152
  task: ~
@@ -18,22 +18,26 @@ External dependencies are things a feature needs from other topics or systems th
18
18
 
19
19
  ## Format
20
20
 
21
- In Plan Index Files, external dependencies appear in a dedicated section:
22
-
23
- ```markdown
24
- ## External Dependencies
25
-
26
- - billing-system: Invoice generation for order completion
27
- - user-authentication: User context for permissions → {task-id} (resolved)
28
- - ~~payment-gateway: Payment processing~~ → satisfied externally
21
+ In Plan Index Files, external dependencies are stored in the **frontmatter** as a YAML array:
22
+
23
+ ```yaml
24
+ external_dependencies:
25
+ - topic: billing-system
26
+ description: Invoice generation for order completion
27
+ state: unresolved
28
+ - topic: user-authentication
29
+ description: User context for permissions
30
+ state: resolved
31
+ task_id: auth-1-3
32
+ - topic: payment-gateway
33
+ description: Payment processing
34
+ state: satisfied_externally
29
35
  ```
30
36
 
31
- If there are no external dependencies, still include the section:
32
-
33
- ```markdown
34
- ## External Dependencies
37
+ If there are no external dependencies, use an empty array:
35
38
 
36
- No external dependencies.
39
+ ```yaml
40
+ external_dependencies: []
37
41
  ```
38
42
 
39
43
  This makes it explicit for downstream stages that dependencies were considered and none exist.
@@ -42,16 +46,16 @@ This makes it explicit for downstream stages that dependencies were considered a
42
46
 
43
47
  | State | Format | Meaning |
44
48
  |-------|--------|---------|
45
- | Unresolved | `- {topic}: {description}` | Dependency exists but not yet linked to a task |
46
- | Resolved | `- {topic}: {description} {task-id}` | Linked to specific task in another plan |
47
- | Satisfied externally | `- ~~{topic}: {description}~~ → satisfied externally` | Implemented outside workflow |
49
+ | `unresolved` | `state: unresolved` | Dependency exists but not yet linked to a task |
50
+ | `resolved` | `state: resolved` + `task_id: {id}` | Linked to specific task in another plan |
51
+ | `satisfied_externally` | `state: satisfied_externally` | Implemented outside workflow |
48
52
 
49
53
  ## Lifecycle
50
54
 
51
55
  ```
52
56
  SPECIFICATION PLANNING
53
57
  ───────────────────────────────────────────────────────────────────
54
- Dependencies section → Copied to Plan Index File as unresolved
58
+ Dependencies section → Added to plan frontmatter as unresolved
55
59
  (natural language) ↓
56
60
  Resolved when linked to specific task ID
57
61
  (via planning or /link-dependencies)
@@ -59,11 +63,11 @@ Dependencies section → Copied to Plan Index File as unresolved
59
63
 
60
64
  ## Resolution
61
65
 
62
- Dependencies move from unresolved → resolved when:
66
+ Dependencies move from `unresolved``resolved` when:
63
67
  - The dependency topic is planned and you identify the specific task
64
68
  - The `/link-dependencies` command finds and wires the match
65
69
 
66
- Dependencies become "satisfied externally" when:
70
+ Dependencies become `satisfied_externally` when:
67
71
  - The user confirms it was implemented outside the workflow
68
72
  - It already exists in the codebase
69
73
  - It's a third-party system that's already available
@@ -10,29 +10,29 @@ Orient the user:
10
10
 
11
11
  After all phases are detailed and written, handle external dependencies — things this plan needs from other topics or systems.
12
12
 
13
+ Dependencies are stored in the plan's **frontmatter** as `external_dependencies`. See [dependencies.md](../dependencies.md) for the format and states.
14
+
13
15
  #### If the specification has a Dependencies section
14
16
 
15
17
  The specification's Dependencies section lists what this feature needs from outside its own scope. These must be documented in the plan so implementation knows what is blocked and what is available.
16
18
 
17
- 1. **Document each dependency** in the plan's External Dependencies section using the format described in [dependencies.md](../dependencies.md). Initially, record each as unresolved.
19
+ 1. **Document each dependency** in the plan's `external_dependencies` frontmatter field using the format described in [dependencies.md](../dependencies.md). Initially, record each as `state: unresolved`.
18
20
 
19
21
  2. **Resolve where possible** — For each dependency, check whether a plan already exists for that topic:
20
- - If a plan exists, identify the specific task(s) that satisfy the dependency. Query the output format to find relevant tasks. If ambiguous, ask the user which tasks apply. Update the dependency entry from unresolved → resolved with the task reference.
21
- - If no plan exists, leave the dependency as unresolved. It will be linked later via `/link-dependencies` or when that topic is planned.
22
+ - If a plan exists, identify the specific task(s) that satisfy the dependency. Query the output format to find relevant tasks. If ambiguous, ask the user which tasks apply. Update the dependency entry from `state: unresolved``state: resolved` with the `task_id`.
23
+ - If no plan exists, leave the dependency as `state: unresolved`. It will be linked later via `/link-dependencies` or when that topic is planned.
22
24
 
23
- 3. **Reverse check** — Check whether any existing plans have unresolved dependencies that reference *this* topic. Now that this plan exists with specific tasks:
24
- - Scan other plan files for External Dependencies entries that mention this topic
25
+ 3. **Reverse check** — Check whether any existing plans have unresolved dependencies in their `external_dependencies` frontmatter that reference *this* topic. Now that this plan exists with specific tasks:
26
+ - Scan other plan files' `external_dependencies` for entries that mention this topic
25
27
  - For each match, identify which task(s) in the current plan satisfy that dependency
26
- - Update the other plan's dependency entry with the task reference (unresolved resolved)
28
+ - Update the other plan's `external_dependencies` entry with the task reference (`state: resolved`, `task_id`)
27
29
 
28
30
  #### If the specification has no Dependencies section
29
31
 
30
- Document this explicitly in the plan:
31
-
32
- ```markdown
33
- ## External Dependencies
32
+ Set the frontmatter field to an empty array:
34
33
 
35
- No external dependencies.
34
+ ```yaml
35
+ external_dependencies: []
36
36
  ```
37
37
 
38
38
  This makes it clear that dependencies were considered and none exist — not that they were overlooked.
@@ -28,6 +28,21 @@ Either way: Explore feasibility (technical, business, market), validate assumpti
28
28
  - **Topic is vague or could go many directions?**
29
29
  > "You mentioned {topic}. That could cover a lot of ground — is there a specific angle you'd like to start with, or should I explore broadly?"
30
30
 
31
+ ---
32
+
33
+ ## Resuming After Context Refresh
34
+
35
+ Context refresh (compaction) summarizes the conversation, losing procedural detail. When you detect a context refresh has occurred — the conversation feels abruptly shorter, you lack memory of recent steps, or a summary precedes this message — follow this recovery protocol:
36
+
37
+ 1. **Re-read this skill file completely.** Do not rely on your summary of it. The full process, steps, and rules must be reloaded.
38
+ 2. **Read all tracking and state files** for the current topic — plan index files, review tracking files, implementation tracking files, or any working documents this skill creates. These are your source of truth for progress.
39
+ 3. **Check git state.** Run `git status` and `git log --oneline -10` to see recent commits. Commit messages follow a conventional pattern that reveals what was completed.
40
+ 4. **Announce your position** to the user before continuing: what step you believe you're at, what's been completed, and what comes next. Wait for confirmation.
41
+
42
+ Do not guess at progress or continue from memory. The files on disk and git history are authoritative — your recollection is not.
43
+
44
+ ---
45
+
31
46
  ## Your Expertise
32
47
 
33
48
  You bring knowledge across the full landscape:
@@ -41,6 +41,21 @@ Either way: Verify every plan task was implemented, tested adequately, and meets
41
41
 
42
42
  The specification is optional — the review can proceed with just the plan.
43
43
 
44
+ ---
45
+
46
+ ## Resuming After Context Refresh
47
+
48
+ Context refresh (compaction) summarizes the conversation, losing procedural detail. When you detect a context refresh has occurred — the conversation feels abruptly shorter, you lack memory of recent steps, or a summary precedes this message — follow this recovery protocol:
49
+
50
+ 1. **Re-read this skill file completely.** Do not rely on your summary of it. The full process, steps, and rules must be reloaded.
51
+ 2. **Read all tracking and state files** for the current topic — plan index files, review tracking files, implementation tracking files, or any working documents this skill creates. These are your source of truth for progress.
52
+ 3. **Check git state.** Run `git status` and `git log --oneline -10` to see recent commits. Commit messages follow a conventional pattern that reveals what was completed.
53
+ 4. **Announce your position** to the user before continuing: what step you believe you're at, what's been completed, and what comes next. Wait for confirmation.
54
+
55
+ Do not guess at progress or continue from memory. The files on disk and git history are authoritative — your recollection is not.
56
+
57
+ ---
58
+
44
59
  ## Review Approach
45
60
 
46
61
  Start from the **plan** - it contains the granular tasks and acceptance criteria.
@@ -39,6 +39,21 @@ Either way: Transform unvalidated reference material into a specification that's
39
39
 
40
40
  **Multiple sources:** When multiple sources are provided, extract exhaustively from ALL of them. Content may be scattered across sources - a decision in one may have constraints or details in another. The specification consolidates everything into a single standalone document.
41
41
 
42
+ ---
43
+
44
+ ## Resuming After Context Refresh
45
+
46
+ Context refresh (compaction) summarizes the conversation, losing procedural detail. When you detect a context refresh has occurred — the conversation feels abruptly shorter, you lack memory of recent steps, or a summary precedes this message — follow this recovery protocol:
47
+
48
+ 1. **Re-read this skill file completely.** Do not rely on your summary of it. The full process, steps, and rules must be reloaded.
49
+ 2. **Read all tracking and state files** for the current topic — plan index files, review tracking files, implementation tracking files, or any working documents this skill creates. These are your source of truth for progress.
50
+ 3. **Check git state.** Run `git status` and `git log --oneline -10` to see recent commits. Commit messages follow a conventional pattern that reveals what was completed.
51
+ 4. **Announce your position** to the user before continuing: what step you believe you're at, what's been completed, and what comes next. Wait for confirmation.
52
+
53
+ Do not guess at progress or continue from memory. The files on disk and git history are authoritative — your recollection is not.
54
+
55
+ ---
56
+
42
57
  ## The Process
43
58
 
44
59
  **Load**: [specification-guide.md](references/specification-guide.md)
@@ -295,12 +295,6 @@ Ask: **"Is there a standalone thing to build, or does this inform how we build o
295
295
 
296
296
  **Trust nothing without validation**: Synthesize and present, but never assume source material is correct.
297
297
 
298
- ## After Context Refresh
299
-
300
- Read the specification. It contains validated, approved content. Trust it - you built it together with the user.
301
-
302
- If working notes exist, they show where you left off.
303
-
304
298
  ## Dependencies Section
305
299
 
306
300
  At the end of every specification, add a **Dependencies** section that identifies **prerequisites** - systems that must exist before this feature can be built.