@leeovery/claude-technical-workflows 2.1.25 → 2.1.27

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.
package/README.md CHANGED
@@ -291,7 +291,7 @@ Helpers for navigating and maintaining the workflow.
291
291
  | Skill | Description |
292
292
  |------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
293
293
  | [**/migrate**](skills/migrate/) | Keep workflow files in sync with the current system design. Runs automatically at the start of every workflow skill. |
294
- | [**/status**](skills/status/) | Show workflow status - what topics exist at each phase, and suggested next steps. |
294
+ | [**/status**](skills/status/) | Show workflow status with relationship-aware display specification sources, unlinked discussions, plan dependencies, and suggested next steps. |
295
295
  | [**/view-plan**](skills/view-plan/) | View a plan's tasks and progress, regardless of output format. |
296
296
 
297
297
  #### Standalone Skills
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leeovery/claude-technical-workflows",
3
- "version": "2.1.25",
3
+ "version": "2.1.27",
4
4
  "description": "Technical workflow skills & commands for Claude Code",
5
5
  "license": "MIT",
6
6
  "author": "Lee Overy <me@leeovery.com>",
@@ -126,113 +126,9 @@ At least one specification is ready for planning, or an existing plan can be con
126
126
 
127
127
  ## Step 3: Present Workflow State and Options
128
128
 
129
- Present everything discovered to help the user make an informed choice.
129
+ Load **[display-state.md](references/display-state.md)** and follow its instructions as written.
130
130
 
131
- **Present the full state:**
132
-
133
- > *Output the next fenced block as a code block:*
134
-
135
- ```
136
- Planning Overview
137
-
138
- {N} specifications found. {M} plans exist.
139
-
140
- 1. {topic:(titlecase)}
141
- └─ Plan: @if(has_plan) {plan_status:[in-progress|concluded]} @else (no plan) @endif
142
- └─ Spec: concluded
143
-
144
- 2. ...
145
- ```
146
-
147
- **Tree rules:**
148
-
149
- Each numbered item shows a feature specification that is actionable:
150
- - Concluded spec with no plan → `Plan: (no plan)`
151
- - Has a plan with `plan_status: planning` → `Plan: in-progress`
152
- - Has a plan with `plan_status: concluded` → `Plan: concluded`
153
-
154
- **If non-plannable specifications exist**, show them in a separate code block:
155
-
156
- > *Output the next fenced block as a code block:*
157
-
158
- ```
159
- Specifications not ready for planning:
160
- These specifications are either still in progress or cross-cutting
161
- and cannot be planned directly.
162
-
163
- • {topic} ({type:[feature|cross-cutting]}, {status:[in-progress|concluded]})
164
- ```
165
-
166
- **Key/Legend** — show only statuses that appear in the current display. No `---` separator before this section.
167
-
168
- > *Output the next fenced block as a code block:*
169
-
170
- ```
171
- Key:
172
-
173
- Plan status:
174
- in-progress — planning work is ongoing
175
- concluded — plan is complete
176
-
177
- Spec type:
178
- cross-cutting — architectural policy, not directly plannable
179
- feature — plannable feature specification
180
- ```
181
-
182
- Omit any section entirely if it has no entries.
183
-
184
- **Then prompt based on what's actionable:**
185
-
186
- **If multiple actionable items:**
187
-
188
- The verb in the menu depends on the plan state:
189
- - No plan exists → **Create**
190
- - Plan is `in-progress` → **Continue**
191
- - Plan is `concluded` → **Review**
192
-
193
- > *Output the next fenced block as markdown (not a code block):*
194
-
195
- ```
196
- · · · · · · · · · · · ·
197
- 1. Create "Auth Flow" — concluded spec, no plan
198
- 2. Continue "Data Model" — plan in-progress
199
- 3. Review "Billing" — plan concluded
200
-
201
- Select an option (enter number):
202
- · · · · · · · · · · · ·
203
- ```
204
-
205
- Recreate with actual topics and states from discovery.
206
-
207
- **STOP.** Wait for user response.
208
-
209
- **If single actionable item (auto-select):**
210
-
211
- > *Output the next fenced block as a code block:*
212
-
213
- ```
214
- Automatically proceeding with "{topic:(titlecase)}".
215
- ```
216
-
217
- → Proceed directly to **Step 4**.
218
-
219
- **If nothing actionable:**
220
-
221
- > *Output the next fenced block as a code block:*
222
-
223
- ```
224
- Planning Overview
225
-
226
- No plannable specifications found.
227
-
228
- The planning phase requires a concluded feature specification.
229
- Complete any in-progress specifications with /start-specification,
230
- or create a new specification first.
231
- ```
232
-
233
- **STOP.** Do not proceed — terminal condition.
234
-
235
- → Based on user choice, proceed to **Step 4**.
131
+ Proceed to **Step 4**.
236
132
 
237
133
  ---
238
134
 
@@ -273,46 +169,7 @@ Any additional context since the specification was concluded?
273
169
 
274
170
  ## Step 6: Surface Cross-Cutting Context
275
171
 
276
- **If no cross-cutting specifications exist**: Skip this step. → Proceed to **Step 7**.
277
-
278
- Read each cross-cutting specification from `specifications.crosscutting` in the discovery output.
279
-
280
- ### 6a: Warn about in-progress cross-cutting specs
281
-
282
- If any **in-progress** cross-cutting specifications exist, check whether they could be relevant to the feature being planned (by topic overlap — e.g., a caching strategy is relevant if the feature involves data retrieval or API calls).
283
-
284
- If any are relevant:
285
-
286
- > *Output the next fenced block as markdown (not a code block):*
287
-
288
- ```
289
- Cross-cutting specifications still in progress:
290
- These may contain architectural decisions relevant to this plan.
291
-
292
- • {topic}
293
-
294
- · · · · · · · · · · · ·
295
- - **`c`/`continue`** — Plan without them
296
- - **`s`/`stop`** — Complete them first (/start-specification)
297
- · · · · · · · · · · · ·
298
- ```
299
-
300
- **STOP.** Wait for user response.
301
-
302
- If the user chooses to stop, end here. If they choose to continue, proceed.
303
-
304
- ### 6b: Summarize concluded cross-cutting specs
305
-
306
- If any **concluded** cross-cutting specifications exist, identify which are relevant to the feature being planned and summarize for handoff:
307
-
308
- > *Output the next fenced block as a code block:*
309
-
310
- ```
311
- Cross-cutting specifications to reference:
312
- - caching-strategy.md: [brief summary of key decisions]
313
- ```
314
-
315
- These specifications contain validated architectural decisions that should inform the plan. The planning skill will incorporate these as a "Cross-Cutting References" section in the plan.
172
+ Load **[cross-cutting-context.md](references/cross-cutting-context.md)** and follow its instructions as written.
316
173
 
317
174
  → Proceed to **Step 7**.
318
175
 
@@ -320,33 +177,4 @@ These specifications contain validated architectural decisions that should infor
320
177
 
321
178
  ## Step 7: Invoke the Skill
322
179
 
323
- After completing the steps above, this skill's purpose is fulfilled.
324
-
325
- Invoke the [technical-planning](../technical-planning/SKILL.md) skill for your next instructions. Do not act on the gathered information until the skill is loaded - it contains the instructions for how to proceed.
326
-
327
- **Example handoff (fresh plan):**
328
- ```
329
- Planning session for: {topic}
330
- Specification: docs/workflow/specification/{topic}.md
331
- Additional context: {summary of user's answers from Step 5}
332
- Cross-cutting references: {list of applicable cross-cutting specs with brief summaries, or "none"}
333
- Recommended output format: {common_format from discovery if non-empty, otherwise "none"}
334
-
335
- Invoke the technical-planning skill.
336
- ```
337
-
338
- **Example handoff (continue/review existing plan):**
339
- ```
340
- Planning session for: {topic}
341
- Specification: docs/workflow/specification/{topic}.md
342
- Existing plan: docs/workflow/planning/{topic}.md
343
-
344
- Invoke the technical-planning skill.
345
- ```
346
-
347
- ## Notes
348
-
349
- - Ask questions clearly and wait for responses before proceeding
350
- - The feature specification is the primary source of truth for planning
351
- - Cross-cutting specifications provide supplementary context for architectural decisions
352
- - Do not reference discussions - only specifications
180
+ Load **[invoke-skill.md](references/invoke-skill.md)** and follow its instructions as written.
@@ -0,0 +1,50 @@
1
+ # Cross-Cutting Context
2
+
3
+ *Reference for **[start-planning](../SKILL.md)***
4
+
5
+ ---
6
+
7
+ **If no cross-cutting specifications exist**:
8
+
9
+ Skip this step.
10
+
11
+ → Proceed to **Step 7**.
12
+
13
+ Read each cross-cutting specification from `specifications.crosscutting` in the discovery output.
14
+
15
+ ### 6a: Warn about in-progress cross-cutting specs
16
+
17
+ If any **in-progress** cross-cutting specifications exist, check whether they could be relevant to the feature being planned (by topic overlap — e.g., a caching strategy is relevant if the feature involves data retrieval or API calls).
18
+
19
+ If any are relevant:
20
+
21
+ > *Output the next fenced block as markdown (not a code block):*
22
+
23
+ ```
24
+ Cross-cutting specifications still in progress:
25
+ These may contain architectural decisions relevant to this plan.
26
+
27
+ • {topic}
28
+
29
+ · · · · · · · · · · · ·
30
+ - **`c`/`continue`** — Plan without them
31
+ - **`s`/`stop`** — Complete them first (/start-specification)
32
+ · · · · · · · · · · · ·
33
+ ```
34
+
35
+ **STOP.** Wait for user response.
36
+
37
+ If the user chooses to stop, end here. If they choose to continue, proceed.
38
+
39
+ ### 6b: Summarize concluded cross-cutting specs
40
+
41
+ If any **concluded** cross-cutting specifications exist, identify which are relevant to the feature being planned and summarize for handoff:
42
+
43
+ > *Output the next fenced block as a code block:*
44
+
45
+ ```
46
+ Cross-cutting specifications to reference:
47
+ - caching-strategy.md: [brief summary of key decisions]
48
+ ```
49
+
50
+ These specifications contain validated architectural decisions that should inform the plan. The planning skill will incorporate these as a "Cross-Cutting References" section in the plan.
@@ -0,0 +1,109 @@
1
+ # Display State and Options
2
+
3
+ *Reference for **[start-planning](../SKILL.md)***
4
+
5
+ ---
6
+
7
+ Present everything discovered to help the user make an informed choice.
8
+
9
+ **Present the full state:**
10
+
11
+ > *Output the next fenced block as a code block:*
12
+
13
+ ```
14
+ Planning Overview
15
+
16
+ {N} specifications found. {M} plans exist.
17
+
18
+ 1. {topic:(titlecase)}
19
+ └─ Plan: @if(has_plan) {plan_status:[in-progress|concluded]} @else (no plan) @endif
20
+ └─ Spec: concluded
21
+
22
+ 2. ...
23
+ ```
24
+
25
+ **Tree rules:**
26
+
27
+ Each numbered item shows a feature specification that is actionable:
28
+ - Concluded spec with no plan → `Plan: (no plan)`
29
+ - Has a plan with `plan_status: planning` → `Plan: in-progress`
30
+ - Has a plan with `plan_status: concluded` → `Plan: concluded`
31
+
32
+ **If non-plannable specifications exist**, show them in a separate code block:
33
+
34
+ > *Output the next fenced block as a code block:*
35
+
36
+ ```
37
+ Specifications not ready for planning:
38
+ These specifications are either still in progress or cross-cutting
39
+ and cannot be planned directly.
40
+
41
+ • {topic} ({type:[feature|cross-cutting]}, {status:[in-progress|concluded]})
42
+ ```
43
+
44
+ **Key/Legend** — show only statuses that appear in the current display. No `---` separator before this section.
45
+
46
+ > *Output the next fenced block as a code block:*
47
+
48
+ ```
49
+ Key:
50
+
51
+ Plan status:
52
+ in-progress — planning work is ongoing
53
+ concluded — plan is complete
54
+
55
+ Spec type:
56
+ cross-cutting — architectural policy, not directly plannable
57
+ feature — plannable feature specification
58
+ ```
59
+
60
+ Omit any section entirely if it has no entries.
61
+
62
+ **Then prompt based on what's actionable:**
63
+
64
+ **If multiple actionable items:**
65
+
66
+ The verb in the menu depends on the plan state:
67
+ - No plan exists → **Create**
68
+ - Plan is `in-progress` → **Continue**
69
+ - Plan is `concluded` → **Review**
70
+
71
+ > *Output the next fenced block as markdown (not a code block):*
72
+
73
+ ```
74
+ · · · · · · · · · · · ·
75
+ 1. Create "Auth Flow" — concluded spec, no plan
76
+ 2. Continue "Data Model" — plan in-progress
77
+ 3. Review "Billing" — plan concluded
78
+
79
+ Select an option (enter number):
80
+ · · · · · · · · · · · ·
81
+ ```
82
+
83
+ Recreate with actual topics and states from discovery.
84
+
85
+ **STOP.** Wait for user response.
86
+
87
+ **If single actionable item (auto-select):**
88
+
89
+ > *Output the next fenced block as a code block:*
90
+
91
+ ```
92
+ Automatically proceeding with "{topic:(titlecase)}".
93
+ ```
94
+
95
+ **If nothing actionable:**
96
+
97
+ > *Output the next fenced block as a code block:*
98
+
99
+ ```
100
+ Planning Overview
101
+
102
+ No plannable specifications found.
103
+
104
+ The planning phase requires a concluded feature specification.
105
+ Complete any in-progress specifications with /start-specification,
106
+ or create a new specification first.
107
+ ```
108
+
109
+ **STOP.** Do not proceed — terminal condition.
@@ -0,0 +1,29 @@
1
+ # Invoke the Skill
2
+
3
+ *Reference for **[start-planning](../SKILL.md)***
4
+
5
+ ---
6
+
7
+ After completing the steps above, this skill's purpose is fulfilled.
8
+
9
+ Invoke the [technical-planning](../../technical-planning/SKILL.md) skill for your next instructions. Do not act on the gathered information until the skill is loaded - it contains the instructions for how to proceed.
10
+
11
+ **Example handoff (fresh plan):**
12
+ ```
13
+ Planning session for: {topic}
14
+ Specification: docs/workflow/specification/{topic}.md
15
+ Additional context: {summary of user's answers from Step 5}
16
+ Cross-cutting references: {list of applicable cross-cutting specs with brief summaries, or "none"}
17
+ Recommended output format: {common_format from discovery if non-empty, otherwise "none"}
18
+
19
+ Invoke the technical-planning skill.
20
+ ```
21
+
22
+ **Example handoff (continue/review existing plan):**
23
+ ```
24
+ Planning session for: {topic}
25
+ Specification: docs/workflow/specification/{topic}.md
26
+ Existing plan: docs/workflow/planning/{topic}.md
27
+
28
+ Invoke the technical-planning skill.
29
+ ```
@@ -2,6 +2,7 @@
2
2
  name: status
3
3
  description: "Show workflow status - what exists, where you are, and what to do next."
4
4
  disable-model-invocation: true
5
+ allowed-tools: Bash(.claude/skills/status/scripts/discovery.sh)
5
6
  ---
6
7
 
7
8
  Show the current state of the workflow for this project.
@@ -12,81 +13,194 @@ Show the current state of the workflow for this project.
12
13
 
13
14
  Invoke the `/migrate` skill and assess its output.
14
15
 
15
- **If files were updated**: STOP and wait for the user to review the changes (e.g., via `git diff`) and confirm before proceeding to Step 1. Do not continue automatically.
16
+ **If files were updated**: STOP and wait for the user to review the changes (e.g., via `git diff`) and confirm before proceeding to Step 1.
16
17
 
17
18
  **If no updates needed**: Proceed to Step 1.
18
19
 
19
20
  ---
20
21
 
21
- ## Step 1: Scan Directories
22
+ ## Step 1: Discovery State
22
23
 
23
- Check for files in each workflow directory:
24
+ !`.claude/skills/status/scripts/discovery.sh`
24
25
 
26
+ If the above shows a script invocation rather than YAML output, the dynamic content preprocessor did not run. Execute the script before continuing:
27
+
28
+ ```bash
29
+ .claude/skills/status/scripts/discovery.sh
25
30
  ```
26
- docs/workflow/research/
27
- docs/workflow/discussion/
28
- docs/workflow/specification/
29
- docs/workflow/planning/
30
- docs/workflow/implementation/
31
- ```
32
31
 
33
- For implementation, check `docs/workflow/implementation/{topic}/tracking.md` files and extract frontmatter fields: `status`, `current_phase`, `current_task`, `completed_tasks`, `completed_phases`.
32
+ If YAML content is already displayed, it has been run on your behalf.
33
+
34
+ Parse the discovery output. **IMPORTANT**: Use ONLY this script for discovery. Do NOT run additional bash commands (ls, head, cat, etc.) to gather state.
35
+
36
+ → Proceed to **Step 2**.
37
+
38
+ ---
34
39
 
35
40
  ## Step 2: Present Status
36
41
 
37
- Research is project-wide exploration. From discussion onwards, work is organised by **topic** - different topics may be at different stages.
42
+ Build the display from discovery data. Only show sections for phases that have content.
43
+
44
+ **CRITICAL**: Entities don't flow one-to-one across phases. Multiple discussions may combine into one specification, topic names may change between phases, and specs may be superseded. The display must make these relationships visible — primarily through the specification's `sources` array.
38
45
 
39
- > *Output the next fenced block as markdown (not a code block):*
46
+ ### 2a: Summary
47
+
48
+ > *Output the next fenced block as a code block:*
40
49
 
41
50
  ```
42
- **Workflow Overview**
51
+ Workflow Status
43
52
 
44
- **Research:** {count} files ({filenames})
53
+ Research: {count} file(s)
54
+ Discussion: {count} ({concluded} concluded, {in_progress} in-progress)
55
+ Specification: {active} active ({feature} feature, {crosscutting} cross-cutting)
56
+ Planning: {count} ({concluded} concluded, {in_progress} in-progress)
57
+ Implementation: {count} ({completed} completed, {in_progress} in-progress)
58
+ ```
59
+
60
+ Only show lines for phases that have content. If a phase has zero items but a later phase has content, show the line as `(none)` to highlight the gap.
61
+
62
+ #### If no workflow content exists at all
63
+
64
+ > *Output the next fenced block as a code block:*
45
65
 
46
- | Topic | Discussion | Spec | Plan | Implemented |
47
- |-------|------------|------|------|-------------|
48
- | {topic} | {discussion_status} | {spec_status} | {plan_status} | {impl_status} |
49
- | ... | | | | |
50
66
  ```
67
+ Workflow Status
51
68
 
52
- Adapt based on what exists:
53
- - If a directory is empty or missing, show `-`
54
- - For planning, note the output format if specified in frontmatter
55
- - Match topics across phases by filename
56
- - For implementation, derive the Implemented column from tracking file data:
57
- - No tracking file → `-`
58
- - `status: not-started` → `not started`
59
- - `status: in-progress` → `phase {current_phase} ({n}/{total} tasks done)` — count `completed_tasks` for n; use total task count from `completed_tasks` + remaining if available, otherwise just show completed count
60
- - `status: completed` → `completed`
69
+ No workflow files found in docs/workflow/
61
70
 
62
- ## Step 3: Suggest Next Steps
71
+ Start with /start-research to explore ideas,
72
+ or /start-discussion if you already know what to build.
73
+ ```
74
+
75
+ **STOP.** Do not proceed — terminal condition.
63
76
 
64
- Based on what exists, offer relevant options. Don't assume linear progression - topics may have dependencies on each other.
77
+ ### 2b: Specifications
65
78
 
66
- **If nothing exists:**
67
- - "Start with `/start-research` to explore ideas, or `/start-discussion` if you already know what you're building."
79
+ Show if any specifications exist. This is the most important section — it reveals many-to-one relationships between discussions and specifications.
68
80
 
69
- **If topics exist at various stages**, summarise options without being prescriptive:
70
- - Topics in discussion can move to specification
71
- - Topics with specs can move to planning
72
- - Topics with plans can move to implementation
73
- - Completed implementations can be reviewed
81
+ > *Output the next fenced block as a code block:*
82
+
83
+ ```
84
+ Specifications
74
85
 
75
- Example: "auth-system has a plan ready. payment-flow needs a spec before planning. You might want to complete planning for related topics before implementing if there are dependencies."
86
+ 1. {name:(titlecase)} ({status})
87
+ └─ Sources: @if(no_sources) (none) @else
88
+ ├─ {src} ({src_status})
89
+ └─ ...
90
+ @endif
91
+
92
+ 2. ...
93
+ ```
76
94
 
77
- Keep suggestions brief - the user knows their project's dependencies better than we do.
95
+ **Rules:**
96
+
97
+ - Each numbered item is an active (non-superseded) specification
98
+ - Show `(cross-cutting)` after status for cross-cutting specs; omit type label for feature specs
99
+ - Blank line between numbered items
100
+ - If superseded specs exist, show after the numbered list:
101
+
102
+ ```
103
+ Superseded:
104
+ • {name} → {superseded_by}
105
+ ```
78
106
 
79
- ## Step 4: Mention Plan Viewing
107
+ ### 2c: Plans
80
108
 
81
- If planning files exist, let the user know they can view plan details:
109
+ Show if any plans exist.
82
110
 
83
111
  > *Output the next fenced block as a code block:*
84
112
 
85
113
  ```
86
- To view a plan's tasks and progress, use /view-plan
114
+ Plans
115
+
116
+ 1. {name:(titlecase)} ({status})
117
+ └─ Spec: {specification_name}
118
+ @if(has_unresolved_deps) └─ Blocked:
119
+ ├─ {dep_topic}:{dep_task_id} ({dep_state})
120
+ └─ ...
121
+ @endif
122
+
123
+ 2. ...
87
124
  ```
88
125
 
126
+ **Rules:**
127
+
128
+ - Map raw `planning` status to `in-progress` in the display
129
+ - Show spec name without `.md` extension
130
+
131
+ ### 2d: Implementation
132
+
133
+ Show if any implementations exist.
134
+
135
+ > *Output the next fenced block as a code block:*
136
+
137
+ ```
138
+ Implementation
139
+
140
+ 1. {topic:(titlecase)} ({status})
141
+ └─ Phase {current_phase}, {completed_tasks}/{total_tasks} tasks done
142
+
143
+ 2. ...
144
+ ```
145
+
146
+ **Rules:**
147
+
148
+ - `not-started` → `└─ Not started`
149
+ - `in-progress` → phase and task progress; if `total_tasks` is 0, show `{completed_tasks} tasks done` without denominator
150
+ - `completed` → `└─ Complete`
151
+
152
+ ### 2e: Unlinked Discussions
153
+
154
+ Derive which discussions are NOT referenced in any active (non-superseded) specification's `sources` array. Show only if unlinked discussions exist.
155
+
156
+ > *Output the next fenced block as a code block:*
157
+
158
+ ```
159
+ Discussions not yet in a specification:
160
+
161
+ • {name} ({status})
162
+ ```
163
+
164
+ ### 2f: Key
165
+
166
+ Show if the display uses statuses that benefit from explanation. Only include statuses actually shown. No `---` separator before this section.
167
+
168
+ > *Output the next fenced block as a code block:*
169
+
170
+ ```
171
+ Key:
172
+
173
+ Status:
174
+ in-progress — work is ongoing
175
+ concluded — complete, ready for next step
176
+ superseded — replaced by another specification
177
+
178
+ Spec type:
179
+ cross-cutting — architectural policy, not directly plannable
180
+ ```
181
+
182
+ Omit categories with no entries.
183
+
184
+ ---
185
+
186
+ ## Step 3: Suggest Next Steps
187
+
188
+ Based on gaps in the workflow, briefly suggest 2-3 most relevant actions:
189
+
190
+ - Concluded discussions not in any spec → `/start-specification`
191
+ - In-progress specs → finish with `/start-specification`
192
+ - Concluded feature specs without plans → `/start-planning`
193
+ - Concluded plans not yet implemented → `/start-implementation`
194
+ - Completed implementations → `/start-review`
195
+
196
+ If plans exist, mention `/view-plan` for detailed plan viewing.
197
+
198
+ Keep suggestions brief — the user knows their project better than we do.
199
+
89
200
  ## Notes
90
201
 
91
- - Keep output concise - this is a quick status check
92
- - Use tables for scannable information
202
+ - Keep output scannable this is a status check, not a deep analysis
203
+ - Discussions may appear in multiple specifications' sources
204
+ - A discussion not appearing in any active spec's sources is "unlinked"
205
+ - Research files are project-wide, not topic-specific
206
+ - Topic names may differ across phases (e.g., discussions "auth-flow" and "session-mgmt" may combine into specification "auth-system")
@@ -0,0 +1,420 @@
1
+ #!/bin/bash
2
+ #
3
+ # Discovers the full workflow state across all phases
4
+ # for the /status command.
5
+ #
6
+ # Outputs structured YAML that the command can consume directly.
7
+ #
8
+
9
+ set -eo pipefail
10
+
11
+ RESEARCH_DIR="docs/workflow/research"
12
+ DISCUSSION_DIR="docs/workflow/discussion"
13
+ SPEC_DIR="docs/workflow/specification"
14
+ PLAN_DIR="docs/workflow/planning"
15
+ IMPL_DIR="docs/workflow/implementation"
16
+
17
+ # Helper: Extract a frontmatter field value from a file
18
+ # Usage: extract_field <file> <field_name>
19
+ extract_field() {
20
+ local file="$1"
21
+ local field="$2"
22
+ local value=""
23
+
24
+ if head -1 "$file" 2>/dev/null | grep -q "^---$"; then
25
+ value=$(sed -n '2,/^---$/p' "$file" 2>/dev/null | \
26
+ grep -i -m1 "^${field}:" | \
27
+ sed -E "s/^${field}:[[:space:]]*//i" || true)
28
+ fi
29
+
30
+ echo "$value"
31
+ }
32
+
33
+ # Helper: Extract frontmatter content (between first pair of --- delimiters)
34
+ extract_frontmatter() {
35
+ local file="$1"
36
+ awk 'BEGIN{c=0} /^---$/{c++; if(c==2) exit; next} c==1{print}' "$file" 2>/dev/null
37
+ }
38
+
39
+ # Helper: Extract sources from specification frontmatter
40
+ # Outputs: name|status per line (object format only; legacy converted by migration 004)
41
+ extract_sources() {
42
+ local file="$1"
43
+ local in_sources=false
44
+ local current_name=""
45
+ local current_status=""
46
+
47
+ while IFS= read -r line; do
48
+ if [[ "$line" =~ ^sources: ]]; then
49
+ in_sources=true
50
+ continue
51
+ fi
52
+
53
+ if $in_sources && [[ "$line" =~ ^[a-z_]+: ]] && [[ ! "$line" =~ ^[[:space:]] ]]; then
54
+ if [ -n "$current_name" ]; then
55
+ echo "${current_name}|${current_status:-incorporated}"
56
+ fi
57
+ break
58
+ fi
59
+
60
+ if $in_sources; then
61
+ if [[ "$line" =~ ^[[:space:]]*-[[:space:]]*name:[[:space:]]*(.+)$ ]]; then
62
+ if [ -n "$current_name" ]; then
63
+ echo "${current_name}|${current_status:-incorporated}"
64
+ fi
65
+ current_name="${BASH_REMATCH[1]}"
66
+ current_name=$(echo "$current_name" | sed 's/^"//' | sed 's/"$//' | xargs)
67
+ current_status=""
68
+ elif [[ "$line" =~ ^[[:space:]]*status:[[:space:]]*(.+)$ ]]; then
69
+ current_status="${BASH_REMATCH[1]}"
70
+ current_status=$(echo "$current_status" | sed 's/^"//' | sed 's/"$//' | xargs)
71
+ fi
72
+ fi
73
+ done < <(extract_frontmatter "$file")
74
+
75
+ if [ -n "$current_name" ]; then
76
+ echo "${current_name}|${current_status:-incorporated}"
77
+ fi
78
+ }
79
+
80
+ # Helper: Extract external_dependencies from plan frontmatter
81
+ # Outputs: topic|state|task_id per line
82
+ extract_external_deps() {
83
+ local file="$1"
84
+ local frontmatter
85
+ frontmatter=$(extract_frontmatter "$file")
86
+
87
+ if ! echo "$frontmatter" | grep -q "^external_dependencies:" 2>/dev/null; then
88
+ return 0
89
+ fi
90
+
91
+ if echo "$frontmatter" | grep -q "^external_dependencies:[[:space:]]*\[\]" 2>/dev/null; then
92
+ return 0
93
+ fi
94
+
95
+ echo "$frontmatter" | awk '
96
+ /^external_dependencies:/ { in_block=1; next }
97
+ in_block && /^[a-z_]+:/ && !/^[[:space:]]/ { exit }
98
+ in_block && /^[[:space:]]*- topic:/ {
99
+ if (topic != "") print topic "|" state "|" task_id
100
+ line=$0; gsub(/^[[:space:]]*- topic:[[:space:]]*/, "", line)
101
+ topic=line; state=""; task_id=""
102
+ next
103
+ }
104
+ in_block && /^[[:space:]]*state:/ {
105
+ line=$0; gsub(/^[[:space:]]*state:[[:space:]]*/, "", line)
106
+ state=line; next
107
+ }
108
+ in_block && /^[[:space:]]*task_id:/ {
109
+ line=$0; gsub(/^[[:space:]]*task_id:[[:space:]]*/, "", line)
110
+ task_id=line; next
111
+ }
112
+ END { if (topic != "") print topic "|" state "|" task_id }
113
+ '
114
+ }
115
+
116
+ # Helper: Count completed tasks from implementation tracking
117
+ count_completed_tasks() {
118
+ local file="$1"
119
+ local frontmatter
120
+ frontmatter=$(extract_frontmatter "$file")
121
+
122
+ if echo "$frontmatter" | grep -q "^completed_tasks:[[:space:]]*\[\]" 2>/dev/null; then
123
+ echo 0
124
+ return
125
+ fi
126
+
127
+ local count
128
+ count=$(echo "$frontmatter" | awk '
129
+ /^completed_tasks:/ { in_block=1; next }
130
+ in_block && /^[a-z_]+:/ { exit }
131
+ in_block && /^[[:space:]]*-[[:space:]]/ { c++ }
132
+ END { print c+0 }
133
+ ')
134
+ echo "$count"
135
+ }
136
+
137
+ # Helper: Count completed phases from implementation tracking
138
+ count_completed_phases() {
139
+ local file="$1"
140
+ local frontmatter
141
+ frontmatter=$(extract_frontmatter "$file")
142
+
143
+ # Handle inline array format: [1, 2, 3]
144
+ local inline
145
+ inline=$(echo "$frontmatter" | grep "^completed_phases:" | sed 's/^completed_phases:[[:space:]]*//' || true)
146
+ if echo "$inline" | grep -q '^\['; then
147
+ local items
148
+ items=$(echo "$inline" | tr -d '[]' | tr ',' '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | grep -v '^$')
149
+ if [ -n "$items" ]; then
150
+ echo "$items" | wc -l | tr -d ' '
151
+ else
152
+ echo 0
153
+ fi
154
+ return
155
+ fi
156
+
157
+ if echo "$frontmatter" | grep -q "^completed_phases:[[:space:]]*\[\]" 2>/dev/null; then
158
+ echo 0
159
+ return
160
+ fi
161
+
162
+ local count
163
+ count=$(echo "$frontmatter" | awk '
164
+ /^completed_phases:/ { in_block=1; next }
165
+ in_block && /^[a-z_]+:/ { exit }
166
+ in_block && /^[[:space:]]*-[[:space:]]/ { c++ }
167
+ END { print c+0 }
168
+ ')
169
+ echo "$count"
170
+ }
171
+
172
+
173
+ # Start YAML output
174
+ echo "# Workflow Status Discovery"
175
+ echo "# Generated: $(date -Iseconds)"
176
+ echo ""
177
+
178
+ #
179
+ # RESEARCH
180
+ #
181
+ echo "research:"
182
+
183
+ research_count=0
184
+ if [ -d "$RESEARCH_DIR" ] && [ -n "$(ls -A "$RESEARCH_DIR" 2>/dev/null)" ]; then
185
+ echo " exists: true"
186
+ echo " files:"
187
+ for file in "$RESEARCH_DIR"/*; do
188
+ [ -f "$file" ] || continue
189
+ name=$(basename "$file" .md)
190
+ echo " - \"$name\""
191
+ research_count=$((research_count + 1))
192
+ done
193
+ echo " count: $research_count"
194
+ else
195
+ echo " exists: false"
196
+ echo " files: []"
197
+ echo " count: 0"
198
+ fi
199
+
200
+ echo ""
201
+
202
+ #
203
+ # DISCUSSIONS
204
+ #
205
+ echo "discussions:"
206
+
207
+ disc_count=0
208
+ disc_concluded=0
209
+ disc_in_progress=0
210
+
211
+ if [ -d "$DISCUSSION_DIR" ] && [ -n "$(ls -A "$DISCUSSION_DIR" 2>/dev/null)" ]; then
212
+ echo " exists: true"
213
+ echo " files:"
214
+ for file in "$DISCUSSION_DIR"/*.md; do
215
+ [ -f "$file" ] || continue
216
+ name=$(basename "$file" .md)
217
+ status=$(extract_field "$file" "status")
218
+ status=${status:-"unknown"}
219
+
220
+ echo " - name: \"$name\""
221
+ echo " status: \"$status\""
222
+
223
+ disc_count=$((disc_count + 1))
224
+ [ "$status" = "concluded" ] && disc_concluded=$((disc_concluded + 1))
225
+ [ "$status" = "in-progress" ] && disc_in_progress=$((disc_in_progress + 1))
226
+ done
227
+ echo " count: $disc_count"
228
+ echo " concluded: $disc_concluded"
229
+ echo " in_progress: $disc_in_progress"
230
+ else
231
+ echo " exists: false"
232
+ echo " files: []"
233
+ echo " count: 0"
234
+ echo " concluded: 0"
235
+ echo " in_progress: 0"
236
+ fi
237
+
238
+ echo ""
239
+
240
+ #
241
+ # SPECIFICATIONS
242
+ #
243
+ echo "specifications:"
244
+
245
+ spec_count=0
246
+ spec_active=0
247
+ spec_superseded=0
248
+ spec_feature=0
249
+ spec_crosscutting=0
250
+
251
+ if [ -d "$SPEC_DIR" ] && [ -n "$(ls -A "$SPEC_DIR" 2>/dev/null)" ]; then
252
+ echo " exists: true"
253
+ echo " files:"
254
+ for file in "$SPEC_DIR"/*.md; do
255
+ [ -f "$file" ] || continue
256
+ name=$(basename "$file" .md)
257
+ status=$(extract_field "$file" "status")
258
+ status=${status:-"in-progress"}
259
+ spec_type=$(extract_field "$file" "type")
260
+ spec_type=${spec_type:-"feature"}
261
+ superseded_by=$(extract_field "$file" "superseded_by")
262
+
263
+ echo " - name: \"$name\""
264
+ echo " status: \"$status\""
265
+ echo " type: \"$spec_type\""
266
+ [ -n "$superseded_by" ] && echo " superseded_by: \"$superseded_by\""
267
+
268
+ # Sources
269
+ sources_output=$(extract_sources "$file")
270
+ if [ -n "$sources_output" ]; then
271
+ echo " sources:"
272
+ while IFS='|' read -r src_name src_status; do
273
+ [ -z "$src_name" ] && continue
274
+ echo " - name: \"$src_name\""
275
+ echo " status: \"$src_status\""
276
+ done <<< "$sources_output"
277
+ else
278
+ echo " sources: []"
279
+ fi
280
+
281
+ spec_count=$((spec_count + 1))
282
+ if [ "$status" = "superseded" ]; then
283
+ spec_superseded=$((spec_superseded + 1))
284
+ else
285
+ spec_active=$((spec_active + 1))
286
+ [ "$spec_type" = "cross-cutting" ] && spec_crosscutting=$((spec_crosscutting + 1))
287
+ [ "$spec_type" != "cross-cutting" ] && spec_feature=$((spec_feature + 1))
288
+ fi
289
+ done
290
+ echo " count: $spec_count"
291
+ echo " active: $spec_active"
292
+ echo " superseded: $spec_superseded"
293
+ echo " feature: $spec_feature"
294
+ echo " crosscutting: $spec_crosscutting"
295
+ else
296
+ echo " exists: false"
297
+ echo " files: []"
298
+ echo " count: 0"
299
+ echo " active: 0"
300
+ echo " superseded: 0"
301
+ echo " feature: 0"
302
+ echo " crosscutting: 0"
303
+ fi
304
+
305
+ echo ""
306
+
307
+ #
308
+ # PLANS
309
+ #
310
+ echo "plans:"
311
+
312
+ plan_count=0
313
+ plan_concluded=0
314
+ plan_in_progress=0
315
+
316
+ if [ -d "$PLAN_DIR" ] && [ -n "$(ls -A "$PLAN_DIR" 2>/dev/null)" ]; then
317
+ echo " exists: true"
318
+ echo " files:"
319
+ for file in "$PLAN_DIR"/*.md; do
320
+ [ -f "$file" ] || continue
321
+ name=$(basename "$file" .md)
322
+ status=$(extract_field "$file" "status")
323
+ status=${status:-"unknown"}
324
+ format=$(extract_field "$file" "format")
325
+ format=${format:-"unknown"}
326
+ specification=$(extract_field "$file" "specification")
327
+ specification=${specification:-"${name}.md"}
328
+
329
+ echo " - name: \"$name\""
330
+ echo " status: \"$status\""
331
+ echo " format: \"$format\""
332
+ echo " specification: \"$specification\""
333
+
334
+ # External dependencies
335
+ deps_output=$(extract_external_deps "$file")
336
+ has_unresolved="false"
337
+ if [ -n "$deps_output" ]; then
338
+ echo " external_deps:"
339
+ while IFS='|' read -r dep_topic dep_state dep_task_id; do
340
+ [ -z "$dep_topic" ] && continue
341
+ echo " - topic: \"$dep_topic\""
342
+ echo " state: \"$dep_state\""
343
+ [ -n "$dep_task_id" ] && echo " task_id: \"$dep_task_id\""
344
+ [ "$dep_state" = "unresolved" ] && has_unresolved="true"
345
+ done <<< "$deps_output"
346
+ else
347
+ echo " external_deps: []"
348
+ fi
349
+ echo " has_unresolved_deps: $has_unresolved"
350
+
351
+ plan_count=$((plan_count + 1))
352
+ [ "$status" = "concluded" ] && plan_concluded=$((plan_concluded + 1))
353
+ { [ "$status" = "planning" ] || [ "$status" = "in-progress" ]; } && plan_in_progress=$((plan_in_progress + 1))
354
+ done
355
+ echo " count: $plan_count"
356
+ echo " concluded: $plan_concluded"
357
+ echo " in_progress: $plan_in_progress"
358
+ else
359
+ echo " exists: false"
360
+ echo " files: []"
361
+ echo " count: 0"
362
+ echo " concluded: 0"
363
+ echo " in_progress: 0"
364
+ fi
365
+
366
+ echo ""
367
+
368
+ #
369
+ # IMPLEMENTATION
370
+ #
371
+ echo "implementation:"
372
+
373
+ impl_count=0
374
+ impl_completed=0
375
+ impl_in_progress=0
376
+
377
+ if [ -d "$IMPL_DIR" ] && [ -n "$(ls -A "$IMPL_DIR" 2>/dev/null)" ]; then
378
+ echo " exists: true"
379
+ echo " files:"
380
+ for file in "$IMPL_DIR"/*/tracking.md; do
381
+ [ -f "$file" ] || continue
382
+ topic=$(basename "$(dirname "$file")")
383
+ status=$(extract_field "$file" "status")
384
+ status=${status:-"unknown"}
385
+ current_phase=$(extract_field "$file" "current_phase")
386
+
387
+ completed_tasks=$(count_completed_tasks "$file")
388
+ completed_phases=$(count_completed_phases "$file")
389
+
390
+ # Count total tasks from plan directory (local-markdown format)
391
+ total_tasks=0
392
+ plan_file="$PLAN_DIR/${topic}.md"
393
+ if [ -f "$plan_file" ]; then
394
+ plan_format=$(extract_field "$plan_file" "format")
395
+ if [ "$plan_format" = "local-markdown" ] && [ -d "$PLAN_DIR/${topic}" ]; then
396
+ total_tasks=$(ls -1 "$PLAN_DIR/${topic}/"*.md 2>/dev/null | wc -l | tr -d ' ')
397
+ fi
398
+ fi
399
+
400
+ echo " - topic: \"$topic\""
401
+ echo " status: \"$status\""
402
+ [ -n "$current_phase" ] && [ "$current_phase" != "~" ] && echo " current_phase: $current_phase"
403
+ echo " completed_tasks: $completed_tasks"
404
+ echo " completed_phases: $completed_phases"
405
+ echo " total_tasks: $total_tasks"
406
+
407
+ impl_count=$((impl_count + 1))
408
+ [ "$status" = "completed" ] && impl_completed=$((impl_completed + 1))
409
+ [ "$status" = "in-progress" ] && impl_in_progress=$((impl_in_progress + 1))
410
+ done
411
+ echo " count: $impl_count"
412
+ echo " completed: $impl_completed"
413
+ echo " in_progress: $impl_in_progress"
414
+ else
415
+ echo " exists: false"
416
+ echo " files: []"
417
+ echo " count: 0"
418
+ echo " completed: 0"
419
+ echo " in_progress: 0"
420
+ fi