@@ -158,6 +158,10 @@ Loop over ALL ready units from the DAG (not just one):
158158``` bash
159159source " ${CLAUDE_PLUGIN_ROOT} /lib/dag.sh"
160160READY_UNITS=$( find_ready_units " $INTENT_DIR " )
161+
162+ # Determine first construction hat (skip "elaborator" if present)
163+ WORKFLOW_HATS=$( echo " $STATE " | han parse json workflow)
164+ FIRST_HAT=$( echo " $WORKFLOW_HATS " | jq -r ' [.[] | select(. != "elaborator")][0]' )
161165```
162166
163167For EACH ready unit:
@@ -184,31 +188,59 @@ update_unit_status "$UNIT_FILE" "in_progress"
1841883 . ** Initialize unit state in ` unitStates ` ** :
185189
186190``` bash
187- STATE=$( echo " $STATE " | han parse json --set " unitStates.${UNIT_NAME} .hat=planner " --set " unitStates.${UNIT_NAME} .retries=0" )
191+ STATE=$( echo " $STATE " | han parse json --set " unitStates.${UNIT_NAME} .hat=${FIRST_HAT} " --set " unitStates.${UNIT_NAME} .retries=0" )
188192han keep save iteration.json " $STATE "
189193```
190194
191- 4 . ** Create shared task via TaskCreate** :
195+ 4 . ** Load hat instructions for the first hat** :
196+
197+ ``` bash
198+ # Load hat instructions for the teammate's role
199+ HAT_NAME=" ${FIRST_HAT} "
200+ HAT_FILE=" "
201+ if [ -f " .ai-dlc/hats/${HAT_NAME} .md" ]; then
202+ HAT_FILE=" .ai-dlc/hats/${HAT_NAME} .md"
203+ elif [ -n " $CLAUDE_PLUGIN_ROOT " ] && [ -f " ${CLAUDE_PLUGIN_ROOT} /hats/${HAT_NAME} .md" ]; then
204+ HAT_FILE=" ${CLAUDE_PLUGIN_ROOT} /hats/${HAT_NAME} .md"
205+ fi
206+
207+ # Extract instructions (content after second --- in frontmatter)
208+ HAT_INSTRUCTIONS=" "
209+ if [ -n " $HAT_FILE " ]; then
210+ HAT_INSTRUCTIONS=$( sed ' 1,/^---$/d' " $HAT_FILE " | sed ' 1,/^---$/d' )
211+ fi
212+ ```
213+
214+ 5 . ** Select agent type based on hat** :
215+
216+ - ` planner ` -> ` Plan ` agent
217+ - ` builder ` -> discipline-specific agent (see builder agent selection table below)
218+ - All other hats (` reviewer ` , ` red-team ` , ` blue-team ` , etc.) -> ` general-purpose ` agent
219+
220+ 6 . ** Create shared task via TaskCreate** :
192221
193222``` javascript
194223TaskCreate ({
195- subject: ` Plan : ${ unitName} ` ,
196- description: ` Execute planner role for unit ${ unitName} . Worktree: ${ WORKTREE_PATH } ` ,
197- activeForm: ` Planning ${ unitName} `
224+ subject: ` ${ FIRST_HAT } : ${ unitName} ` ,
225+ description: ` Execute ${ FIRST_HAT } role for unit ${ unitName} . Worktree: ${ WORKTREE_PATH } ` ,
226+ activeForm: ` ${ FIRST_HAT } : ${ unitName} `
198227})
199228```
200229
201- 5 . ** Spawn teammate** :
230+ 7 . ** Spawn teammate with hat instructions in prompt ** :
202231
203232``` javascript
204233Task ({
205- subagent_type: " Plan " , // planner hat starts as Plan agent
206- description: ` planner : ${ unitName} ` ,
207- name: ` planner -${ unitSlug} ` ,
234+ subagent_type: getAgentTypeForHat ( FIRST_HAT , unit . discipline ),
235+ description: ` ${ FIRST_HAT } : ${ unitName} ` ,
236+ name: ` ${ FIRST_HAT } -${ unitSlug} ` ,
208237 team_name: ` ai-dlc-${ intentSlug} ` ,
209238 mode: modeToAgentTeamsMode (intentMode),
210239 prompt: `
211- Execute the planner role for this AI-DLC unit.
240+ Execute the ${ FIRST_HAT } role for unit ${ unitName} .
241+
242+ ## Your Role: ${ FIRST_HAT }
243+ ${ HAT_INSTRUCTIONS }
212244
213245 ## CRITICAL: Work in Worktree
214246 **Worktree path:** ${ WORKTREE_PATH }
@@ -241,53 +273,125 @@ Mode mapping:
241273
242274The lead processes auto-delivered teammate messages. Handle each event type:
243275
244- #### Planner Completes
276+ #### Teammate Completes (Any Hat)
245277
246- 1 . Save the plan: ` han keep save current-plan.md "<plan content>" `
247- 2 . Update ` unitStates.{unit}.hat = "builder" `
248- 3 . Spawn builder teammate:
278+ When a teammate reports successful completion:
249279
250- ``` javascript
251- Task ({
252- subagent_type: getAgentForDiscipline (unit .discipline ),
253- description: ` builder: ${ unitName} ` ,
254- name: ` builder-${ unitSlug} ` ,
255- team_name: ` ai-dlc-${ intentSlug} ` ,
256- mode: modeToAgentTeamsMode (intentMode),
257- prompt: ` Execute the builder role for unit ${ unitName} ...`
258- })
280+ 1 . Read current hat for this unit from ` unitStates.{unit}.hat `
281+ 2 . Find current hat's index in the ` workflow ` array
282+ 3 . Determine next hat: ` workflow[currentIndex + 1] `
283+
284+ ** If next hat exists** (not at end of workflow):
285+
286+ a. Update ` unitStates.{unit}.hat = nextHat `
287+ b. Save state: ` han keep save iteration.json "$STATE" `
288+ c. Load hat file for nextHat:
289+
290+ ``` bash
291+ HAT_NAME=" ${nextHat} "
292+ HAT_FILE=" "
293+ if [ -f " .ai-dlc/hats/${HAT_NAME} .md" ]; then
294+ HAT_FILE=" .ai-dlc/hats/${HAT_NAME} .md"
295+ elif [ -n " $CLAUDE_PLUGIN_ROOT " ] && [ -f " ${CLAUDE_PLUGIN_ROOT} /hats/${HAT_NAME} .md" ]; then
296+ HAT_FILE=" ${CLAUDE_PLUGIN_ROOT} /hats/${HAT_NAME} .md"
297+ fi
298+ HAT_INSTRUCTIONS=" "
299+ if [ -n " $HAT_FILE " ]; then
300+ HAT_INSTRUCTIONS=$( sed ' 1,/^---$/d' " $HAT_FILE " | sed ' 1,/^---$/d' )
301+ fi
259302```
260303
261- #### Builder Completes
304+ d. Select agent type based on hat:
305+ - ` planner ` -> ` Plan ` agent
306+ - ` builder ` -> discipline-specific agent (see builder agent selection table below)
307+ - All other hats (` reviewer ` , ` red-team ` , ` blue-team ` , etc.) -> ` general-purpose ` agent
262308
263- 1 . Update ` unitStates.{unit}.hat = "reviewer" `
264- 2 . Spawn reviewer teammate:
309+ e. Spawn teammate with hat instructions in prompt:
265310
266311``` javascript
267312Task ({
268- subagent_type: " general-purpose " ,
269- description: ` reviewer : ${ unitName} ` ,
270- name: ` reviewer -${ unitSlug} ` ,
313+ subagent_type: getAgentTypeForHat (nextHat, unit . discipline ) ,
314+ description: ` ${ nextHat } : ${ unitName} ` ,
315+ name: ` ${ nextHat } -${ unitSlug} ` ,
271316 team_name: ` ai-dlc-${ intentSlug} ` ,
272317 mode: modeToAgentTeamsMode (intentMode),
273- prompt: ` Execute the reviewer role for unit ${ unitName} ...`
318+ prompt: `
319+ Execute the ${ nextHat} role for unit ${ unitName} .
320+
321+ ## Your Role: ${ nextHat}
322+ ${ HAT_INSTRUCTIONS }
323+
324+ ## CRITICAL: Work in Worktree
325+ **Worktree path:** ${ WORKTREE_PATH }
326+ **Branch:** ${ UNIT_BRANCH }
327+
328+ You MUST:
329+ 1. cd ${ WORKTREE_PATH }
330+ 2. Verify you're on branch ${ UNIT_BRANCH }
331+ 3. Do ALL work in that directory
332+ 4. Commit changes to that branch
333+
334+ ## Unit: ${ unitName}
335+ ## Completion Criteria
336+ ${ unit .criteria }
337+
338+ Work according to your role. Report completion via SendMessage to the team lead when done.
339+ `
274340})
275341```
276342
277- #### Reviewer APPROVES
343+ ** If no next hat** (last hat in workflow -- unit complete):
344+
345+ a. Mark unit as completed: ` update_unit_status "$UNIT_FILE" "completed" `
346+ b. Remove unit from ` unitStates `
347+ c. Merge unit branch into intent branch:
348+
349+ ``` bash
350+ # Merge unit branch into intent branch
351+ source " ${CLAUDE_PLUGIN_ROOT} /lib/config.sh"
352+ INTENT_DIR=" .ai-dlc/${INTENT_SLUG} "
353+ CONFIG=$( get_ai_dlc_config " $INTENT_DIR " )
354+ AUTO_MERGE=$( echo " $CONFIG " | jq -r ' .auto_merge // "true"' )
355+ AUTO_SQUASH=$( echo " $CONFIG " | jq -r ' .auto_squash // "false"' )
356+
357+ if [ " $AUTO_MERGE " = " true" ]; then
358+ UNIT_BRANCH=" ai-dlc/${INTENT_SLUG} /${UNIT_SLUG} "
359+ git checkout " ai-dlc/${INTENT_SLUG} "
360+
361+ if [ " $AUTO_SQUASH " = " true" ]; then
362+ git merge --squash " $UNIT_BRANCH "
363+ git commit -m " unit: ${UNIT_NAME} completed"
364+ else
365+ git merge --no-ff " $UNIT_BRANCH " -m " Merge ${UNIT_NAME} into intent branch"
366+ fi
367+
368+ WORKTREE_PATH=" /tmp/ai-dlc-${INTENT_SLUG} -${UNIT_SLUG} "
369+ [ -d " $WORKTREE_PATH " ] && git worktree remove " $WORKTREE_PATH "
370+ fi
371+ ```
372+
373+ d. Check DAG for newly unblocked units
374+ e. For each newly ready unit, spawn at ` workflow[0] ` (first hat, skipping "elaborator" if present -- use the first non-elaborator hat):
375+
376+ ``` bash
377+ FIRST_HAT=$( echo " $WORKFLOW_HATS " | jq -r ' [.[] | select(. != "elaborator")][0]' )
378+ ```
379+
380+ Then follow the same spawn logic from Step 3 (load hat instructions, select agent type, spawn teammate with hat instructions in prompt).
381+
382+ #### Teammate Reports Issues (Any Hat)
278383
279- 1 . Mark unit completed: ` update_unit_status "$UNIT_FILE" "completed" `
280- 2 . Remove unit from ` unitStates `
281- 3 . Check DAG for newly unblocked units
282- 4 . For each newly ready unit, go back to Step 3 logic (spawn at planner hat)
384+ When a teammate reports issues or rejects the work:
283385
284- #### Reviewer REJECTS
386+ 1 . Read current hat index from ` workflow ` array
387+ 2 . Determine previous hat: ` workflow[currentIndex - 1] `
388+ 3 . Increment ` unitStates.{unit}.retries `
389+ 4 . If ` retries >= 3 ` : Mark unit as blocked, document in ` han keep save blockers.md `
390+ 5 . Otherwise: Set ` unitStates.{unit}.hat = previousHat `
391+ 6 . Load hat file for previousHat
392+ 7 . Spawn teammate at previous hat with the feedback/issues in the prompt
285393
286- 1 . Increment ` unitStates.{unit}.retries `
287- 2 . Check retry limit (max 3):
288- - If ` retries >= 3 ` : Mark unit as blocked, document in ` han keep save blockers.md `
289- - If ` retries < 3 ` : Update ` unitStates.{unit}.hat = "builder" ` , spawn new builder teammate with reviewer feedback in prompt
290- 3 . Continue monitoring
394+ This means ANY hat can reject -- not just the reviewer. A red-team finding issues sends work back to the previous hat.
291395
292396#### Blocked
293397
0 commit comments