Skip to content

Commit 3f5765d

Browse files
jwaldripclaude
andcommitted
fix: namespace intent branches as ai-dlc/{slug}/main
Git refs cannot be both a leaf node and a directory, so ai-dlc/{slug} as a branch prevents creating unit branches at ai-dlc/{slug}/{unit-slug}. This renames intent branches to ai-dlc/{slug}/main, keeping unit branches at ai-dlc/{slug}/{unit-slug}. Updated branch patterns in all skills, hooks, and dag.sh. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 595e9ca commit 3f5765d

File tree

8 files changed

+41
-37
lines changed

8 files changed

+41
-37
lines changed

plugin/hooks/enforce-iteration.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ ITERATION_JSON=""
3131
ITERATION_JSON=$(han keep load iteration.json --quiet 2>/dev/null || echo "")
3232

3333
# If not found and we're on a unit branch, try the parent intent branch
34-
if [ -z "$ITERATION_JSON" ] && [[ "$CURRENT_BRANCH" == ai-dlc/*/* ]]; then
35-
# Extract intent branch: ai-dlc/intent-slug/unit-slug -> ai-dlc/intent-slug
36-
INTENT_BRANCH=$(echo "$CURRENT_BRANCH" | sed 's|^\(ai-dlc/[^/]*\)/.*|\1|')
34+
if [ -z "$ITERATION_JSON" ] && [[ "$CURRENT_BRANCH" == ai-dlc/*/* ]] && [[ "$CURRENT_BRANCH" != ai-dlc/*/main ]]; then
35+
# Extract intent branch: ai-dlc/intent-slug/unit-slug -> ai-dlc/intent-slug/main
36+
INTENT_BRANCH=$(echo "$CURRENT_BRANCH" | sed 's|^\(ai-dlc/[^/]*\)/.*|\1/main|')
3737
ITERATION_JSON=$(han keep load --branch "$INTENT_BRANCH" iteration.json --quiet 2>/dev/null || echo "")
3838
fi
3939

plugin/hooks/inject-context.sh

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,11 @@ ITERATION_JSON=""
114114
ITERATION_JSON=$(han keep load iteration.json --quiet 2>/dev/null || echo "")
115115

116116
# If not found and we're on a unit branch, try the parent intent branch
117-
if [ -z "$ITERATION_JSON" ] && [[ "$CURRENT_BRANCH" == ai-dlc/*/* ]]; then
118-
# Extract intent branch: ai-dlc/intent-slug/unit-slug -> ai-dlc/intent-slug
119-
INTENT_BRANCH=$(echo "$CURRENT_BRANCH" | sed 's|^\(ai-dlc/[^/]*\)/.*|\1|')
117+
# Unit branches: ai-dlc/{slug}/{unit-slug} (where unit-slug != "main")
118+
# Intent branches: ai-dlc/{slug}/main
119+
if [ -z "$ITERATION_JSON" ] && [[ "$CURRENT_BRANCH" == ai-dlc/*/* ]] && [[ "$CURRENT_BRANCH" != ai-dlc/*/main ]]; then
120+
# Extract intent branch: ai-dlc/intent-slug/unit-slug -> ai-dlc/intent-slug/main
121+
INTENT_BRANCH=$(echo "$CURRENT_BRANCH" | sed 's|^\(ai-dlc/[^/]*\)/.*|\1/main|')
120122
ITERATION_JSON=$(han keep load --branch "$INTENT_BRANCH" iteration.json --quiet 2>/dev/null || echo "")
121123
fi
122124

@@ -582,9 +584,9 @@ echo ""
582584
# Check branch naming convention (informational only)
583585
# Note: CURRENT_BRANCH already cached at top of script
584586
if [ -n "$CURRENT_BRANCH" ] && [ "$CURRENT_BRANCH" != "main" ] && [ "$CURRENT_BRANCH" != "master" ]; then
585-
if ! echo "$CURRENT_BRANCH" | grep -qE '^ai-dlc/[a-z0-9-]+/[0-9]+-[a-z0-9-]+$'; then
587+
if ! echo "$CURRENT_BRANCH" | grep -qE '^ai-dlc/[a-z0-9-]+/(main|[0-9]+-[a-z0-9-]+)$'; then
586588
echo "> **WARNING:** Current branch \`$CURRENT_BRANCH\` doesn't follow AI-DLC convention."
587-
echo "> Expected: \`ai-dlc/{intent-slug}/{unit-number}-{unit-slug}\`"
589+
echo "> Expected: \`ai-dlc/{intent-slug}/main\` or \`ai-dlc/{intent-slug}/{unit-number}-{unit-slug}\`"
588590
echo "> Create correct branch before proceeding."
589591
echo ""
590592
fi

plugin/hooks/subagent-context.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ ITERATION_JSON=""
2525
ITERATION_JSON=$(han keep load iteration.json --quiet 2>/dev/null || echo "")
2626

2727
# If not found and we're on a unit branch, try the parent intent branch
28-
if [ -z "$ITERATION_JSON" ] && [[ "$CURRENT_BRANCH" == ai-dlc/*/* ]]; then
29-
# Extract intent branch: ai-dlc/intent-slug/unit-slug -> ai-dlc/intent-slug
30-
INTENT_BRANCH=$(echo "$CURRENT_BRANCH" | sed 's|^\(ai-dlc/[^/]*\)/.*|\1|')
28+
# Unit branches: ai-dlc/{slug}/{unit-slug} (where unit-slug != "main")
29+
# Intent branches: ai-dlc/{slug}/main
30+
if [ -z "$ITERATION_JSON" ] && [[ "$CURRENT_BRANCH" == ai-dlc/*/* ]] && [[ "$CURRENT_BRANCH" != ai-dlc/*/main ]]; then
31+
# Extract intent branch: ai-dlc/intent-slug/unit-slug -> ai-dlc/intent-slug/main
32+
INTENT_BRANCH=$(echo "$CURRENT_BRANCH" | sed 's|^\(ai-dlc/[^/]*\)/.*|\1/main|')
3133
ITERATION_JSON=$(han keep load --branch "$INTENT_BRANCH" iteration.json --quiet 2>/dev/null || echo "")
3234
fi
3335

plugin/lib/dag.sh

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -564,13 +564,13 @@ discover_branch_intents() {
564564
local seen_slugs=""
565565

566566
# 1. Check existing worktrees (highest priority)
567-
# Parse git worktree list --porcelain to find ai-dlc/* branches
567+
# Parse git worktree list --porcelain to find ai-dlc/*/main branches
568568
while IFS= read -r line; do
569569
if [[ "$line" == "branch refs/heads/ai-dlc/"* ]]; then
570570
local branch="${line#branch refs/heads/}"
571-
# Only intent-level branches (ai-dlc/slug, not ai-dlc/slug/unit)
572-
if [[ "$branch" =~ ^ai-dlc/[^/]+$ ]]; then
573-
local slug="${branch#ai-dlc/}"
571+
# Only intent-level branches (ai-dlc/slug/main)
572+
if [[ "$branch" =~ ^ai-dlc/([^/]+)/main$ ]]; then
573+
local slug="${BASH_REMATCH[1]}"
574574
# Read intent.md from the branch
575575
local intent_content
576576
intent_content=$(git show "$branch:.ai-dlc/$slug/intent.md" 2>/dev/null) || continue
@@ -585,12 +585,12 @@ discover_branch_intents() {
585585
fi
586586
done < <(git worktree list --porcelain 2>/dev/null)
587587

588-
# 2. Check local ai-dlc/* branches (no worktree)
588+
# 2. Check local ai-dlc/*/main branches (no worktree)
589589
while IFS= read -r branch; do
590590
[ -z "$branch" ] && continue
591-
# Only intent-level branches (ai-dlc/slug, not ai-dlc/slug/unit)
592-
[[ "$branch" =~ ^ai-dlc/[^/]+$ ]] || continue
593-
local slug="${branch#ai-dlc/}"
591+
# Only intent-level branches (ai-dlc/slug/main)
592+
[[ "$branch" =~ ^ai-dlc/([^/]+)/main$ ]] || continue
593+
local slug="${BASH_REMATCH[1]}"
594594
# Skip if already seen in worktree
595595
[[ "$seen_slugs" == *" $slug"* ]] && continue
596596
# Read intent.md from the branch
@@ -603,15 +603,15 @@ discover_branch_intents() {
603603
workflow=$(echo "$intent_content" | han parse yaml workflow -r --default default 2>/dev/null || echo "default")
604604
echo "$slug|$workflow|local|$branch"
605605
seen_slugs="$seen_slugs $slug"
606-
done < <(git for-each-ref --format='%(refname:short)' 'refs/heads/ai-dlc/*' 2>/dev/null)
606+
done < <(git for-each-ref --format='%(refname:short)' 'refs/heads/ai-dlc/*/main' 2>/dev/null)
607607

608608
# 3. Check remote branches (only if include_remote=true)
609609
if [ "$include_remote" = "true" ]; then
610610
while IFS= read -r branch; do
611611
[ -z "$branch" ] && continue
612-
# Only intent-level branches
613-
[[ "$branch" =~ ^origin/ai-dlc/[^/]+$ ]] || continue
614-
local slug="${branch#origin/ai-dlc/}"
612+
# Only intent-level branches (origin/ai-dlc/slug/main)
613+
[[ "$branch" =~ ^origin/ai-dlc/([^/]+)/main$ ]] || continue
614+
local slug="${BASH_REMATCH[1]}"
615615
# Skip if already seen
616616
[[ "$seen_slugs" == *" $slug"* ]] && continue
617617
# Read intent.md from the remote branch
@@ -624,6 +624,6 @@ discover_branch_intents() {
624624
workflow=$(echo "$intent_content" | han parse yaml workflow -r --default default 2>/dev/null || echo "default")
625625
echo "$slug|$workflow|remote|$branch"
626626
seen_slugs="$seen_slugs $slug"
627-
done < <(git for-each-ref --format='%(refname:short)' 'refs/remotes/origin/ai-dlc/*' 2>/dev/null)
627+
done < <(git for-each-ref --format='%(refname:short)' 'refs/remotes/origin/ai-dlc/*/main' 2>/dev/null)
628628
fi
629629
}

plugin/skills/advance/SKILL.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ if [ "$AUTO_MERGE" = "true" ]; then
8686
UNIT_BRANCH="ai-dlc/${INTENT_SLUG}/${UNIT_SLUG}"
8787

8888
# Ensure we're on the intent branch
89-
git checkout "ai-dlc/${INTENT_SLUG}"
89+
git checkout "ai-dlc/${INTENT_SLUG}/main"
9090

9191
# Merge unit branch
9292
if [ "$AUTO_SQUASH" = "true" ]; then
@@ -205,15 +205,15 @@ DEFAULT_BRANCH=$(echo "$CONFIG" | jq -r '.default_branch')
205205
```
206206

207207
```
208-
Intent branch ready: ai-dlc/{intent-slug} → ${DEFAULT_BRANCH}
208+
Intent branch ready: ai-dlc/{intent-slug}/main → ${DEFAULT_BRANCH}
209209
210-
Create PR: gh pr create --base ${DEFAULT_BRANCH} --head ai-dlc/{intent-slug}
210+
Create PR: gh pr create --base ${DEFAULT_BRANCH} --head ai-dlc/{intent-slug}/main
211211
```
212212

213213
### Next Steps
214214

215-
1. **Review changes** - Check the work on branch `ai-dlc/{intent-slug}`
216-
2. **Create PR** - `gh pr create --base ${DEFAULT_BRANCH} --head ai-dlc/{intent-slug}`
215+
1. **Review changes** - Check the work on branch `ai-dlc/{intent-slug}/main`
216+
2. **Create PR** - `gh pr create --base ${DEFAULT_BRANCH} --head ai-dlc/{intent-slug}/main`
217217
3. **Clean up worktrees** - `git worktree remove /tmp/ai-dlc-{intent-slug}`
218218
4. **Start new task** - Run `/reset` to clear state, then `/elaborate`
219219
```

plugin/skills/construct/SKILL.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ elif [ ${#ACTIVE_INTENTS[@]} -gt 1 ]; then
115115
fi
116116

117117
# Ensure we're in the intent worktree
118-
INTENT_BRANCH="ai-dlc/${INTENT_SLUG}"
118+
INTENT_BRANCH="ai-dlc/${INTENT_SLUG}/main"
119119
INTENT_WORKTREE="/tmp/ai-dlc-${INTENT_SLUG}"
120120

121121
if [ ! -d "$INTENT_WORKTREE" ]; then
@@ -134,7 +134,7 @@ Ensure the intent branch tracks the remote so teammates can push their unit bran
134134
```bash
135135
# Verify remote exists and configure upstream tracking
136136
if git remote get-url origin &>/dev/null; then
137-
INTENT_BRANCH="ai-dlc/${INTENT_SLUG}"
137+
INTENT_BRANCH="ai-dlc/${INTENT_SLUG}/main"
138138

139139
# Ensure the intent branch tracks the remote
140140
git branch --set-upstream-to=origin/"$INTENT_BRANCH" 2>/dev/null || true
@@ -436,7 +436,7 @@ AUTO_SQUASH=$(echo "$CONFIG" | jq -r '.auto_squash // "false"')
436436

437437
if [ "$AUTO_MERGE" = "true" ]; then
438438
UNIT_BRANCH="ai-dlc/${INTENT_SLUG}/${UNIT_SLUG}"
439-
git checkout "ai-dlc/${INTENT_SLUG}"
439+
git checkout "ai-dlc/${INTENT_SLUG}/main"
440440

441441
if [ "$AUTO_SQUASH" = "true" ]; then
442442
git merge --squash "$UNIT_BRANCH"

plugin/skills/elaborate/SKILL.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ Create the intent branch and worktree, then write files in `.ai-dlc/{intent-slug
672672
**CRITICAL: The intent MUST run in an isolated worktree, not the main working directory. Create this BEFORE writing any artifacts so all files are committed to the intent branch.**
673673

674674
```bash
675-
INTENT_BRANCH="ai-dlc/${intentSlug}"
675+
INTENT_BRANCH="ai-dlc/${intentSlug}/main"
676676
INTENT_WORKTREE="/tmp/ai-dlc-${intentSlug}"
677677
git worktree add -B "$INTENT_BRANCH" "$INTENT_WORKTREE"
678678
cd "$INTENT_WORKTREE"
@@ -757,7 +757,7 @@ problem space.}
757757
---
758758
status: pending
759759
depends_on: []
760-
branch: ai-dlc/{intent-slug}/NN-{slug}
760+
branch: ai-dlc/{intent-slug}/NN-{unit-slug}
761761
discipline: {discipline} # frontend, backend, api, documentation, devops, etc.
762762
ticket: "" # Ticketing provider ticket key (auto-populated if ticketing provider configured)
763763
---
@@ -828,7 +828,7 @@ If the orchestrator is in a temporary workspace (`/tmp/ai-dlc-workspace-*`):
828828
git push -u origin "$INTENT_BRANCH"
829829
```
830830

831-
This ensures builders can pull the intent branch when working remotely. Note in the handoff: "Artifacts pushed to `ai-dlc/{intent-slug}` branch on remote."
831+
This ensures builders can pull the intent branch when working remotely. Note in the handoff: "Artifacts pushed to `ai-dlc/{intent-slug}/main` branch on remote."
832832

833833
---
834834

@@ -873,7 +873,7 @@ Tell the user:
873873
Elaboration complete!
874874
875875
Intent Worktree: /tmp/ai-dlc-{intent-slug}/
876-
Branch: ai-dlc/{intent-slug}
876+
Branch: ai-dlc/{intent-slug}/main
877877
878878
Created: .ai-dlc/{intent-slug}/
879879
- intent.md (intent, config, and testing requirements)

plugin/skills/resume/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ starting_hat=$(get_recommended_hat ".ai-dlc/${slug}" "${workflow}")
104104
**CRITICAL: The orchestrator MUST run in the intent worktree, not the main working directory.**
105105

106106
```bash
107-
INTENT_BRANCH="ai-dlc/${slug}"
107+
INTENT_BRANCH="ai-dlc/${slug}/main"
108108
INTENT_WORKTREE="/tmp/ai-dlc-${slug}"
109109

110110
if [ ! -d "$INTENT_WORKTREE" ]; then

0 commit comments

Comments
 (0)