jdi-cli 0.1.1 → 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.
Files changed (50) hide show
  1. package/README.md +6 -0
  2. package/core/agents/jdi-architect.md +19 -0
  3. package/core/agents/jdi-researcher.md +2 -1
  4. package/core/commands/jdi-add-phase.md +171 -0
  5. package/core/commands/jdi-remove-phase.md +228 -0
  6. package/core/skills/clean-architecture/SKILL.md +134 -0
  7. package/core/skills/ddd/SKILL.md +140 -0
  8. package/core/skills/hexagonal/SKILL.md +127 -0
  9. package/core/skills/onion/SKILL.md +133 -0
  10. package/core/skills/the-method/SKILL.md +139 -0
  11. package/core/skills/vertical-slice/SKILL.md +127 -0
  12. package/package.json +1 -1
  13. package/runtimes/antigravity/agents.md +4 -0
  14. package/runtimes/antigravity/skills/clean-architecture/SKILL.md +125 -0
  15. package/runtimes/antigravity/skills/ddd/SKILL.md +131 -0
  16. package/runtimes/antigravity/skills/hexagonal/SKILL.md +118 -0
  17. package/runtimes/antigravity/skills/jdi-add-phase/SKILL.md +171 -0
  18. package/runtimes/antigravity/skills/jdi-architect/SKILL.md +19 -0
  19. package/runtimes/antigravity/skills/jdi-remove-phase/SKILL.md +228 -0
  20. package/runtimes/antigravity/skills/jdi-researcher/SKILL.md +2 -1
  21. package/runtimes/antigravity/skills/onion/SKILL.md +124 -0
  22. package/runtimes/antigravity/skills/the-method/SKILL.md +130 -0
  23. package/runtimes/antigravity/skills/vertical-slice/SKILL.md +118 -0
  24. package/runtimes/claude/CLAUDE.md +4 -0
  25. package/runtimes/claude/agents/jdi-architect.md +19 -0
  26. package/runtimes/claude/agents/jdi-researcher.md +2 -1
  27. package/runtimes/claude/commands/jdi-add-phase.md +171 -0
  28. package/runtimes/claude/commands/jdi-remove-phase.md +228 -0
  29. package/runtimes/claude/skills/clean-architecture/SKILL.md +120 -0
  30. package/runtimes/claude/skills/ddd/SKILL.md +125 -0
  31. package/runtimes/claude/skills/hexagonal/SKILL.md +112 -0
  32. package/runtimes/claude/skills/onion/SKILL.md +119 -0
  33. package/runtimes/claude/skills/the-method/SKILL.md +124 -0
  34. package/runtimes/claude/skills/vertical-slice/SKILL.md +113 -0
  35. package/runtimes/copilot/agents/jdi-architect.agent.md +19 -0
  36. package/runtimes/copilot/agents/jdi-researcher.agent.md +2 -1
  37. package/runtimes/copilot/copilot-instructions.md +4 -0
  38. package/runtimes/copilot/prompts/jdi-add-phase.prompt.md +171 -0
  39. package/runtimes/copilot/prompts/jdi-remove-phase.prompt.md +228 -0
  40. package/runtimes/opencode/AGENTS.md +4 -0
  41. package/runtimes/opencode/agents/jdi-architect.md +19 -0
  42. package/runtimes/opencode/agents/jdi-researcher.md +2 -1
  43. package/runtimes/opencode/commands/jdi-add-phase.md +171 -0
  44. package/runtimes/opencode/commands/jdi-remove-phase.md +228 -0
  45. package/runtimes/opencode/skills/clean-architecture/SKILL.md +120 -0
  46. package/runtimes/opencode/skills/ddd/SKILL.md +125 -0
  47. package/runtimes/opencode/skills/hexagonal/SKILL.md +112 -0
  48. package/runtimes/opencode/skills/onion/SKILL.md +119 -0
  49. package/runtimes/opencode/skills/the-method/SKILL.md +124 -0
  50. package/runtimes/opencode/skills/vertical-slice/SKILL.md +113 -0
@@ -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>
@@ -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 genericos no `core/` (so dentro do repo JDI).
@@ -378,13 +378,29 @@ Write to `.jdi/agents/jdi-reviewer-{slug}.md`.
378
378
 
379
379
  After writing doer/reviewer, inject `<skills_to_load>` block after `</role>` via Edit.
380
380
 
381
+ **Code-design skill (mandatory) — resolve from `PROJECT.md.Code Design` (LOCKED value) using this mapping:**
382
+
383
+ | Code Design (PROJECT.md) | Skill to load |
384
+ |---|---|
385
+ | The Method | `the-method` |
386
+ | DDD | `ddd` |
387
+ | Clean Architecture | `clean-architecture` |
388
+ | Hexagonal | `hexagonal` |
389
+ | Onion | `onion` |
390
+ | Vertical Slice | `vertical-slice` |
391
+
392
+ The resolved code-design skill is loaded by **both doer and reviewer**. Exactly one code-design skill is loaded. Never load two code-design skills simultaneously — the project uses exactly one design. If the mapping cannot resolve, abort with an error and ask the user to fix `PROJECT.md.Code Design`.
393
+
381
394
  **Doer — always:**
382
395
  ```markdown
383
396
  <skills_to_load>
384
397
  - solid — before creating classes/modules/interfaces. Detects god class, large switches, deep inheritance, dep on concretes.
398
+ - {CODE_DESIGN_SKILL} — INVIOLABLE structural rules for the project's locked code design. Apply on every file created.
385
399
  </skills_to_load>
386
400
  ```
387
401
 
402
+ Replace `{CODE_DESIGN_SKILL}` with the resolved entry from the mapping above (e.g. `the-method`, `ddd`, `clean-architecture`, `hexagonal`, `onion`, `vertical-slice`).
403
+
388
404
  If `has_frontend=true`, append:
389
405
  ```markdown
390
406
  - frontend-rules — when task touches .tsx/.vue/.svelte/.razor/.cshtml/.html/.twig/.erb/.blade.php. WCAG 2.2 AA + UX.
@@ -397,9 +413,12 @@ If `has_frontend=true`, append:
397
413
  - kiss — gate 5: over-engineering — interface with 1 impl, factory for new(), pass-through, deep inheritance.
398
414
  - yagni — gate 5: speculative code — optional params never passed, TODO without ticket, generic with 1 type.
399
415
  - clean-code — bad names, long functions, magic numbers, silent catch, boolean params, redundant comments.
416
+ - {CODE_DESIGN_SKILL} — gate 5: enforce INVIOLABLE structural rules for the project's locked code design. BLOCKED on violations defined by the skill.
400
417
  </skills_to_load>
401
418
  ```
402
419
 
420
+ Replace `{CODE_DESIGN_SKILL}` with the same resolved entry — both doer and reviewer load the SAME code-design skill.
421
+
403
422
  If `has_frontend=true`, append:
404
423
  ```markdown
405
424
  - frontend-rules — gate 5 frontend: <input> without label, button without aria-label, localStorage with token, outline removed.
@@ -60,10 +60,11 @@ Options:
60
60
  - Vertical Slice
61
61
  - Clean Architecture
62
62
  - Hexagonal (Ports & Adapters)
63
+ - Onion Architecture
63
64
  - The Method (Juval Löwy)
64
65
  - "Don't know, suggest" (-> recommend based on type + stack)
65
66
 
66
- Locked for the life of the project (global rule).
67
+ Locked for the life of the project (global rule). Mutually exclusive — the project uses exactly ONE code design. The choice is enforced by a JDI skill loaded into doer + reviewer (one of: `ddd`, `vertical-slice`, `clean-architecture`, `hexagonal`, `onion`, `the-method`).
67
68
 
68
69
  **Q4 — MVP scope**
69
70
  "Which minimum features for the MVP? (comma-separated)"
@@ -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>