Skip to content

Commit 68340c4

Browse files
jwaldripclaude
andcommitted
fix: remove elaborator from construction workflows and improve intent discovery
Elaboration is a separate pre-construction phase (/elaborate), not a construction hat. Including it in workflows forced construct to work around it everywhere. This removes the elaborator hat from all workflow definitions, fallback defaults, and construction logic. Also improves: - Elaborate Phase 0 skips completed/in-progress intents (only pending intents can be re-elaborated) - Construct discovers intents from both filesystem AND ai-dlc/* branches (not just current directory) - Workflow selection uses preflight display + AI recommendation before user decides, with support for custom hat compositions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent c7930fe commit 68340c4

File tree

9 files changed

+118
-48
lines changed

9 files changed

+118
-48
lines changed

plugin/hooks/inject-context.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ fi
284284

285285
# Parse iteration state using han parse (no jq needed)
286286
ITERATION=$(echo "$ITERATION_JSON" | han parse json iteration -r --default 1)
287-
HAT=$(echo "$ITERATION_JSON" | han parse json hat -r --default elaborator)
287+
HAT=$(echo "$ITERATION_JSON" | han parse json hat -r --default planner)
288288
STATUS=$(echo "$ITERATION_JSON" | han parse json status -r --default active)
289289
WORKFLOW_NAME=$(echo "$ITERATION_JSON" | han parse json workflowName -r --default default)
290290

@@ -295,10 +295,10 @@ if ! echo "$KNOWN_WORKFLOWS" | grep -qw "$WORKFLOW_NAME"; then
295295
fi
296296

297297
# Get workflow hats array as string
298-
WORKFLOW_HATS=$(echo "$ITERATION_JSON" | han parse json workflow 2>/dev/null || echo '["elaborator","planner","builder","reviewer"]')
298+
WORKFLOW_HATS=$(echo "$ITERATION_JSON" | han parse json workflow 2>/dev/null || echo '["planner","builder","reviewer"]')
299299
# Format as arrow-separated list
300300
WORKFLOW_HATS_STR=$(echo "$WORKFLOW_HATS" | tr -d '[]"' | sed 's/,/ → /g')
301-
[ -z "$WORKFLOW_HATS_STR" ] && WORKFLOW_HATS_STR="elaborator → planner → builder → reviewer"
301+
[ -z "$WORKFLOW_HATS_STR" ] && WORKFLOW_HATS_STR="planner → builder → reviewer"
302302

303303
# If task is complete, just show completion message
304304
if [ "$STATUS" = "complete" ]; then

plugin/hooks/subagent-context.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ if [ "$STATUS" = "complete" ] || [ -z "$HAT" ]; then
4848
fi
4949

5050
# Get workflow hats array as string
51-
WORKFLOW_HATS=$(echo "$ITERATION_JSON" | han parse json workflow 2>/dev/null || echo '["elaborator","planner","builder","reviewer"]')
51+
WORKFLOW_HATS=$(echo "$ITERATION_JSON" | han parse json workflow 2>/dev/null || echo '["planner","builder","reviewer"]')
5252
WORKFLOW_HATS_STR=$(echo "$WORKFLOW_HATS" | tr -d '[]"' | sed 's/,/ → /g')
53-
[ -z "$WORKFLOW_HATS_STR" ] && WORKFLOW_HATS_STR="elaborator → planner → builder → reviewer"
53+
[ -z "$WORKFLOW_HATS_STR" ] && WORKFLOW_HATS_STR="planner → builder → reviewer"
5454

5555
# Get intent-slug from han keep (pointer only, not content)
5656
load_keep_value() {

plugin/lib/dag.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ is_dag_complete() {
433433

434434
# Determine recommended starting hat based on unit states
435435
# Usage: get_recommended_hat <intent_dir> [workflow_name]
436-
# Returns: hat name (elaborator, planner, builder, reviewer, etc.)
436+
# Returns: hat name (planner, builder, reviewer, etc.)
437437
get_recommended_hat() {
438438
local intent_dir="$1"
439439
local workflow_name="${2:-default}"
@@ -444,7 +444,7 @@ get_recommended_hat() {
444444
hats=$(han parse yaml "${workflow_name}.hats" < "$hats_file" 2>/dev/null | sed 's/^- //' | tr '\n' ' ')
445445

446446
# Default hats if parse fails
447-
[ -z "$hats" ] && hats="elaborator planner builder reviewer"
447+
[ -z "$hats" ] && hats="planner builder reviewer"
448448

449449
# Convert to array
450450
read -ra hat_array <<< "$hats"

plugin/skills/advance/SKILL.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ user-invocable: false
1818
**Internal command** - Called by the AI during `/construct`, not directly by users.
1919

2020
Advances to the next hat in the workflow sequence. For example, in the default workflow:
21-
- elaborator -> planner (intent defined, now plan the work)
2221
- planner -> builder (plan ready, now implement)
2322
- builder -> reviewer (bolt complete, now review)
2423

@@ -39,7 +38,7 @@ STATE=$(han keep load iteration.json --quiet)
3938
### Step 2: Determine Next Hat (or Handle Completion)
4039

4140
```javascript
42-
const workflow = state.workflow || ["elaborator", "planner", "builder", "reviewer"];
41+
const workflow = state.workflow || ["planner", "builder", "reviewer"];
4342
const currentIndex = workflow.indexOf(state.hat);
4443
const nextIndex = currentIndex + 1;
4544

plugin/skills/ai-dlc-fundamentals/SKILL.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,13 +144,14 @@ Different phases of work require different mindsets. AI-DLC uses "hats" to forma
144144

145145
### Default Workflow
146146

147+
Elaboration (`/elaborate`) is a separate pre-construction phase. The construction workflow starts after elaboration is complete:
148+
147149
```
148-
elaborator → planner → builder → reviewer
150+
planner → builder → reviewer
149151
```
150152

151153
| Hat | Focus | Mode |
152154
|-----|-------|------|
153-
| Elaborator | Define intent and criteria | HITL |
154155
| Planner | Plan this iteration | HITL |
155156
| Builder | Implement to spec | OHOTL |
156157
| Reviewer | Verify quality | HITL |

plugin/skills/construct/SKILL.md

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -65,33 +65,64 @@ If truly blocked (cannot proceed without user input):
6565

6666
**CRITICAL: The orchestrator MUST run in the intent worktree, not the main working directory.**
6767

68-
Before loading state, find and switch to the intent worktree:
68+
Before loading state, discover all active intents from both the filesystem and `ai-dlc/*` branches:
6969

7070
```bash
71-
# First, check if we have an intent slug saved (try to find it)
72-
# Look for .ai-dlc/*/intent.md files to detect intent
73-
INTENT_SLUG=""
71+
# Source DAG library for branch discovery
72+
source "${CLAUDE_PLUGIN_ROOT}/lib/dag.sh"
73+
74+
declare -A ACTIVE_INTENTS # slug -> "source" (filesystem|worktree|local)
75+
76+
# 1. Check filesystem (current directory)
7477
for intent_file in .ai-dlc/*/intent.md; do
7578
[ -f "$intent_file" ] || continue
7679
dir=$(dirname "$intent_file")
7780
slug=$(basename "$dir")
78-
status=$(han parse yaml status -r --default active < "$intent_file" 2>/dev/null || echo "active")
79-
[ "$status" = "active" ] && INTENT_SLUG="$slug" && break
81+
status=$(_yaml_get_simple "status" "active" < "$intent_file")
82+
[ "$status" = "active" ] && ACTIVE_INTENTS[$slug]="filesystem"
8083
done
8184

82-
# If we found an intent, ensure we're in its worktree
83-
if [ -n "$INTENT_SLUG" ]; then
84-
INTENT_BRANCH="ai-dlc/${INTENT_SLUG}"
85-
INTENT_WORKTREE="/tmp/ai-dlc-${INTENT_SLUG}"
85+
# 2. Check ai-dlc/* branches (worktrees and local branches)
86+
while IFS='|' read -r slug workflow source branch; do
87+
[ -z "$slug" ] && continue
88+
# Don't overwrite filesystem entries (they take display priority)
89+
[ -z "${ACTIVE_INTENTS[$slug]}" ] && ACTIVE_INTENTS[$slug]="$source"
90+
done < <(discover_branch_intents false)
91+
92+
# 3. Handle results
93+
if [ ${#ACTIVE_INTENTS[@]} -eq 0 ]; then
94+
echo "No active AI-DLC intent found."
95+
echo ""
96+
echo "Run /elaborate to start a new task, or /resume <slug> if you know the intent slug."
97+
exit 0
98+
fi
8699

87-
# Create worktree if it doesn't exist
88-
if [ ! -d "$INTENT_WORKTREE" ]; then
89-
git worktree add -B "$INTENT_BRANCH" "$INTENT_WORKTREE"
90-
fi
100+
if [ ${#ACTIVE_INTENTS[@]} -eq 1 ]; then
101+
# Single intent — use it
102+
INTENT_SLUG="${!ACTIVE_INTENTS[@]}"
103+
elif [ ${#ACTIVE_INTENTS[@]} -gt 1 ]; then
104+
# Multiple intents — ask the user which one to construct
105+
echo "Multiple active intents found:"
106+
echo ""
107+
for slug in "${!ACTIVE_INTENTS[@]}"; do
108+
echo "- **$slug** (${ACTIVE_INTENTS[$slug]})"
109+
done
110+
echo ""
111+
# Use AskUserQuestion with the discovered intents as options
112+
# (construct will present these dynamically)
113+
echo "Use /construct <slug> to specify which intent to build."
114+
exit 0
115+
fi
91116

92-
# Switch to the intent worktree
93-
cd "$INTENT_WORKTREE"
117+
# Ensure we're in the intent worktree
118+
INTENT_BRANCH="ai-dlc/${INTENT_SLUG}"
119+
INTENT_WORKTREE="/tmp/ai-dlc-${INTENT_SLUG}"
120+
121+
if [ ! -d "$INTENT_WORKTREE" ]; then
122+
git worktree add -B "$INTENT_BRANCH" "$INTENT_WORKTREE"
94123
fi
124+
125+
cd "$INTENT_WORKTREE"
95126
```
96127

97128
**Important:** The orchestrator runs in `/tmp/ai-dlc-{intent-slug}/`, NOT the original repo directory. This keeps main clean and enables parallel intents.
@@ -179,9 +210,9 @@ Loop over ALL ready units from the DAG (not just one):
179210
source "${CLAUDE_PLUGIN_ROOT}/lib/dag.sh"
180211
READY_UNITS=$(find_ready_units "$INTENT_DIR")
181212

182-
# Determine first construction hat (skip "elaborator" if present)
213+
# Determine first construction hat
183214
WORKFLOW_HATS=$(echo "$STATE" | han parse json workflow)
184-
FIRST_HAT=$(echo "$WORKFLOW_HATS" | jq -r '[.[] | select(. != "elaborator")][0]')
215+
FIRST_HAT=$(echo "$WORKFLOW_HATS" | jq -r '.[0]')
185216
```
186217

187218
**Include repo URL for cowork**: If operating in a cloned workspace, include the repo URL in each teammate's prompt: "Repository: `<remote-url>`. Clone and checkout `ai-dlc/<intent-slug>` if you don't have local access." This enables teammates to clone independently in cowork mode.
@@ -420,10 +451,10 @@ fi
420451
```
421452

422453
d. Check DAG for newly unblocked units
423-
e. For each newly ready unit, spawn at `workflow[0]` (first hat, skipping "elaborator" if present -- use the first non-elaborator hat):
454+
e. For each newly ready unit, spawn at `workflow[0]` (first hat):
424455

425456
```bash
426-
FIRST_HAT=$(echo "$WORKFLOW_HATS" | jq -r '[.[] | select(. != "elaborator")][0]')
457+
FIRST_HAT=$(echo "$WORKFLOW_HATS" | jq -r '.[0]')
427458
```
428459

429460
Then follow the same spawn logic from Step 3 (load hat instructions, select agent type, spawn teammate with hat instructions in prompt).
@@ -488,7 +519,7 @@ The `iteration.json` is extended with `unitStates` for parallel hat tracking:
488519
"hat": "builder",
489520
"status": "active",
490521
"workflowName": "default",
491-
"workflow": ["elaborator", "planner", "builder", "reviewer"],
522+
"workflow": ["planner", "builder", "reviewer"],
492523
"teamName": "ai-dlc-my-intent",
493524
"unitStates": {
494525
"unit-01-foundation": { "hat": "reviewer", "retries": 0 },

plugin/skills/elaborate/SKILL.md

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,11 @@ Before any elaboration, verify the working environment:
7272
If the user invoked this with a slug argument:
7373

7474
1. Check if `.ai-dlc/{slug}/intent.md` exists
75-
2. If it exists and no units are completed (all units have `status: pending`):
76-
- **Assume the user wants to modify the existing intent**
75+
2. If it exists, check the intent and unit statuses:
76+
- **Skip if intent status is `complete`**: Tell the user "Intent `{slug}` is already completed. Run `/elaborate` without a slug to start a new intent." Then stop.
77+
- **Skip if ANY unit has status `in_progress` or `completed`**: Construction has already started — elaboration would conflict with in-flight work. Tell the user "Intent `{slug}` already has units in progress or completed. Use `/resume {slug}` to continue construction or `/construct` to resume the build loop." Then stop.
78+
- **Only proceed if ALL units have `status: pending`** (no work has begun yet):
79+
3. If all units are pending — **assume the user wants to modify the existing intent**:
7780
- Read ALL files in `.ai-dlc/{slug}/` directory
7881
- **Display FULL file contents** to the user in markdown code blocks (never summarize or truncate):
7982
```
@@ -107,7 +110,7 @@ If the user invoked this with a slug argument:
107110
}]
108111
}
109112
```
110-
3. Based on their choice:
113+
4. Based on their choice:
111114
- **Modify intent**: Jump to Phase 4 (Success Criteria) with current values pre-filled
112115
- **Modify units**: Jump to Phase 5 (Decompose) with current units shown
113116
- **Start fresh**: Delete `.ai-dlc/{slug}/` and proceed to Phase 1
@@ -308,26 +311,63 @@ cat "${CLAUDE_PLUGIN_ROOT}/workflows.yml"
308311

309312
### Step 3: Select or Compose Workflow
310313

311-
Based on the intent, recommend a workflow from the discovered options. Present available workflows dynamically — do NOT hardcode the options.
314+
This step has three parts: show what's available, make a recommendation, then let the user decide.
312315

313-
Use `AskUserQuestion` with the discovered workflows as options. Include a "Custom" option that lets the user compose their own hat sequence from the available hats:
316+
#### 3a. Preflight — Display Available Options
317+
318+
First, show the user all predefined workflows (from Step 2) and available hats (from Step 1) so they have full visibility before any recommendation:
319+
320+
```markdown
321+
## Available Workflows
322+
323+
{List each predefined workflow with its hat sequence, from Step 2}
324+
325+
## Available Hats
326+
327+
{List each hat with its slug and one-line description, from Step 1}
328+
```
329+
330+
#### 3b. Recommendation — Suggest the Best Fit
331+
332+
Analyze the intent against the available options. Consider:
333+
- What phases does this intent actually need? (Not every intent needs planning — a pure refactor might skip straight to builder.)
334+
- Does the domain suggest specialized hats? (Security-sensitive work benefits from red-team/blue-team. Bug investigations benefit from observer/hypothesizer.)
335+
- Keep it minimal — every hat adds an iteration cycle. Don't add hats "just in case."
336+
337+
Present your recommendation with reasoning:
338+
339+
```markdown
340+
## Recommendation
341+
342+
**{workflow name or "Custom"}**: {hats as arrows}
343+
344+
{1-2 sentences explaining why this fits the intent. Reference specific aspects of what the user described.}
345+
```
346+
347+
The recommendation can be a predefined workflow or a custom composition — whichever best fits. If suggesting a custom sequence, explain what each hat contributes to this specific intent.
348+
349+
#### 3c. User Decides
350+
351+
Use `AskUserQuestion` with the predefined workflows as options. Do NOT hardcode options — use the workflows discovered in Step 2:
314352

315353
```json
316354
{
317355
"questions": [{
318-
"question": "Which workflow fits this task? (or compose a custom one from available hats)",
356+
"question": "Which workflow would you like to use?",
319357
"header": "Workflow",
320358
"options": [
321359
{"label": "{recommended} (Recommended)", "description": "{hats as arrows}"},
322360
{"label": "{workflow2}", "description": "{hats as arrows}"},
323361
{"label": "{workflow3}", "description": "{hats as arrows}"},
324-
{"label": "Custom", "description": "Compose a custom hat sequence from available hats"}
362+
{"label": "Custom", "description": "Tell me which hats to use and in what order"}
325363
],
326364
"multiSelect": false
327365
}]
328366
}
329367
```
330368

369+
If your recommendation is a custom composition, include it as the first option with "(Recommended)". The predefined workflows still appear as alternatives.
370+
331371
If the user selects "Custom", ask them to specify which hats to include and in what order.
332372

333373
---
@@ -770,7 +810,7 @@ Intent-level state is saved to the current branch (which is now the intent branc
770810
han keep save intent-slug "{intent-slug}"
771811

772812
# Intent-level state -> current branch (intent branch)
773-
han keep save iteration.json '{"iteration":1,"hat":"{first-hat-after-elaborator}","workflowName":"{workflow}","mode":"{HITL|OHOTL|AHOTL}","workflow":["{hat1}","{hat2}"],"status":"active"}'
813+
han keep save iteration.json '{"iteration":1,"hat":"{first-hat}","workflowName":"{workflow}","mode":"{HITL|OHOTL|AHOTL}","workflow":["{hat1}","{hat2}"],"status":"active"}'
774814
```
775815

776816
### 5. Commit all artifacts on intent branch:

plugin/skills/fail/SKILL.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,8 @@ user-invocable: false
2020
Goes back to the previous hat in the workflow. Typically used when:
2121
- Reviewer finds issues -> return to builder
2222
- Builder hits fundamental blocker -> return to planner
23-
- Planner realizes requirements unclear -> return to elaborator
2423

25-
If already at the first hat (elaborator by default), this command is blocked.
24+
If already at the first hat (planner by default), this command is blocked.
2625

2726
## Implementation
2827

@@ -36,13 +35,13 @@ STATE=$(han keep load iteration.json --quiet)
3635
### Step 2: Determine Previous Hat
3736

3837
```javascript
39-
const workflow = state.workflow || ["elaborator", "planner", "builder", "reviewer"];
38+
const workflow = state.workflow || ["planner", "builder", "reviewer"];
4039
const currentIndex = workflow.indexOf(state.hat);
4140
const prevIndex = currentIndex - 1;
4241

4342
if (prevIndex < 0) {
4443
// Already at first hat - cannot go back
45-
return "Cannot fail before the first hat (elaborator).";
44+
return "Cannot fail before the first hat (planner).";
4645
}
4746

4847
const prevHat = workflow[prevIndex];
@@ -121,9 +120,9 @@ Continuing construction with the previous hat...
121120

122121
## Guard
123122

124-
If already at the first hat (elaborator by default), output:
123+
If already at the first hat (planner by default), output:
125124
```
126-
You are at the first hat (elaborator).
125+
You are at the first hat (planner).
127126
128-
Cannot go back further. Continue elaboration or use `/reset` to start over.
127+
Cannot go back further. Use `/reset` to start over, or re-elaborate with `/elaborate <slug>`.
129128
```

plugin/workflows.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
default:
1212
description: Standard development workflow
13-
hats: [elaborator, planner, builder, reviewer]
13+
hats: [planner, builder, reviewer]
1414

1515
tdd:
1616
description: Test-Driven Development (Red-Green-Refactor)

0 commit comments

Comments
 (0)