jdi-cli 0.1.2 → 0.1.3

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
@@ -27,6 +27,10 @@ Full-blown AI workflows (33+ agents, 60+ commands, 100+ subworkflows) burn token
27
27
  /jdi-do <N> <- execute via doer specialist (SUMMARY.md)
28
28
  /jdi-verify <N> <- gates via reviewer (REVIEW.md)
29
29
  /jdi-ship <N> <- update ROADMAP, advance phase
30
+
31
+ # Roadmap mutation (run anytime)
32
+ /jdi-add-phase "<name>" <- append (or --at <pos>) a new phase
33
+ /jdi-remove-phase <N> <- remove a future/pending phase
30
34
  ```
31
35
 
32
36
  ### Brownfield (existing project)
@@ -527,6 +531,8 @@ See [AGENTS.md](AGENTS.md) for full details.
527
531
  | `/jdi-do <N>` | phase number | `--sequential` (force sequential execution even if waves permit parallel) | Execute tasks via doer specialist(s) → SUMMARY.md |
528
532
  | `/jdi-verify <N>` | phase number | — | Run reviewer specialist gates → REVIEW.md (verdict APPROVED / APPROVED_WITH_WARNINGS / BLOCKED) |
529
533
  | `/jdi-ship <N>` | phase number | — | Update ROADMAP, advance phase. Gates: verdict must not be BLOCKED |
534
+ | `/jdi-add-phase "<name>"` | phase name (required) | `--goal "<text>"`, `--at <pos>`, `--reason "<text>"` | Append (or insert at position) a new phase in ROADMAP.md. Bumps `total_phases`. Cannot insert at or before `current_phase`. |
535
+ | `/jdi-remove-phase <N>` | phase number (required) | `--force` (required if artifacts exist) | Remove a future or pending phase. Refuses for `done`, current, or past phases. Archives existing artifacts to `.jdi/archive/removed-<NN-slug>/`. Numbers are NOT renumbered (preserves history). |
530
536
 
531
537
  **Brownfield entry (1):**
532
538
 
@@ -0,0 +1,171 @@
1
+ ---
2
+ name: jdi-add-phase
3
+ description: Adds a new phase to ROADMAP.md. Append at end (default) or insert at a specific position. Bumps total_phases. Atomic commit.
4
+ argument_hint: "\"<phase name>\" [--goal \"<goal>\"] [--at <position>]"
5
+ runtime_intent:
6
+ invokes_agent: none
7
+ runtime_overrides:
8
+ claude:
9
+ allowed-tools: [Read, Write, Edit, Bash, Grep, Glob, AskUserQuestion]
10
+ copilot:
11
+ tools: [read, write, edit, grep, glob, terminal]
12
+ opencode:
13
+ subtask: true
14
+ antigravity:
15
+ triggers:
16
+ - "/jdi-add-phase"
17
+ - "add new phase"
18
+ - "create phase"
19
+ ---
20
+
21
+ <objective>
22
+ Adds a new phase to the project's roadmap. Edits `.jdi/ROADMAP.md`. Does not start the phase — only registers it. The user advances via `/jdi-discuss <N>` when ready.
23
+ </objective>
24
+
25
+ <arguments>
26
+ - `name` (required) — short phase name. Quote if it contains spaces.
27
+ - `--goal "<text>"` (optional) — 1-line description of what the phase delivers. If missing, AskUserQuestion will prompt.
28
+ - `--at <position>` (optional) — insert at this position instead of appending. Existing phases at and after `<position>` shift down by 1 (renumbered in ROADMAP only — slugs stay the same in any existing `.jdi/phases/` folders). Default: append.
29
+
30
+ Examples:
31
+ - `/jdi-add-phase "User authentication" --goal "Login + signup + JWT"`
32
+ - `/jdi-add-phase "Performance pass" --at 3`
33
+ - `/jdi-add-phase "Hotfix N+1 query"`
34
+ </arguments>
35
+
36
+ <process>
37
+
38
+ ### Step 1: Validation
39
+ ```bash
40
+ test -d .jdi/ || { echo "Not a JDI project. /jdi-new first."; exit 1; }
41
+ test -f .jdi/ROADMAP.md || { echo "ROADMAP.md missing."; exit 1; }
42
+ test -f .jdi/STATE.md || { echo "STATE.md missing."; exit 1; }
43
+ ```
44
+
45
+ If `<name>` argument missing: AskUserQuestion "Phase name?" (free text). Required.
46
+
47
+ If `--goal` flag missing: AskUserQuestion "Phase goal (1 line)?" (free text). Required.
48
+
49
+ ### Step 2: Compute phase number + slug
50
+
51
+ Read `total_phases` from `.jdi/ROADMAP.md`:
52
+
53
+ ```bash
54
+ TOTAL=$(grep -oE 'total_phases:\s*[0-9]+' .jdi/ROADMAP.md | grep -oE '[0-9]+')
55
+ ```
56
+
57
+ PowerShell:
58
+ ```powershell
59
+ $total = (Select-String -Path .jdi/ROADMAP.md -Pattern 'total_phases:\s*([0-9]+)').Matches[0].Groups[1].Value -as [int]
60
+ ```
61
+
62
+ If `--at <pos>` provided, validate `1 <= pos <= total + 1`. Otherwise `pos = total + 1` (append).
63
+
64
+ If `pos <= current_phase` (read from STATE.md), abort with error: "Cannot insert before current phase {current}. Use --at {current+1} or higher."
65
+
66
+ Generate `slug` from `name`:
67
+ - Lowercase
68
+ - Replace accents (à → a, é → e, ç → c, ñ → n)
69
+ - Non-alphanumeric → `-`
70
+ - Collapse repeated `-`, strip leading/trailing `-`
71
+ - Truncate to 40 chars
72
+
73
+ Phase identifier prefix is the 2-digit position (`NN`): `01`, `02`, ..., zero-padded.
74
+
75
+ ### Step 3: Renumber prefix on shift (only if --at)
76
+
77
+ If `--at <pos>` shifts existing phases:
78
+
79
+ Edit `.jdi/ROADMAP.md` — for every existing `### Phase K:` where `K >= pos`, change to `### Phase K+1:` and bump its `**Slug:**` prefix from `KK-...` to `(K+1)(K+1)-...`.
80
+
81
+ **WARNING (printed):**
82
+ > "Renumbering ROADMAP phases. Any existing `.jdi/phases/<NN-slug>/` folders are NOT renamed — they keep their original slugs and become "history". New work in renumbered phases creates new folders. Commits referencing old `phase {K}` remain valid as history."
83
+
84
+ This is intentional. Do not rename `.jdi/phases/` folders — would break commit history and cross-references in DECISIONS.md.
85
+
86
+ If `--at` not provided (append), skip Step 3.
87
+
88
+ ### Step 4: Append phase section to ROADMAP.md
89
+
90
+ If appending (`pos == total + 1`), append at the bottom of `## Phases`:
91
+
92
+ ```markdown
93
+
94
+ ### Phase {pos}: {name}
95
+ - **Slug:** {NN}-{slug}
96
+ - **Status:** pending
97
+ - **Goal:** {goal}
98
+ ```
99
+
100
+ If inserting (`pos <= total`), insert the new section BEFORE the section that previously had number `pos` (now renumbered to `pos+1`).
101
+
102
+ ### Step 5: Bump total_phases
103
+
104
+ Edit `.jdi/ROADMAP.md`:
105
+ ```
106
+ total_phases: {TOTAL + 1}
107
+ ```
108
+
109
+ ### Step 6: Audit trail in DECISIONS.md (optional, only if user passes --reason)
110
+
111
+ Not required. If user wants to record why this phase was added mid-project, they pass `--reason "<text>"`. When present, append to `.jdi/DECISIONS.md`:
112
+
113
+ ```markdown
114
+ D-{N+1} ({date}, phase {pos}): Phase added mid-project. Reason: {reason}
115
+ ```
116
+
117
+ (N = current max D-X.)
118
+
119
+ ### Step 7: Commit
120
+
121
+ ```bash
122
+ git add .jdi/ROADMAP.md .jdi/DECISIONS.md 2>/dev/null
123
+ git commit -m "chore(jdi): add phase {pos} {NN-slug}"
124
+ ```
125
+
126
+ PowerShell:
127
+ ```powershell
128
+ git add .jdi/ROADMAP.md .jdi/DECISIONS.md 2>$null
129
+ git commit -m "chore(jdi): add phase $pos $NN-$slug"
130
+ ```
131
+
132
+ ### Step 8: Confirm
133
+
134
+ ```
135
+ Phase {pos}: {name} added.
136
+ Slug: {NN}-{slug}
137
+ Goal: {goal}
138
+ Status: pending
139
+ total_phases: {TOTAL + 1}
140
+
141
+ Next: /jdi-discuss {pos} (when ready to start this phase)
142
+ ```
143
+
144
+ </process>
145
+
146
+ <gates>
147
+ - pre: `.jdi/ROADMAP.md` + `.jdi/STATE.md` exist
148
+ - pre: `--at <pos>` (if used) is greater than `current_phase` in STATE.md
149
+ - post: ROADMAP.md has new phase section + bumped total_phases + atomic commit
150
+ </gates>
151
+
152
+ <errors>
153
+ - `.jdi/` missing -> "Run /jdi-new first"
154
+ - `--at <pos>` <= current_phase -> "Cannot insert before current phase. Use --at {current+1} or higher."
155
+ - `--at <pos>` < 1 or > total+1 -> "Position out of range. Valid: 1..{total+1}"
156
+ - Phase name empty -> AskUserQuestion to fill
157
+ - Goal empty -> AskUserQuestion to fill
158
+ </errors>
159
+
160
+ <runtime_notes>
161
+
162
+ **Claude Code:**
163
+ - AskUserQuestion handles missing args interactively.
164
+
165
+ **Copilot:**
166
+ - AskUserQuestion not always available — read missing args from prompt body or fail with clear error.
167
+
168
+ **OpenCode/Antigravity:**
169
+ - Same interactive flow as Claude when supported. Otherwise fail with clear error message asking the user to re-invoke with all args.
170
+
171
+ </runtime_notes>
@@ -0,0 +1,228 @@
1
+ ---
2
+ name: jdi-remove-phase
3
+ description: Removes a phase from ROADMAP.md. Refuses to remove done phases or the current phase. Archives any existing phase artifacts. Atomic commit.
4
+ argument_hint: "<phase_number> [--force]"
5
+ runtime_intent:
6
+ invokes_agent: none
7
+ runtime_overrides:
8
+ claude:
9
+ allowed-tools: [Read, Write, Edit, Bash, Grep, Glob, AskUserQuestion]
10
+ copilot:
11
+ tools: [read, write, edit, grep, glob, terminal]
12
+ opencode:
13
+ subtask: true
14
+ antigravity:
15
+ triggers:
16
+ - "/jdi-remove-phase"
17
+ - "remove phase"
18
+ - "delete phase"
19
+ ---
20
+
21
+ <objective>
22
+ Removes a phase from `.jdi/ROADMAP.md`. Refuses to remove the current phase or any phase already shipped. If the phase has artifacts under `.jdi/phases/<NN-slug>/`, moves them to `.jdi/archive/removed-<NN-slug>/` instead of deleting (preserves history).
23
+ </objective>
24
+
25
+ <arguments>
26
+ - `phase_number` (required) — number of the phase to remove (as listed in ROADMAP.md).
27
+ - `--force` (optional) — required when removing a phase that has any artifacts in `.jdi/phases/`. Without `--force`, the command refuses and explains.
28
+
29
+ Examples:
30
+ - `/jdi-remove-phase 4`
31
+ - `/jdi-remove-phase 5 --force`
32
+ </arguments>
33
+
34
+ <process>
35
+
36
+ ### Step 1: Validation
37
+
38
+ ```bash
39
+ test -d .jdi/ || { echo "Not a JDI project."; exit 1; }
40
+ test -f .jdi/ROADMAP.md || { echo "ROADMAP.md missing."; exit 1; }
41
+ test -f .jdi/STATE.md || { echo "STATE.md missing."; exit 1; }
42
+
43
+ # Argument required
44
+ [ -n "$1" ] || { echo "Phase number required. Usage: /jdi-remove-phase <N> [--force]"; exit 1; }
45
+ ```
46
+
47
+ Parse `phase_number` (positional). Parse `--force` flag.
48
+
49
+ ### Step 2: Read state
50
+
51
+ ```bash
52
+ CURRENT=$(grep -oE 'current_phase:\s*[0-9]+' .jdi/STATE.md | grep -oE '[0-9]+')
53
+ TOTAL=$(grep -oE 'total_phases:\s*[0-9]+' .jdi/ROADMAP.md | grep -oE '[0-9]+')
54
+ PHASE_NUMBER=$1
55
+ ```
56
+
57
+ PowerShell:
58
+ ```powershell
59
+ $current = (Select-String -Path .jdi/STATE.md -Pattern 'current_phase:\s*([0-9]+)').Matches[0].Groups[1].Value -as [int]
60
+ $total = (Select-String -Path .jdi/ROADMAP.md -Pattern 'total_phases:\s*([0-9]+)').Matches[0].Groups[1].Value -as [int]
61
+ $phaseNumber = [int]$args[0]
62
+ ```
63
+
64
+ ### Step 3: Hard refuses (no override)
65
+
66
+ ```bash
67
+ # Must be in range
68
+ if [ "$PHASE_NUMBER" -lt 1 ] || [ "$PHASE_NUMBER" -gt "$TOTAL" ]; then
69
+ echo "Phase $PHASE_NUMBER does not exist. Valid: 1..$TOTAL"
70
+ exit 1
71
+ fi
72
+
73
+ # Cannot remove past phases (preserves history)
74
+ if [ "$PHASE_NUMBER" -lt "$CURRENT" ]; then
75
+ echo "Cannot remove phase $PHASE_NUMBER — already past. current_phase is $CURRENT. Past phases are immutable history."
76
+ exit 1
77
+ fi
78
+
79
+ # Cannot remove the current phase
80
+ if [ "$PHASE_NUMBER" -eq "$CURRENT" ]; then
81
+ echo "Cannot remove the current phase ($CURRENT). Ship or abandon it first, then advance current_phase."
82
+ exit 1
83
+ fi
84
+ ```
85
+
86
+ Read the phase's `Status:` from ROADMAP:
87
+
88
+ ```bash
89
+ STATUS=$(awk "/### Phase $PHASE_NUMBER:/,/^### Phase /" .jdi/ROADMAP.md | grep -oE 'Status:\*\* (pending|ready|done|partial|blocked|in-progress)' | head -1 | awk '{print $2}')
90
+ ```
91
+
92
+ If `STATUS == done`: refuse hard.
93
+ ```
94
+ Phase $PHASE_NUMBER is `done`. Cannot remove. Shipped phases are immutable history.
95
+ ```
96
+
97
+ ### Step 4: Detect artifacts
98
+
99
+ Find the phase folder under `.jdi/phases/`:
100
+
101
+ ```bash
102
+ NN=$(printf '%02d' "$PHASE_NUMBER")
103
+ PHASE_DIR=$(ls -d .jdi/phases/${NN}-*/ 2>/dev/null | head -1 || true)
104
+ ```
105
+
106
+ PowerShell:
107
+ ```powershell
108
+ $nn = '{0:D2}' -f $phaseNumber
109
+ $phaseDir = Get-ChildItem .jdi/phases/ -Directory -Filter "$nn-*" -ErrorAction SilentlyContinue | Select-Object -First 1
110
+ ```
111
+
112
+ If `PHASE_DIR` exists AND `--force` NOT passed: refuse.
113
+ ```
114
+ Phase $PHASE_NUMBER has artifacts in $PHASE_DIR (CONTEXT/PLAN/SUMMARY/REVIEW).
115
+ Re-run with --force to archive these artifacts to .jdi/archive/removed-<NN-slug>/ and proceed.
116
+ ```
117
+
118
+ ### Step 5: Confirm with user (irreversible-ish action)
119
+
120
+ AskUserQuestion (always run, even with --force):
121
+
122
+ > "Remove phase $PHASE_NUMBER: '$PHASE_NAME'?
123
+ >
124
+ > Status: $STATUS
125
+ > Artifacts: ${PHASE_DIR:-none}
126
+ > Action: ROADMAP section removed, total_phases decremented, artifacts (if any) moved to .jdi/archive/removed-<NN-slug>/."
127
+ >
128
+ > Options:
129
+ > - [Yes, remove]
130
+ > - [Cancel]
131
+
132
+ If "Cancel" -> exit clean.
133
+
134
+ ### Step 6: Archive artifacts (if any)
135
+
136
+ ```bash
137
+ if [ -n "$PHASE_DIR" ]; then
138
+ mkdir -p .jdi/archive
139
+ test -f .jdi/archive/index.md || echo "# Archive index" > .jdi/archive/index.md
140
+
141
+ BASENAME=$(basename "$PHASE_DIR")
142
+ TARGET=".jdi/archive/removed-$BASENAME"
143
+ mv "$PHASE_DIR" "$TARGET"
144
+ echo "- removed-$BASENAME (removed $(date -u +%F) via /jdi-remove-phase)" >> .jdi/archive/index.md
145
+ fi
146
+ ```
147
+
148
+ PowerShell:
149
+ ```powershell
150
+ if ($phaseDir) {
151
+ if (-not (Test-Path .jdi/archive)) { New-Item -ItemType Directory .jdi/archive | Out-Null }
152
+ if (-not (Test-Path .jdi/archive/index.md)) { Set-Content .jdi/archive/index.md "# Archive index" }
153
+ $basename = $phaseDir.Name
154
+ $target = ".jdi/archive/removed-$basename"
155
+ Move-Item $phaseDir.FullName $target
156
+ Add-Content .jdi/archive/index.md "- removed-$basename (removed $(Get-Date -Format 'yyyy-MM-dd') via /jdi-remove-phase)"
157
+ }
158
+ ```
159
+
160
+ ### Step 7: Edit ROADMAP.md
161
+
162
+ Remove the entire `### Phase $PHASE_NUMBER: ...` block (header + bullets) up to (but not including) the next `### Phase ` line or end of file.
163
+
164
+ Decrement `total_phases`:
165
+ ```
166
+ total_phases: {TOTAL - 1}
167
+ ```
168
+
169
+ **Do NOT renumber** subsequent phases. Phases after the removed one keep their original numbers. This preserves all references in commit history, `DECISIONS.md`, and archived phase folders. The roadmap simply has a gap (e.g., 1, 2, 3, 5, 6 — 4 was removed).
170
+
171
+ ### Step 8: Audit trail in DECISIONS.md
172
+
173
+ Append:
174
+ ```markdown
175
+ D-{N+1} ({date}): Phase $PHASE_NUMBER removed via /jdi-remove-phase. Artifacts: ${PHASE_DIR:+archived to .jdi/archive/removed-<NN-slug>/}{none if empty}.
176
+ ```
177
+
178
+ ### Step 9: Commit
179
+
180
+ ```bash
181
+ git add .jdi/ROADMAP.md .jdi/DECISIONS.md .jdi/archive/ 2>/dev/null
182
+ git commit -m "chore(jdi): remove phase {PHASE_NUMBER}"
183
+ ```
184
+
185
+ ### Step 10: Confirm
186
+
187
+ ```
188
+ Phase {PHASE_NUMBER} removed.
189
+ {if artifacts:} Artifacts archived: .jdi/archive/removed-{NN-slug}/
190
+ total_phases: {TOTAL - 1}
191
+
192
+ Note: phase numbers are not renumbered — references in commits, DECISIONS, and archive remain valid.
193
+ ```
194
+
195
+ </process>
196
+
197
+ <gates>
198
+ - pre: `.jdi/ROADMAP.md` + `.jdi/STATE.md` exist
199
+ - pre: `phase_number` is in range `1..total_phases`
200
+ - pre: `phase_number > current_phase`
201
+ - pre: phase status != `done`
202
+ - pre: `--force` provided when phase has artifacts
203
+ - post: ROADMAP.md section removed + total_phases decremented + artifacts archived (if any) + DECISIONS.md appended + atomic commit
204
+ </gates>
205
+
206
+ <errors>
207
+ - `.jdi/` missing -> "Run /jdi-new first"
208
+ - `phase_number` missing -> usage hint
209
+ - `phase_number` out of range -> "Valid: 1..{total}"
210
+ - `phase_number < current_phase` -> refuse (past = history)
211
+ - `phase_number == current_phase` -> refuse (ship or abandon first)
212
+ - phase status `done` -> refuse (shipped = history)
213
+ - artifacts exist + no `--force` -> refuse + suggest `--force`
214
+ - user cancels at AskUserQuestion -> exit clean
215
+ </errors>
216
+
217
+ <runtime_notes>
218
+
219
+ **Claude Code:**
220
+ - Confirms via AskUserQuestion.
221
+
222
+ **Copilot:**
223
+ - AskUserQuestion not always available — require explicit `--yes` flag as fallback.
224
+
225
+ **OpenCode/Antigravity:**
226
+ - Same interactive confirm as Claude. Fallback to `--yes` when prompts unsupported.
227
+
228
+ </runtime_notes>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jdi-cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "JDI (Just Do It) — lean workflow toolkit for Claude Code, GitHub Copilot, Antigravity, and OpenCode. 10 commands (7 loop + ralph + adopt + meta), 6 core agents + N per-project specialists with file-glob routing. Optional Playwright MCP + Caveman plugin install.",
5
5
  "bin": {
6
6
  "jdi": "bin/jdi.js"
@@ -12,6 +12,10 @@ Este projeto usa **JDI (Just Do It)** como workflow de desenvolvimento. JDI eh u
12
12
  /jdi-do <N> -> executa via doer specialist
13
13
  /jdi-verify <N> -> gates via reviewer specialist
14
14
  /jdi-ship <N> -> finaliza phase
15
+
16
+ # Roadmap mutation (qualquer hora)
17
+ /jdi-add-phase "<name>" [--goal "<t>"] [--at <pos>] -> adiciona phase
18
+ /jdi-remove-phase <N> [--force] -> remove future/pending phase
15
19
  ```
16
20
 
17
21
  `/jdi-create [desc]` cria agents/skills no `core/` (so dentro do repo JDI).
@@ -0,0 +1,171 @@
1
+ ---
2
+ name: jdi-add-phase
3
+ description: Adds a new phase to ROADMAP.md. Append at end (default) or insert at a specific position. Bumps total_phases. Atomic commit.
4
+ argument_hint: "\"<phase name>\" [--goal \"<goal>\"] [--at <position>]"
5
+ runtime_intent:
6
+ invokes_agent: none
7
+ runtime_overrides:
8
+ claude:
9
+ allowed-tools: [Read, Write, Edit, Bash, Grep, Glob, AskUserQuestion]
10
+ copilot:
11
+ tools: [read, write, edit, grep, glob, terminal]
12
+ opencode:
13
+ subtask: true
14
+ antigravity:
15
+ triggers:
16
+ - "/jdi-add-phase"
17
+ - "add new phase"
18
+ - "create phase"
19
+ ---
20
+
21
+ <objective>
22
+ Adds a new phase to the project's roadmap. Edits `.jdi/ROADMAP.md`. Does not start the phase — only registers it. The user advances via `/jdi-discuss <N>` when ready.
23
+ </objective>
24
+
25
+ <arguments>
26
+ - `name` (required) — short phase name. Quote if it contains spaces.
27
+ - `--goal "<text>"` (optional) — 1-line description of what the phase delivers. If missing, AskUserQuestion will prompt.
28
+ - `--at <position>` (optional) — insert at this position instead of appending. Existing phases at and after `<position>` shift down by 1 (renumbered in ROADMAP only — slugs stay the same in any existing `.jdi/phases/` folders). Default: append.
29
+
30
+ Examples:
31
+ - `/jdi-add-phase "User authentication" --goal "Login + signup + JWT"`
32
+ - `/jdi-add-phase "Performance pass" --at 3`
33
+ - `/jdi-add-phase "Hotfix N+1 query"`
34
+ </arguments>
35
+
36
+ <process>
37
+
38
+ ### Step 1: Validation
39
+ ```bash
40
+ test -d .jdi/ || { echo "Not a JDI project. /jdi-new first."; exit 1; }
41
+ test -f .jdi/ROADMAP.md || { echo "ROADMAP.md missing."; exit 1; }
42
+ test -f .jdi/STATE.md || { echo "STATE.md missing."; exit 1; }
43
+ ```
44
+
45
+ If `<name>` argument missing: AskUserQuestion "Phase name?" (free text). Required.
46
+
47
+ If `--goal` flag missing: AskUserQuestion "Phase goal (1 line)?" (free text). Required.
48
+
49
+ ### Step 2: Compute phase number + slug
50
+
51
+ Read `total_phases` from `.jdi/ROADMAP.md`:
52
+
53
+ ```bash
54
+ TOTAL=$(grep -oE 'total_phases:\s*[0-9]+' .jdi/ROADMAP.md | grep -oE '[0-9]+')
55
+ ```
56
+
57
+ PowerShell:
58
+ ```powershell
59
+ $total = (Select-String -Path .jdi/ROADMAP.md -Pattern 'total_phases:\s*([0-9]+)').Matches[0].Groups[1].Value -as [int]
60
+ ```
61
+
62
+ If `--at <pos>` provided, validate `1 <= pos <= total + 1`. Otherwise `pos = total + 1` (append).
63
+
64
+ If `pos <= current_phase` (read from STATE.md), abort with error: "Cannot insert before current phase {current}. Use --at {current+1} or higher."
65
+
66
+ Generate `slug` from `name`:
67
+ - Lowercase
68
+ - Replace accents (à → a, é → e, ç → c, ñ → n)
69
+ - Non-alphanumeric → `-`
70
+ - Collapse repeated `-`, strip leading/trailing `-`
71
+ - Truncate to 40 chars
72
+
73
+ Phase identifier prefix is the 2-digit position (`NN`): `01`, `02`, ..., zero-padded.
74
+
75
+ ### Step 3: Renumber prefix on shift (only if --at)
76
+
77
+ If `--at <pos>` shifts existing phases:
78
+
79
+ Edit `.jdi/ROADMAP.md` — for every existing `### Phase K:` where `K >= pos`, change to `### Phase K+1:` and bump its `**Slug:**` prefix from `KK-...` to `(K+1)(K+1)-...`.
80
+
81
+ **WARNING (printed):**
82
+ > "Renumbering ROADMAP phases. Any existing `.jdi/phases/<NN-slug>/` folders are NOT renamed — they keep their original slugs and become "history". New work in renumbered phases creates new folders. Commits referencing old `phase {K}` remain valid as history."
83
+
84
+ This is intentional. Do not rename `.jdi/phases/` folders — would break commit history and cross-references in DECISIONS.md.
85
+
86
+ If `--at` not provided (append), skip Step 3.
87
+
88
+ ### Step 4: Append phase section to ROADMAP.md
89
+
90
+ If appending (`pos == total + 1`), append at the bottom of `## Phases`:
91
+
92
+ ```markdown
93
+
94
+ ### Phase {pos}: {name}
95
+ - **Slug:** {NN}-{slug}
96
+ - **Status:** pending
97
+ - **Goal:** {goal}
98
+ ```
99
+
100
+ If inserting (`pos <= total`), insert the new section BEFORE the section that previously had number `pos` (now renumbered to `pos+1`).
101
+
102
+ ### Step 5: Bump total_phases
103
+
104
+ Edit `.jdi/ROADMAP.md`:
105
+ ```
106
+ total_phases: {TOTAL + 1}
107
+ ```
108
+
109
+ ### Step 6: Audit trail in DECISIONS.md (optional, only if user passes --reason)
110
+
111
+ Not required. If user wants to record why this phase was added mid-project, they pass `--reason "<text>"`. When present, append to `.jdi/DECISIONS.md`:
112
+
113
+ ```markdown
114
+ D-{N+1} ({date}, phase {pos}): Phase added mid-project. Reason: {reason}
115
+ ```
116
+
117
+ (N = current max D-X.)
118
+
119
+ ### Step 7: Commit
120
+
121
+ ```bash
122
+ git add .jdi/ROADMAP.md .jdi/DECISIONS.md 2>/dev/null
123
+ git commit -m "chore(jdi): add phase {pos} {NN-slug}"
124
+ ```
125
+
126
+ PowerShell:
127
+ ```powershell
128
+ git add .jdi/ROADMAP.md .jdi/DECISIONS.md 2>$null
129
+ git commit -m "chore(jdi): add phase $pos $NN-$slug"
130
+ ```
131
+
132
+ ### Step 8: Confirm
133
+
134
+ ```
135
+ Phase {pos}: {name} added.
136
+ Slug: {NN}-{slug}
137
+ Goal: {goal}
138
+ Status: pending
139
+ total_phases: {TOTAL + 1}
140
+
141
+ Next: /jdi-discuss {pos} (when ready to start this phase)
142
+ ```
143
+
144
+ </process>
145
+
146
+ <gates>
147
+ - pre: `.jdi/ROADMAP.md` + `.jdi/STATE.md` exist
148
+ - pre: `--at <pos>` (if used) is greater than `current_phase` in STATE.md
149
+ - post: ROADMAP.md has new phase section + bumped total_phases + atomic commit
150
+ </gates>
151
+
152
+ <errors>
153
+ - `.jdi/` missing -> "Run /jdi-new first"
154
+ - `--at <pos>` <= current_phase -> "Cannot insert before current phase. Use --at {current+1} or higher."
155
+ - `--at <pos>` < 1 or > total+1 -> "Position out of range. Valid: 1..{total+1}"
156
+ - Phase name empty -> AskUserQuestion to fill
157
+ - Goal empty -> AskUserQuestion to fill
158
+ </errors>
159
+
160
+ <runtime_notes>
161
+
162
+ **Claude Code:**
163
+ - AskUserQuestion handles missing args interactively.
164
+
165
+ **Copilot:**
166
+ - AskUserQuestion not always available — read missing args from prompt body or fail with clear error.
167
+
168
+ **OpenCode/Antigravity:**
169
+ - Same interactive flow as Claude when supported. Otherwise fail with clear error message asking the user to re-invoke with all args.
170
+
171
+ </runtime_notes>