@leeovery/claude-technical-workflows 2.1.33 → 2.1.35

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.
Files changed (52) hide show
  1. package/README.md +14 -5
  2. package/agents/implementation-analysis-task-writer.md +3 -2
  3. package/agents/planning-task-author.md +46 -16
  4. package/agents/review-findings-synthesizer.md +108 -0
  5. package/agents/review-task-verifier.md +4 -3
  6. package/package.json +1 -1
  7. package/skills/begin-implementation/SKILL.md +5 -1
  8. package/skills/begin-planning/SKILL.md +5 -1
  9. package/skills/migrate/SKILL.md +2 -1
  10. package/skills/migrate/scripts/migrate.sh +31 -28
  11. package/skills/migrate/scripts/migrations/001-discussion-frontmatter.sh +1 -15
  12. package/skills/migrate/scripts/migrations/002-specification-frontmatter.sh +0 -14
  13. package/skills/migrate/scripts/migrations/003-planning-frontmatter.sh +0 -14
  14. package/skills/migrate/scripts/migrations/004-sources-object-format.sh +0 -12
  15. package/skills/migrate/scripts/migrations/005-plan-external-deps-frontmatter.sh +0 -12
  16. package/skills/migrate/scripts/migrations/006-directory-restructure.sh +2 -22
  17. package/skills/migrate/scripts/migrations/007-tasks-subdirectory.sh +1 -17
  18. package/skills/migrate/scripts/migrations/008-review-directory-structure.sh +96 -0
  19. package/skills/migrate/scripts/migrations/009-review-per-plan-storage.sh +117 -0
  20. package/skills/migrate/scripts/migrations/010-gitignore-sessions.sh +67 -0
  21. package/skills/start-discussion/SKILL.md +1 -1
  22. package/skills/start-discussion/references/handle-selection.md +1 -1
  23. package/skills/start-discussion/references/research-analysis.md +3 -3
  24. package/skills/start-discussion/scripts/discovery.sh +1 -1
  25. package/skills/start-review/SKILL.md +48 -16
  26. package/skills/start-review/references/display-plans.md +11 -3
  27. package/skills/start-review/references/invoke-skill.md +41 -13
  28. package/skills/start-review/references/select-plans.md +31 -2
  29. package/skills/start-review/scripts/discovery.sh +89 -0
  30. package/skills/start-specification/SKILL.md +1 -1
  31. package/skills/start-specification/references/analysis-flow.md +2 -2
  32. package/skills/start-specification/references/display-analyze.md +1 -1
  33. package/skills/start-specification/references/display-groupings.md +3 -3
  34. package/skills/start-specification/references/display-specs-menu.md +1 -1
  35. package/skills/start-specification/scripts/discovery.sh +1 -1
  36. package/skills/technical-implementation/references/invoke-task-writer.md +1 -0
  37. package/skills/technical-planning/SKILL.md +4 -3
  38. package/skills/technical-planning/references/author-tasks.md +119 -35
  39. package/skills/technical-planning/references/output-formats/tick/about.md +3 -2
  40. package/skills/technical-planning/references/output-formats/tick/graph.md +2 -0
  41. package/skills/technical-planning/references/output-formats/tick/reading.md +2 -0
  42. package/skills/technical-planning/references/plan-construction.md +11 -15
  43. package/skills/technical-planning/references/review-integrity.md +1 -1
  44. package/skills/technical-review/SKILL.md +10 -34
  45. package/skills/technical-review/references/invoke-review-synthesizer.md +64 -0
  46. package/skills/technical-review/references/invoke-review-task-writer.md +44 -0
  47. package/skills/technical-review/references/invoke-task-verifiers.md +7 -6
  48. package/skills/technical-review/references/produce-review.md +25 -0
  49. package/skills/technical-review/references/review-actions-loop.md +295 -0
  50. package/skills/technical-review/references/template.md +1 -21
  51. package/agents/review-product-assessor.md +0 -112
  52. package/skills/technical-review/references/invoke-product-assessor.md +0 -57
package/README.md CHANGED
@@ -110,7 +110,7 @@ Each phase produces documents that feed the next. Here's the journey:
110
110
 
111
111
  **Implementation** — Executes plans via strict TDD. Tests first, then code, commit after each task. Per-task approval gates keep you in control, with auto-mode available when you trust the flow.
112
112
 
113
- **Review** — Validates the implementation against spec and plan. Catches drift, missing requirements, and quality issues. The spec is the source of truth here — earlier phases may contain rejected ideas that were intentionally filtered out. Produces structured feedback without fixing code directly.
113
+ **Review** — Validates the implementation against spec and plan. Catches drift, missing requirements, and quality issues. Findings can be synthesized into remediation tasks that feed back into implementation, closing the review-implementation loop.
114
114
 
115
115
  ### Standalone Skills
116
116
 
@@ -231,8 +231,11 @@ docs/workflow/
231
231
  ├── implementation/ # Phase 5 — directory per topic
232
232
  │ └── {topic}/
233
233
  │ └── tracking.md # Progress, gates, current task
234
- └── review/ # Phase 6 — one file per review
235
- └── {topic}.md
234
+ └── review/ # Phase 6 — versioned per review
235
+ └── {topic}/
236
+ └── r1/
237
+ ├── review.md # Review summary and verdict
238
+ └── qa-task-1.md # Per-task QA verification
236
239
  ```
237
240
 
238
241
  Research starts with `exploration.md` and splits into topic files as themes emerge. From specification onwards, each topic gets its own directory. Planning task storage varies by [output format](#output-formats) — the tree above shows local-markdown; Tick and Linear store tasks externally.
@@ -269,12 +272,15 @@ skills/
269
272
 
270
273
  agents/
271
274
  ├── review-task-verifier.md # Verifies single task implementation for review
275
+ ├── review-findings-synthesizer.md # Synthesizes review findings into remediation tasks
272
276
  ├── implementation-task-executor.md # TDD executor for single plan tasks
273
277
  ├── implementation-task-reviewer.md # Post-task review for spec conformance
274
278
  ├── planning-phase-designer.md # Design phases from specification
275
279
  ├── planning-task-designer.md # Break phases into task lists
276
280
  ├── planning-task-author.md # Write full task detail
277
- └── planning-dependency-grapher.md # Analyze task dependencies and priorities
281
+ ├── planning-dependency-grapher.md # Analyze task dependencies and priorities
282
+ ├── planning-review-traceability.md # Spec-to-plan traceability analysis
283
+ └── planning-review-integrity.md # Plan structural quality review
278
284
 
279
285
  tests/
280
286
  └── scripts/ # Shell script tests for discovery and migrations
@@ -310,7 +316,7 @@ Sequential skills that expect files from previous phases and pass content to pro
310
316
  | [**/start-specification**](skills/start-specification/) | Start a specification session from existing discussion(s). Automatically analyses multiple discussions for natural groupings and consolidates them into unified specifications. |
311
317
  | [**/start-planning**](skills/start-planning/) | Start a planning session from an existing specification. Creates implementation plans with phases, tasks, and acceptance criteria. Supports multiple output formats. |
312
318
  | [**/start-implementation**](skills/start-implementation/) | Start implementing a plan. Executes tasks via strict TDD, committing after each passing test. |
313
- | [**/start-review**](skills/start-review/) | Start reviewing completed work. Validates implementation against plan tasks and acceptance criteria. |
319
+ | [**/start-review**](skills/start-review/) | Start reviewing completed work. Validates implementation against plan tasks and acceptance criteria. Findings can be synthesized into remediation tasks. |
314
320
 
315
321
  #### Utility Skills
316
322
 
@@ -354,6 +360,9 @@ Subagents that skills can spawn for parallel task execution.
354
360
  | [**planning-task-designer**](agents/planning-task-designer.md) | technical-planning | Breaks a single phase into a task list with edge cases. |
355
361
  | [**planning-task-author**](agents/planning-task-author.md) | technical-planning | Writes full detail for a single plan task. |
356
362
  | [**planning-dependency-grapher**](agents/planning-dependency-grapher.md) | technical-planning | Analyzes authored tasks to establish internal dependencies and priorities. |
363
+ | [**planning-review-traceability**](agents/planning-review-traceability.md) | technical-planning | Spec-to-plan traceability analysis. |
364
+ | [**planning-review-integrity**](agents/planning-review-integrity.md) | technical-planning | Plan structural quality review. |
365
+ | [**review-findings-synthesizer**](agents/review-findings-synthesizer.md) | technical-review | Synthesizes review findings into normalized remediation tasks for plan integration. |
357
366
 
358
367
  ## Requirements
359
368
 
@@ -19,6 +19,7 @@ You receive via the orchestrator's prompt:
19
19
  4. **Plan format reading adapter path** — how to read tasks from the plan (for determining next phase number)
20
20
  5. **Plan format authoring adapter path** — how to create tasks in the plan
21
21
  6. **plan-index-schema.md** — Canonical plan index structure
22
+ 7. **Phase label** — the label for the new phase (e.g., "Analysis (Cycle 1)", "Review Remediation (Cycle 1)")
22
23
 
23
24
  ## Your Process
24
25
 
@@ -35,10 +36,10 @@ The Plan Index File (`docs/workflow/planning/{topic}/plan.md`) is the single sou
35
36
 
36
37
  Append at the end of the Plan Index File body, following the **Phase Entry** and **Task Table** templates from plan-index-schema:
37
38
 
38
- - Phase heading: `### Phase {N}: Analysis ({cycle description})`
39
+ - Phase heading: `### Phase {N}: {phase_label}`
39
40
  - Phase `status`: `approved` (pre-approved by user in approval gate)
40
41
  - Phase `ext_id`: external identifier for the phase from the output format
41
- - Phase goal: `Address findings from implementation analysis cycle {N}.`
42
+ - Phase goal: `Address findings from {phase_label}.`
42
43
  - Omit `approved_at` and acceptance criteria (analysis phases don't use them)
43
44
  - Task `Status`: `authored` (task files are fully written)
44
45
  - Task `Ext ID`: external identifier for the task from the output format
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: planning-task-author
3
- description: Writes full detail for a single plan task. Invoked by technical-planning skill during plan construction.
4
- tools: Read, Glob, Grep
3
+ description: Writes full detail for all plan tasks in a phase. Invoked by technical-planning skill during plan construction.
4
+ tools: Read, Glob, Grep, Write
5
5
  model: opus
6
6
  ---
7
7
 
@@ -18,13 +18,12 @@ You receive file paths via the orchestrator's prompt:
18
18
  3. **Cross-cutting spec paths** (if any) — Architectural decisions that influence planning
19
19
  4. **task-design.md** — Task design principles and template
20
20
  5. **All approved phases** — The complete phase structure (from the Plan Index File)
21
- 6. **Task list for current phase** — The approved task table
22
- 7. **Target task** — Which task to author (name, edge cases from the table)
23
- 8. **Output format adapter path** — The output format reference defining the exact file structure
21
+ 6. **Task list for current phase** — The approved task table (ALL tasks in the phase)
22
+ 7. **Scratch file path** — Where to write authored tasks
24
23
 
25
24
  On **amendment**, you also receive:
26
- - **Previous output** — Your prior task detail
27
- - **User feedback**What to change
25
+ - **Scratch file path** — Contains previously authored tasks with status markers
26
+ - The scratch file contains `rejected` tasks with feedback blockquotes rewrite only those
28
27
 
29
28
  ## Your Process
30
29
 
@@ -33,10 +32,40 @@ On **amendment**, you also receive:
33
32
  3. Read any cross-cutting specifications
34
33
  4. Read `task-design.md` — absorb the task template and quality standards
35
34
  5. Read the approved phases and task list — understand context and scope
36
- 6. Read the output format adapter understand the exact format for task files
37
- 7. Author the target task in the output format's structure
35
+ 6. Author all tasks in the phase, writing each to the scratch file incrementally — each task written to disk before starting the next
38
36
 
39
- If this is an **amendment**: read your previous output and the user's feedback, then revise accordingly.
37
+ If this is an **amendment**: read the scratch file, find tasks marked `rejected` (they have a feedback blockquote below the status line). Rewrite the entire scratch file — copy `approved` tasks verbatim, rewrite `rejected` tasks addressing the feedback. Reset rewritten tasks to `pending` status.
38
+
39
+ ## Scratch File Format
40
+
41
+ Write the scratch file with this structure:
42
+
43
+ ```markdown
44
+ ---
45
+ phase: {N}
46
+ phase_name: {Phase Name}
47
+ total: {count}
48
+ ---
49
+
50
+ ## {task-id} | pending
51
+
52
+ ### Task {seq}: {Task Name}
53
+
54
+ **Problem**: ...
55
+ **Solution**: ...
56
+ **Outcome**: ...
57
+ **Do**: ...
58
+ **Acceptance Criteria**: ...
59
+ **Tests**: ...
60
+ **Edge Cases**: ...
61
+ **Context**: ...
62
+ **Spec Reference**: ...
63
+
64
+ ## {task-id} | pending
65
+
66
+ ### Task {seq}: {Task Name}
67
+ ...
68
+ ```
40
69
 
41
70
  ## Task Template
42
71
 
@@ -48,20 +77,21 @@ Every task must include these fields (from task-design.md):
48
77
  - **Do**: Specific implementation steps (file locations, method names where helpful)
49
78
  - **Acceptance Criteria**: Pass/fail verifiable criteria
50
79
  - **Tests**: Named test cases including edge cases
80
+ - **Edge Cases**: Edge case handling (reference from the task table)
51
81
  - **Context**: (when relevant) Specification decisions and constraints that inform implementation
82
+ - **Spec Reference**: Which specification section(s) this task traces to
52
83
 
53
84
  ## Your Output
54
85
 
55
- Return the complete task detail in the exact format specified by the output format adapter. What you produce is what the orchestrator will write verbatim — the user sees your output before approving, and approved output is logged without modification.
56
-
57
- The output format adapter determines the file structure (frontmatter, sections, naming). Follow it precisely.
86
+ Write all tasks to the scratch file path provided. Use the canonical task template format above. Each task is written to disk before starting the next incremental writes, not a single batch at the end.
58
87
 
59
88
  ## Rules
60
89
 
61
- 1. **Self-contained** — anyone (Claude or human) could pick up this task and execute it without opening another document
90
+ 1. **Self-contained** — anyone (Claude or human) could pick up any task and execute it without opening another document
62
91
  2. **Specification is source of truth** — pull rationale, decisions, and constraints from the spec
63
92
  3. **Cross-cutting specs inform** — apply their architectural decisions where relevant (e.g., caching, rate limiting)
64
93
  4. **Every field required** — Problem, Solution, Outcome, Do, Acceptance Criteria, Tests are all mandatory
65
94
  5. **Tests include edge cases** — not just happy path; reference the edge cases from the task table
66
- 6. **Match the output format exactly** — follow the adapter's template structure
67
- 7. **No modifications after approval** — what the user sees is what gets logged
95
+ 6. **Write tasks to the scratch file incrementally** — each task written to disk before starting the next
96
+ 7. **Spec interpretation errors propagate across tasks in a batch** — ground every decision in the specification. When the spec is ambiguous, note the ambiguity in the task's Context section rather than inventing a plausible default.
97
+ 8. **No modifications after approval** — what the user sees is what gets logged
@@ -0,0 +1,108 @@
1
+ ---
2
+ name: review-findings-synthesizer
3
+ description: Synthesizes review findings into normalized tasks. Reads QA verification files, deduplicates, groups, normalizes using task template, and writes a staging file for orchestrator approval. Invoked by technical-review skill after review actions are initiated.
4
+ tools: Read, Write, Glob, Grep
5
+ model: opus
6
+ ---
7
+
8
+ # Review Findings: Synthesizer
9
+
10
+ You locate the review findings files using the provided paths, then read them, deduplicate and group findings, normalize into tasks, and write a staging file for user approval.
11
+
12
+ ## Your Input
13
+
14
+ You receive via the orchestrator's prompt:
15
+
16
+ 1. **Plan topic** — the plan being synthesized
17
+ 2. **Review path** — path to `r{N}/` directory containing review summary and QA files
18
+ 3. **Specification path** — the validated specification for context
19
+ 4. **Cycle number** — which review remediation cycle this is
20
+
21
+ ## Your Process
22
+
23
+ 1. **Read review summary** — extract verdict, required changes, recommendations from `review.md`
24
+ 2. **Read all QA files** — read every `qa-task-*.md` in the review path. Extract BLOCKING ISSUES and significant NON-BLOCKING NOTES with their file:line references
25
+ 3. **Deduplicate** — same issue found across multiple QA files → one finding, note all sources
26
+ 4. **Group related findings** — multiple findings about the same concern become one task (e.g., 3 QA findings about missing error handling in the same module = 1 "add error handling" task)
27
+ 5. **Filter** — discard low-severity non-blocking findings unless they cluster into a pattern. Never discard high-severity or blocking findings.
28
+ 6. **Normalize** — convert each group into a task using the canonical task template (Problem / Solution / Outcome / Do / Acceptance Criteria / Tests)
29
+ 7. **Write report** — output to `docs/workflow/implementation/{topic}/review-report-c{cycle}.md`
30
+ 8. **Write staging file** — if actionable tasks exist, write to `docs/workflow/implementation/{topic}/review-tasks-c{cycle}.md` with `status: pending` for each task
31
+
32
+ ## Report Format
33
+
34
+ Write the report file with this structure:
35
+
36
+ ```markdown
37
+ ---
38
+ scope: {scope description}
39
+ cycle: {N}
40
+ source: review
41
+ total_findings: {N}
42
+ deduplicated_findings: {N}
43
+ proposed_tasks: {N}
44
+ ---
45
+ # Review Report: {Scope} (Cycle {N})
46
+
47
+ ## Summary
48
+ {2-3 sentence overview of findings}
49
+
50
+ ## Discarded Findings
51
+ - {title} — {reason for discarding}
52
+ ```
53
+
54
+ ## Staging File Format
55
+
56
+ Write the staging file with this structure:
57
+
58
+ ```markdown
59
+ ---
60
+ scope: {scope description}
61
+ cycle: {N}
62
+ source: review
63
+ total_proposed: {N}
64
+ gate_mode: gated
65
+ ---
66
+ # Review Tasks: {Scope} (Cycle {N})
67
+
68
+ ## Task 1: {title}
69
+ status: pending
70
+ severity: high
71
+ sources: qa-task-3, qa-task-7
72
+
73
+ **Problem**: {what the review found}
74
+ **Solution**: {what to fix}
75
+ **Outcome**: {what success looks like}
76
+ **Do**: {step-by-step implementation instructions}
77
+ **Acceptance Criteria**:
78
+ - {criterion}
79
+ **Tests**:
80
+ - {test description}
81
+
82
+ ## Task 2: {title}
83
+ status: pending
84
+ ...
85
+ ```
86
+
87
+ ## Hard Rules
88
+
89
+ **MANDATORY. No exceptions.**
90
+
91
+ 1. **No new features** — only address issues found in the review. Every proposed task must trace back to a specific review finding.
92
+ 2. **Never discard blocking** — blocking issues from QA always become proposed tasks.
93
+ 3. **Self-contained tasks** — every proposed task must be independently executable. No task should depend on another proposed task.
94
+ 4. **Faithful synthesis** — do not invent findings. Every proposed task must trace back to at least one QA finding.
95
+ 5. **No git writes** — do not commit or stage. Writing the report and staging files are your only file writes.
96
+
97
+ ## Your Output
98
+
99
+ Return a brief status to the orchestrator:
100
+
101
+ ```
102
+ STATUS: tasks_proposed | clean
103
+ TASKS_PROPOSED: {N}
104
+ SUMMARY: {1-2 sentences}
105
+ ```
106
+
107
+ - `tasks_proposed`: tasks written to staging file — orchestrator should present for approval
108
+ - `clean`: no actionable findings — orchestrator should report clean result
@@ -17,8 +17,9 @@ You receive:
17
17
  3. **Plan path**: The full plan for additional context
18
18
  4. **Project skill paths**: Relevant `.claude/skills/` paths for framework conventions
19
19
  5. **Review checklist path**: Path to the review checklist (`skills/technical-review/references/review-checklist.md`) — read this for detailed verification criteria
20
- 6. **Topic name**: The plan topic (used for output file path)
21
- 7. **Task index**: Sequential number for this task (used for output file naming)
20
+ 6. **Topic**: The plan topic name (used for output directory)
21
+ 7. **Review number**: Version number (e.g., 1 for `r1/`)
22
+ 8. **Task index**: Sequential number for this task (used for output file naming)
22
23
 
23
24
  ## Your Task
24
25
 
@@ -86,7 +87,7 @@ Review the implementation as a senior architect would:
86
87
 
87
88
  ## Output File Format
88
89
 
89
- Write to `docs/workflow/review/{topic}/qa-task-{index}.md`:
90
+ Write to `docs/workflow/review/{topic}/r{N}/qa-task-{index}.md`:
90
91
 
91
92
  ```
92
93
  TASK: [Task name/description]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leeovery/claude-technical-workflows",
3
- "version": "2.1.33",
3
+ "version": "2.1.35",
4
4
  "description": "Technical workflow skills & commands for Claude Code",
5
5
  "license": "MIT",
6
6
  "author": "Lee Overy <me@leeovery.com>",
@@ -25,12 +25,16 @@ This skill is a **bridge** — it runs pre-flight checks for implementation and
25
25
 
26
26
  ## Step 1: Run Discovery
27
27
 
28
- Execute the start-implementation discovery script to gather current state:
28
+ !`.claude/skills/start-implementation/scripts/discovery.sh`
29
+
30
+ If the above shows a script invocation rather than YAML output, the dynamic content preprocessor did not run. Execute the script before continuing:
29
31
 
30
32
  ```bash
31
33
  .claude/skills/start-implementation/scripts/discovery.sh
32
34
  ```
33
35
 
36
+ If YAML content is already displayed, it has been run on your behalf.
37
+
34
38
  Parse the output to find the plan matching the provided topic. Extract:
35
39
 
36
40
  - **Plan details**: status, format, plan_id, specification, specification_exists
@@ -25,12 +25,16 @@ This skill is a **bridge** — it runs pre-flight checks for planning and hands
25
25
 
26
26
  ## Step 1: Run Discovery
27
27
 
28
- Execute the start-planning discovery script to gather current state:
28
+ !`.claude/skills/start-planning/scripts/discovery.sh`
29
+
30
+ If the above shows a script invocation rather than YAML output, the dynamic content preprocessor did not run. Execute the script before continuing:
29
31
 
30
32
  ```bash
31
33
  .claude/skills/start-planning/scripts/discovery.sh
32
34
  ```
33
35
 
36
+ If YAML content is already displayed, it has been run on your behalf.
37
+
34
38
  Parse the output to extract:
35
39
 
36
40
  - **Cross-cutting specifications** from `specifications.crosscutting` (name, status)
@@ -39,6 +39,7 @@ Return control silently - no user interaction needed.
39
39
  ## Notes
40
40
 
41
41
  - This skill is run automatically at the start of every workflow skill
42
- - Migrations are tracked in `docs/workflow/.cache/migrations.log`
42
+ - Migrations are tracked in `docs/workflow/.state/migrations` (one migration ID per line)
43
+ - The orchestrator skips entire migrations once recorded — individual scripts don't track
43
44
  - To force re-running all migrations, delete the tracking file
44
45
  - Each migration is idempotent - safe to run multiple times
@@ -9,54 +9,43 @@
9
9
  # ./scripts/migrate.sh
10
10
  #
11
11
  # Tracking:
12
- # Migrations are tracked in docs/workflow/.cache/migrations.log
13
- # Format: "filepath: migration_id" (one per line, append-only)
12
+ # Migrations are tracked in docs/workflow/.state/migrations
13
+ # Format: "migration_id" per line (e.g., "001", "002")
14
+ # The orchestrator checks/records migration IDs — individual scripts don't track.
14
15
  # Delete the log file to force re-running all migrations.
15
16
  #
16
17
  # Adding new migrations:
17
18
  # 1. Create scripts/migrations/NNN-description.sh (e.g., 002-spec-frontmatter.sh)
18
19
  # 2. The script will be run automatically in numeric order
19
- # 3. Each migration script receives helper functions via source
20
+ # 3. Each migration script receives helper functions via source: report_update, report_skip
20
21
  #
21
22
 
22
23
  set -eo pipefail
23
24
 
24
25
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
25
26
  MIGRATIONS_DIR="$SCRIPT_DIR/migrations"
26
- TRACKING_FILE="docs/workflow/.cache/migrations.log"
27
+ TRACKING_FILE="docs/workflow/.state/migrations"
27
28
 
28
29
  # Track counts for final report
29
30
  FILES_UPDATED=0
30
31
  FILES_SKIPPED=0
31
32
  MIGRATIONS_RUN=0
32
33
 
33
- # Ensure cache directory exists
34
+ # Ensure state directory exists
34
35
  mkdir -p "$(dirname "$TRACKING_FILE")"
35
36
 
37
+ # Self-healing: merge entries from old locations into .state/migrations
38
+ OLD_CACHE_LOG="docs/workflow/.cache/migrations.log"
39
+ OLD_CACHE_FILE="docs/workflow/.cache/migrations"
40
+ if [ -f "$OLD_CACHE_LOG" ] || [ -f "$OLD_CACHE_FILE" ]; then
41
+ { cat "$OLD_CACHE_LOG" 2>/dev/null; cat "$OLD_CACHE_FILE" 2>/dev/null; cat "$TRACKING_FILE" 2>/dev/null; } | sort -u > "${TRACKING_FILE}.tmp"
42
+ mv "${TRACKING_FILE}.tmp" "$TRACKING_FILE"
43
+ rm -f "$OLD_CACHE_LOG" "$OLD_CACHE_FILE"
44
+ fi
45
+
36
46
  # Touch tracking file if it doesn't exist
37
47
  touch "$TRACKING_FILE"
38
48
 
39
- #
40
- # Helper function: Check if a migration has been applied to a file
41
- # Usage: is_migrated "filepath" "migration_id"
42
- # Returns: 0 if migrated, 1 if not
43
- #
44
- is_migrated() {
45
- local filepath="$1"
46
- local migration_id="$2"
47
- grep -q "^${filepath}: ${migration_id}$" "$TRACKING_FILE" 2>/dev/null
48
- }
49
-
50
- #
51
- # Helper function: Record that a migration was applied to a file
52
- # Usage: record_migration "filepath" "migration_id"
53
- #
54
- record_migration() {
55
- local filepath="$1"
56
- local migration_id="$2"
57
- echo "${filepath}: ${migration_id}" >> "$TRACKING_FILE"
58
- }
59
-
60
49
  #
61
50
  # Helper function: Report a file update (for migration scripts to call)
62
51
  # Usage: report_update "filepath" "description"
@@ -78,7 +67,7 @@ report_skip() {
78
67
  }
79
68
 
80
69
  # Export functions and variables for migration scripts
81
- export -f is_migrated record_migration report_update report_skip
70
+ export -f report_update report_skip
82
71
  export TRACKING_FILE FILES_UPDATED FILES_SKIPPED
83
72
 
84
73
  #
@@ -99,6 +88,14 @@ if [ ${#MIGRATION_SCRIPTS[@]} -eq 0 ]; then
99
88
  exit 0
100
89
  fi
101
90
 
91
+ # One-time: convert old per-file format to per-migration format
92
+ # Old: "docs/workflow/discussion/auth.md: 001" → extracts "001"
93
+ # New: "001" → already correct
94
+ if grep -q ': [0-9]' "$TRACKING_FILE" 2>/dev/null; then
95
+ grep -oE '[0-9]+$' "$TRACKING_FILE" | sort -u > "${TRACKING_FILE}.tmp"
96
+ mv "${TRACKING_FILE}.tmp" "$TRACKING_FILE"
97
+ fi
98
+
102
99
  for script in "${MIGRATION_SCRIPTS[@]}"; do
103
100
  # Extract migration ID from filename (e.g., "001" from "001-discussion-frontmatter.sh")
104
101
  migration_id=$(basename "$script" .sh | grep -oE '^[0-9]+')
@@ -108,11 +105,17 @@ for script in "${MIGRATION_SCRIPTS[@]}"; do
108
105
  continue
109
106
  fi
110
107
 
108
+ # Global check — skip entire migration if already recorded
109
+ if grep -q "^${migration_id}$" "$TRACKING_FILE" 2>/dev/null; then
110
+ continue
111
+ fi
112
+
111
113
  # Source and run the migration script
112
- # The script has access to: is_migrated, record_migration, report_update, report_skip
114
+ # The script has access to: report_update, report_skip
113
115
  # shellcheck source=/dev/null
114
116
  source "$script"
115
117
 
118
+ echo "$migration_id" >> "$TRACKING_FILE"
116
119
  MIGRATIONS_RUN=$((MIGRATIONS_RUN + 1))
117
120
  done
118
121
 
@@ -24,9 +24,7 @@
24
24
  # Exploring, Deciding → in-progress
25
25
  # Concluded, Complete, ✅ Complete → concluded
26
26
  #
27
- # This script is sourced by migrate-documents.sh and has access to:
28
- # - is_migrated "filepath" "migration_id"
29
- # - record_migration "filepath" "migration_id"
27
+ # This script is sourced by migrate.sh and has access to:
30
28
  # - report_update "filepath" "description"
31
29
  # - report_skip "filepath"
32
30
  #
@@ -43,24 +41,14 @@ fi
43
41
  for file in "$DISCUSSION_DIR"/*.md; do
44
42
  [ -f "$file" ] || continue
45
43
 
46
- # Check if already migrated via tracking
47
- if is_migrated "$file" "$MIGRATION_ID"; then
48
- report_skip "$file"
49
- continue
50
- fi
51
-
52
44
  # Check if file already has YAML frontmatter
53
45
  if head -1 "$file" 2>/dev/null | grep -q "^---$"; then
54
- # Already has frontmatter - just record and skip
55
- record_migration "$file" "$MIGRATION_ID"
56
46
  report_skip "$file"
57
47
  continue
58
48
  fi
59
49
 
60
50
  # Check if file has legacy format (look for **Status**: or **Status:** or **Date**: or **Started:**)
61
51
  if ! grep -q '^\*\*Status\*\*:\|^\*\*Status:\*\*\|^\*\*Date\*\*:\|^\*\*Started:\*\*' "$file" 2>/dev/null; then
62
- # No legacy format found - might be malformed, skip
63
- record_migration "$file" "$MIGRATION_ID"
64
52
  report_skip "$file"
65
53
  continue
66
54
  fi
@@ -134,7 +122,5 @@ date: $date_value
134
122
  echo "$content"
135
123
  } > "$file"
136
124
 
137
- # Record and report
138
- record_migration "$file" "$MIGRATION_ID"
139
125
  report_update "$file" "added frontmatter"
140
126
  done
@@ -34,8 +34,6 @@
34
34
  # (not found or unrecognized) → empty (requires manual review)
35
35
  #
36
36
  # This script is sourced by migrate.sh and has access to:
37
- # - is_migrated "filepath" "migration_id"
38
- # - record_migration "filepath" "migration_id"
39
37
  # - report_update "filepath" "description"
40
38
  # - report_skip "filepath"
41
39
  #
@@ -57,24 +55,14 @@ for file in "$SPEC_DIR"/*.md; do
57
55
  *-review-*|*-tracking*) continue ;;
58
56
  esac
59
57
 
60
- # Check if already migrated via tracking
61
- if is_migrated "$file" "$MIGRATION_ID"; then
62
- report_skip "$file"
63
- continue
64
- fi
65
-
66
58
  # Check if file already has YAML frontmatter
67
59
  if head -1 "$file" 2>/dev/null | grep -q "^---$"; then
68
- # Already has frontmatter - just record and skip
69
- record_migration "$file" "$MIGRATION_ID"
70
60
  report_skip "$file"
71
61
  continue
72
62
  fi
73
63
 
74
64
  # Check if file has legacy format (look for **Status**: or **Status:** or **Type**: or **Last Updated**:)
75
65
  if ! grep -q '^\*\*Status\*\*:\|^\*\*Status:\*\*\|^\*\*Type\*\*:\|^\*\*Last Updated\*\*:' "$file" 2>/dev/null; then
76
- # No legacy format found - might be malformed, skip
77
- record_migration "$file" "$MIGRATION_ID"
78
66
  report_skip "$file"
79
67
  continue
80
68
  fi
@@ -206,7 +194,5 @@ date: $date_value
206
194
  echo "$content"
207
195
  } > "$file"
208
196
 
209
- # Record and report
210
- record_migration "$file" "$MIGRATION_ID"
211
197
  report_update "$file" "added frontmatter (status: $status_new, type: $type_new)"
212
198
  done
@@ -32,8 +32,6 @@
32
32
  # Completed, Done → concluded
33
33
  #
34
34
  # This script is sourced by migrate.sh and has access to:
35
- # - is_migrated "filepath" "migration_id"
36
- # - record_migration "filepath" "migration_id"
37
35
  # - report_update "filepath" "description"
38
36
  # - report_skip "filepath"
39
37
  #
@@ -55,16 +53,8 @@ for file in "$PLAN_DIR"/*.md; do
55
53
  *-review-*|*-tracking*) continue ;;
56
54
  esac
57
55
 
58
- # Check if already migrated via tracking
59
- if is_migrated "$file" "$MIGRATION_ID"; then
60
- report_skip "$file"
61
- continue
62
- fi
63
-
64
56
  # Check if file already has full frontmatter (topic field present)
65
57
  if head -10 "$file" 2>/dev/null | grep -q "^topic:"; then
66
- # Already has full frontmatter - just record and skip
67
- record_migration "$file" "$MIGRATION_ID"
68
58
  report_skip "$file"
69
59
  continue
70
60
  fi
@@ -75,8 +65,6 @@ for file in "$PLAN_DIR"/*.md; do
75
65
  has_inline_metadata=$(grep -c '^\*\*Date\*\*:\|^\*\*Status\*\*:\|^\*\*Specification\*\*:' "$file" 2>/dev/null || true)
76
66
 
77
67
  if [ "${has_partial_frontmatter:-0}" = "0" ] && [ "${has_inline_metadata:-0}" = "0" ]; then
78
- # No legacy format found - might be malformed, skip
79
- record_migration "$file" "$MIGRATION_ID"
80
68
  report_skip "$file"
81
69
  continue
82
70
  fi
@@ -192,7 +180,5 @@ specification: $spec_value
192
180
  echo "$content"
193
181
  } > "$file"
194
182
 
195
- # Record and report
196
- record_migration "$file" "$MIGRATION_ID"
197
183
  report_update "$file" "added full frontmatter (status: $status_new, format: $format_value)"
198
184
  done
@@ -29,8 +29,6 @@
29
29
  # - If no matching discussion, add empty sources: [] and report for user review
30
30
  #
31
31
  # This script is sourced by migrate.sh and has access to:
32
- # - is_migrated "filepath" "migration_id"
33
- # - record_migration "filepath" "migration_id"
34
32
  # - report_update "filepath" "description"
35
33
  # - report_skip "filepath"
36
34
  #
@@ -92,15 +90,8 @@ for file in "$SPEC_DIR"/*.md; do
92
90
  *-review-*|*-tracking*) continue ;;
93
91
  esac
94
92
 
95
- # Check if already migrated via tracking
96
- if is_migrated "$file" "$MIGRATION_ID"; then
97
- report_skip "$file"
98
- continue
99
- fi
100
-
101
93
  # Check if file has YAML frontmatter
102
94
  if ! head -1 "$file" 2>/dev/null | grep -q "^---$"; then
103
- record_migration "$file" "$MIGRATION_ID"
104
95
  report_skip "$file"
105
96
  continue
106
97
  fi
@@ -113,7 +104,6 @@ for file in "$SPEC_DIR"/*.md; do
113
104
 
114
105
  # If sources field exists, check if already in object format
115
106
  if $has_sources_field && sources_already_object_format "$file"; then
116
- record_migration "$file" "$MIGRATION_ID"
117
107
  report_skip "$file"
118
108
  continue
119
109
  fi
@@ -196,8 +186,6 @@ ${new_sources_block}"
196
186
  echo "$content"
197
187
  } > "$file"
198
188
 
199
- record_migration "$file" "$MIGRATION_ID"
200
-
201
189
  # Report appropriate message based on what was done
202
190
  if $has_sources_field; then
203
191
  report_update "$file" "converted sources to object format"