@mindfoldhq/trellis 0.1.0 → 0.1.2

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 (140) hide show
  1. package/README.md +58 -11
  2. package/dist/.claude/agents/check.md +98 -0
  3. package/dist/.claude/agents/debug.md +109 -0
  4. package/dist/{templates/agents/dispatch.txt → .claude/agents/dispatch.md} +20 -12
  5. package/dist/.claude/agents/implement.md +101 -0
  6. package/dist/.claude/agents/plan.md +396 -0
  7. package/dist/.claude/agents/research.md +120 -0
  8. package/dist/{templates/commands/common/check-cross-layer.txt → .claude/commands/check-cross-layer.md} +29 -29
  9. package/dist/{templates/commands/common/onboard-developer.txt → .claude/commands/onboard-developer.md} +2 -2
  10. package/dist/.claude/commands/parallel.md +199 -0
  11. package/dist/{templates/commands/common/record-agent-flow.txt → .claude/commands/record-agent-flow.md} +1 -1
  12. package/dist/.claude/commands/start.md +192 -0
  13. package/dist/{templates → .claude}/hooks/inject-subagent-context.py +63 -0
  14. package/dist/.cursor/commands/before-backend-dev.md +13 -0
  15. package/dist/.cursor/commands/before-frontend-dev.md +13 -0
  16. package/dist/.cursor/commands/break-loop.md +107 -0
  17. package/dist/.cursor/commands/check-backend.md +13 -0
  18. package/dist/.cursor/commands/check-cross-layer.md +153 -0
  19. package/dist/.cursor/commands/check-frontend.md +13 -0
  20. package/dist/.cursor/commands/create-command.md +154 -0
  21. package/dist/.cursor/commands/finish-work.md +129 -0
  22. package/dist/.cursor/commands/integrate-skill.md +219 -0
  23. package/dist/.cursor/commands/onboard-developer.md +355 -0
  24. package/dist/.cursor/commands/record-agent-flow.md +62 -0
  25. package/dist/.cursor/commands/start.md +157 -0
  26. package/dist/{templates/markdown/agent-traces-index.md.txt → .trellis/agent-traces/index.md} +8 -9
  27. package/dist/{templates/scripts/add-session.sh.txt → .trellis/scripts/add-session.sh} +14 -14
  28. package/dist/{templates/scripts/common/developer.sh.txt → .trellis/scripts/common/developer.sh} +13 -13
  29. package/dist/{templates/scripts/common/git-context.sh.txt → .trellis/scripts/common/git-context.sh} +8 -8
  30. package/dist/{templates/scripts/common/paths.sh.txt → .trellis/scripts/common/paths.sh} +4 -4
  31. package/dist/.trellis/scripts/common/phase.sh +150 -0
  32. package/dist/.trellis/scripts/common/worktree.sh +138 -0
  33. package/dist/{templates/scripts/feature.sh.txt → .trellis/scripts/feature.sh} +297 -0
  34. package/dist/.trellis/scripts/multi-agent/cleanup.sh +416 -0
  35. package/dist/.trellis/scripts/multi-agent/create-pr.sh +241 -0
  36. package/dist/.trellis/scripts/multi-agent/plan.sh +232 -0
  37. package/dist/.trellis/scripts/multi-agent/start.sh +344 -0
  38. package/dist/.trellis/scripts/multi-agent/status.sh +695 -0
  39. package/dist/.trellis/structure/backend/database-guidelines.md +51 -0
  40. package/dist/.trellis/structure/backend/directory-structure.md +209 -0
  41. package/dist/.trellis/structure/backend/error-handling.md +278 -0
  42. package/dist/.trellis/structure/backend/index.md +38 -0
  43. package/dist/.trellis/structure/backend/logging-guidelines.md +266 -0
  44. package/dist/.trellis/structure/backend/quality-guidelines.md +313 -0
  45. package/dist/.trellis/structure/frontend/component-guidelines.md +59 -0
  46. package/dist/.trellis/structure/frontend/directory-structure.md +54 -0
  47. package/dist/.trellis/structure/frontend/hook-guidelines.md +51 -0
  48. package/dist/.trellis/structure/frontend/index.md +39 -0
  49. package/dist/.trellis/structure/frontend/quality-guidelines.md +51 -0
  50. package/dist/.trellis/structure/frontend/state-management.md +51 -0
  51. package/dist/.trellis/structure/frontend/type-safety.md +51 -0
  52. package/dist/.trellis/structure/guides/code-reuse-thinking-guide.md +92 -0
  53. package/dist/.trellis/structure/guides/cross-layer-thinking-guide.md +94 -0
  54. package/dist/.trellis/structure/guides/index.md +79 -0
  55. package/dist/{templates/markdown/workflow.md.txt → .trellis/workflow.md} +6 -6
  56. package/dist/.trellis/worktree.yaml +49 -0
  57. package/dist/cli/index.js +1 -0
  58. package/dist/cli/index.js.map +1 -1
  59. package/dist/commands/init.d.ts.map +1 -1
  60. package/dist/commands/init.js +29 -15
  61. package/dist/commands/init.js.map +1 -1
  62. package/dist/configurators/claude.d.ts +17 -17
  63. package/dist/configurators/claude.d.ts.map +1 -1
  64. package/dist/configurators/claude.js +29 -59
  65. package/dist/configurators/claude.js.map +1 -1
  66. package/dist/configurators/cursor.d.ts +3 -3
  67. package/dist/configurators/cursor.d.ts.map +1 -1
  68. package/dist/configurators/cursor.js +11 -15
  69. package/dist/configurators/cursor.js.map +1 -1
  70. package/dist/configurators/opencode.d.ts +25 -0
  71. package/dist/configurators/opencode.d.ts.map +1 -0
  72. package/dist/configurators/opencode.js +54 -0
  73. package/dist/configurators/opencode.js.map +1 -0
  74. package/dist/configurators/workflow.d.ts +9 -0
  75. package/dist/configurators/workflow.d.ts.map +1 -1
  76. package/dist/configurators/workflow.js +32 -72
  77. package/dist/configurators/workflow.js.map +1 -1
  78. package/dist/templates/extract.d.ts +73 -8
  79. package/dist/templates/extract.d.ts.map +1 -1
  80. package/dist/templates/extract.js +149 -10
  81. package/dist/templates/extract.js.map +1 -1
  82. package/dist/templates/markdown/{agents.md.txt → agents.md} +1 -1
  83. package/dist/templates/markdown/index.d.ts +5 -1
  84. package/dist/templates/markdown/index.d.ts.map +1 -1
  85. package/dist/templates/markdown/index.js +54 -26
  86. package/dist/templates/markdown/index.js.map +1 -1
  87. package/dist/templates/markdown/{init-agent.md.txt → init-agent.md} +8 -8
  88. package/dist/templates/markdown/structure/backend/directory-structure.md.txt +6 -6
  89. package/dist/templates/markdown/structure/backend/error-handling.md.txt +8 -8
  90. package/dist/templates/markdown/structure/backend/index.md.txt +5 -5
  91. package/dist/templates/markdown/structure/backend/logging-guidelines.md.txt +8 -8
  92. package/dist/templates/markdown/structure/frontend/index.md.txt +6 -6
  93. package/dist/templates/markdown/structure/guides/cross-layer-thinking-guide.md.txt +5 -5
  94. package/dist/templates/markdown/structure/guides/index.md.txt +7 -7
  95. package/dist/templates/markdown/worktree.yaml.txt +58 -0
  96. package/dist/types/ai-tools.d.ts +2 -2
  97. package/dist/types/ai-tools.d.ts.map +1 -1
  98. package/dist/types/ai-tools.js +4 -0
  99. package/dist/types/ai-tools.js.map +1 -1
  100. package/package.json +1 -1
  101. package/dist/configurators/templates.d.ts +0 -40
  102. package/dist/configurators/templates.d.ts.map +0 -1
  103. package/dist/configurators/templates.js +0 -67
  104. package/dist/configurators/templates.js.map +0 -1
  105. package/dist/templates/agents/check.txt +0 -120
  106. package/dist/templates/agents/debug.txt +0 -121
  107. package/dist/templates/agents/implement.txt +0 -114
  108. package/dist/templates/agents/index.d.ts +0 -35
  109. package/dist/templates/agents/index.d.ts.map +0 -1
  110. package/dist/templates/agents/index.js +0 -71
  111. package/dist/templates/agents/index.js.map +0 -1
  112. package/dist/templates/agents/research.txt +0 -258
  113. package/dist/templates/commands/claude/start.md.txt +0 -127
  114. package/dist/templates/commands/cursor/start.md.txt +0 -94
  115. package/dist/templates/commands/index.d.ts +0 -46
  116. package/dist/templates/commands/index.d.ts.map +0 -1
  117. package/dist/templates/commands/index.js +0 -151
  118. package/dist/templates/commands/index.js.map +0 -1
  119. package/dist/templates/hooks/index.d.ts +0 -33
  120. package/dist/templates/hooks/index.d.ts.map +0 -1
  121. package/dist/templates/hooks/index.js +0 -53
  122. package/dist/templates/hooks/index.js.map +0 -1
  123. package/dist/templates/markdown/gitignore.txt +0 -3
  124. package/dist/templates/scripts/index.d.ts +0 -25
  125. package/dist/templates/scripts/index.d.ts.map +0 -1
  126. package/dist/templates/scripts/index.js +0 -28
  127. package/dist/templates/scripts/index.js.map +0 -1
  128. /package/dist/{templates/commands/common/before-backend-dev.txt → .claude/commands/before-backend-dev.md} +0 -0
  129. /package/dist/{templates/commands/common/before-frontend-dev.txt → .claude/commands/before-frontend-dev.md} +0 -0
  130. /package/dist/{templates/commands/common/break-loop.txt → .claude/commands/break-loop.md} +0 -0
  131. /package/dist/{templates/commands/common/check-backend.txt → .claude/commands/check-backend.md} +0 -0
  132. /package/dist/{templates/commands/common/check-frontend.txt → .claude/commands/check-frontend.md} +0 -0
  133. /package/dist/{templates/commands/common/create-command.txt → .claude/commands/create-command.md} +0 -0
  134. /package/dist/{templates/commands/common/finish-work.txt → .claude/commands/finish-work.md} +0 -0
  135. /package/dist/{templates/commands/common/integrate-skill.txt → .claude/commands/integrate-skill.md} +0 -0
  136. /package/dist/{templates/hooks → .claude}/settings.json +0 -0
  137. /package/dist/{templates/scripts/create-bootstrap.sh.txt → .trellis/scripts/create-bootstrap.sh} +0 -0
  138. /package/dist/{templates/scripts/get-context.sh.txt → .trellis/scripts/get-context.sh} +0 -0
  139. /package/dist/{templates/scripts/get-developer.sh.txt → .trellis/scripts/get-developer.sh} +0 -0
  140. /package/dist/{templates/scripts/init-developer.sh.txt → .trellis/scripts/init-developer.sh} +0 -0
@@ -1,5 +1,5 @@
1
1
  #!/bin/bash
2
- # Add a new session to progress file and update index.md
2
+ # Add a new session to traces file and update index.md
3
3
  #
4
4
  # Usage:
5
5
  # ./.trellis/scripts/add-session.sh --title "Title" --commit "hash" --summary "Summary"
@@ -30,9 +30,9 @@ get_latest_progress_info() {
30
30
  local latest_file=""
31
31
  local latest_num=0
32
32
 
33
- for f in "$DEV_DIR"/progress-*.md; do
33
+ for f in "$DEV_DIR"/traces-*.md; do
34
34
  if [[ -f "$f" ]]; then
35
- local num=$(basename "$f" | sed 's/progress-\([0-9]*\)\.md/\1/')
35
+ local num=$(basename "$f" | sed 's/traces-\([0-9]*\)\.md/\1/')
36
36
  if [[ "$num" -gt "$latest_num" ]]; then
37
37
  latest_num=$num
38
38
  latest_file="$f"
@@ -57,9 +57,9 @@ count_progress_files() {
57
57
  local result=""
58
58
  local progress_info=$(get_latest_progress_info)
59
59
  local active_num=$(echo "$progress_info" | cut -d: -f2)
60
- local active_file="progress-$active_num.md"
60
+ local active_file="traces-$active_num.md"
61
61
 
62
- for f in $(ls -v "$DEV_DIR"/progress-*.md 2>/dev/null | sort -t- -k2 -n -r); do
62
+ for f in $(ls -v "$DEV_DIR"/traces-*.md 2>/dev/null | sort -t- -k2 -n -r); do
63
63
  if [[ -f "$f" ]]; then
64
64
  local filename=$(basename "$f")
65
65
  local lines=$(wc -l < "$f" | tr -d ' ')
@@ -76,15 +76,15 @@ count_progress_files() {
76
76
  echo "$result" | sed '/^$/d'
77
77
  }
78
78
 
79
- create_new_progress_file() {
79
+ create_new_traces_file() {
80
80
  local num=$1
81
81
  local prev_num=$((num - 1))
82
- local new_file="$DEV_DIR/progress-$num.md"
82
+ local new_file="$DEV_DIR/traces-$num.md"
83
83
 
84
84
  cat > "$new_file" << EOF
85
- # Agent Progress - $DEVELOPER (Part $num)
85
+ # Agent Traces - $DEVELOPER (Part $num)
86
86
 
87
- > Continuation from \`progress-$prev_num.md\` (archived at ~$MAX_LINES lines)
87
+ > Continuation from \`traces-$prev_num.md\` (archived at ~$MAX_LINES lines)
88
88
  > Started: $TODAY
89
89
 
90
90
  ---
@@ -317,7 +317,7 @@ add_session() {
317
317
  echo "Title: $title" >&2
318
318
  echo "Commit: $commit" >&2
319
319
  echo "" >&2
320
- echo "Current progress file: progress-$current_num.md" >&2
320
+ echo "Current traces file: traces-$current_num.md" >&2
321
321
  echo "Current lines: $current_lines" >&2
322
322
  echo "New content lines: $content_lines" >&2
323
323
  echo "Total after append: $((current_lines + content_lines))" >&2
@@ -328,8 +328,8 @@ add_session() {
328
328
 
329
329
  if [[ $((current_lines + content_lines)) -gt $MAX_LINES ]]; then
330
330
  target_num=$((current_num + 1))
331
- echo "[!] Exceeds $MAX_LINES lines, creating progress-$target_num.md" >&2
332
- target_file=$(create_new_progress_file "$target_num")
331
+ echo "[!] Exceeds $MAX_LINES lines, creating traces-$target_num.md" >&2
332
+ target_file=$(create_new_traces_file "$target_num")
333
333
  echo "Created: $target_file" >&2
334
334
  fi
335
335
 
@@ -339,7 +339,7 @@ add_session() {
339
339
  echo "" >&2
340
340
 
341
341
  # Update index.md directly
342
- local active_file="progress-$target_num.md"
342
+ local active_file="traces-$target_num.md"
343
343
  update_index "$title" "$commit" "$new_session" "$active_file"
344
344
 
345
345
  echo "" >&2
@@ -355,7 +355,7 @@ add_session() {
355
355
  show_help() {
356
356
  echo "Usage: $0 --title \"Title\" [options]"
357
357
  echo ""
358
- echo "Add a new session to progress file and update index.md automatically."
358
+ echo "Add a new session to traces file and update index.md automatically."
359
359
  echo ""
360
360
  echo "Options:"
361
361
  echo " --title TEXT Session title (required)"
@@ -40,34 +40,34 @@ EOF
40
40
  mkdir -p "$progress_dir/$DIR_FEATURES"
41
41
  mkdir -p "$progress_dir/$DIR_FEATURES/$DIR_ARCHIVE"
42
42
 
43
- # Create initial progress file
44
- local progress_file="$progress_dir/progress-1.md"
45
- if [[ ! -f "$progress_file" ]]; then
46
- cat > "$progress_file" << PROGRESS_EOF
47
- # Agent Progress - $name (Part 1)
43
+ # Create initial traces file
44
+ local traces_file="$progress_dir/traces-1.md"
45
+ if [[ ! -f "$traces_file" ]]; then
46
+ cat > "$traces_file" << TRACES_EOF
47
+ # Agent Traces - $name (Part 1)
48
48
 
49
- > AI development session progress tracking
49
+ > AI development session traces
50
50
  > Started: $(date +%Y-%m-%d)
51
51
 
52
52
  ---
53
53
 
54
- PROGRESS_EOF
54
+ TRACES_EOF
55
55
  fi
56
56
 
57
57
  # Create index.md with markers for auto-update
58
58
  local index_file="$progress_dir/index.md"
59
59
  if [[ ! -f "$index_file" ]]; then
60
60
  cat > "$index_file" << INDEX_EOF
61
- # Agent Progress Index - $name
61
+ # Agent Traces Index - $name
62
62
 
63
- > Progress tracking for AI development sessions.
63
+ > Traces tracking for AI development sessions.
64
64
 
65
65
  ---
66
66
 
67
67
  ## Current Status
68
68
 
69
69
  <!-- @@@auto:current-status -->
70
- - **Active File**: \`progress-1.md\`
70
+ - **Active File**: \`traces-1.md\`
71
71
  - **Total Sessions**: 0
72
72
  - **Last Active**: -
73
73
  <!-- @@@/auto:current-status -->
@@ -79,7 +79,7 @@ PROGRESS_EOF
79
79
  <!-- @@@auto:active-documents -->
80
80
  | File | Lines | Status |
81
81
  |------|-------|--------|
82
- | \`progress-1.md\` | ~0 | Active |
82
+ | \`traces-1.md\` | ~0 | Active |
83
83
  <!-- @@@/auto:active-documents -->
84
84
 
85
85
  ---
@@ -95,8 +95,8 @@ PROGRESS_EOF
95
95
 
96
96
  ## Notes
97
97
 
98
- - Sessions are appended to progress files
99
- - New progress file created when current exceeds 2000 lines
98
+ - Sessions are appended to traces files
99
+ - New traces file created when current exceeds 2000 lines
100
100
  - Use \`add-session.sh\` to record sessions
101
101
  INDEX_EOF
102
102
  fi
@@ -88,7 +88,7 @@ output_json() {
88
88
  "active": $features_json,
89
89
  "directory": "$DIR_WORKFLOW/$DIR_PROGRESS/$developer/$DIR_FEATURES"
90
90
  },
91
- "progress": {
91
+ "traces": {
92
92
  "file": "$progress_relative",
93
93
  "lines": $progress_lines,
94
94
  "nearLimit": $([ "$progress_lines" -gt 1800 ] && echo "true" || echo "false")
@@ -190,23 +190,23 @@ output_text() {
190
190
  echo "Total: $feature_count active feature(s)"
191
191
  echo ""
192
192
 
193
- echo "## PROGRESS FILE"
194
- local progress_file=$(get_active_progress_file "$repo_root")
195
- if [[ -n "$progress_file" ]]; then
196
- local lines=$(count_lines "$progress_file")
197
- local relative="$DIR_WORKFLOW/$DIR_PROGRESS/$developer/$(basename "$progress_file")"
193
+ echo "## TRACES FILE"
194
+ local traces_file=$(get_active_progress_file "$repo_root")
195
+ if [[ -n "$traces_file" ]]; then
196
+ local lines=$(count_lines "$traces_file")
197
+ local relative="$DIR_WORKFLOW/$DIR_PROGRESS/$developer/$(basename "$traces_file")"
198
198
  echo "Active file: $relative"
199
199
  echo "Line count: $lines / 2000"
200
200
  if [[ "$lines" -gt 1800 ]]; then
201
201
  echo "[!] WARNING: Approaching 2000 line limit!"
202
202
  fi
203
203
  else
204
- echo "No progress file found"
204
+ echo "No traces file found"
205
205
  fi
206
206
  echo ""
207
207
 
208
208
  echo "## PATHS"
209
- echo "Progress dir: $DIR_WORKFLOW/$DIR_PROGRESS/$developer/"
209
+ echo "Traces dir: $DIR_WORKFLOW/$DIR_PROGRESS/$developer/"
210
210
  echo "Features dir: $DIR_WORKFLOW/$DIR_PROGRESS/$developer/$DIR_FEATURES/"
211
211
  echo "Index file: $DIR_WORKFLOW/$DIR_PROGRESS/$developer/index.md"
212
212
  echo ""
@@ -8,8 +8,8 @@
8
8
  # get_repo_root - Get repository root directory
9
9
  # get_developer - Get developer name
10
10
  # get_features_dir - Get features directory
11
- # get_progress_dir - Get progress directory
12
- # get_active_progress_file - Get current progress file
11
+ # get_progress_dir - Get traces directory
12
+ # get_active_progress_file - Get current traces file
13
13
 
14
14
  # =============================================================================
15
15
  # Path Constants (change here to rename directories)
@@ -108,9 +108,9 @@ get_active_progress_file() {
108
108
 
109
109
  local latest=""
110
110
  local highest=0
111
- for f in "$progress_dir"/progress-*.md; do
111
+ for f in "$progress_dir"/traces-*.md; do
112
112
  if [[ -f "$f" ]]; then
113
- local num=$(basename "$f" | sed 's/progress-//' | sed 's/\.md//')
113
+ local num=$(basename "$f" | sed 's/traces-//' | sed 's/\.md//')
114
114
  if [[ "$num" =~ ^[0-9]+$ ]] && [[ "$num" -gt "$highest" ]]; then
115
115
  highest=$num
116
116
  latest="$f"
@@ -0,0 +1,150 @@
1
+ #!/bin/bash
2
+ # =============================================================================
3
+ # Phase Management Utilities
4
+ # =============================================================================
5
+ # Centralized phase tracking for multi-agent pipeline
6
+ #
7
+ # Usage:
8
+ # source common/phase.sh
9
+ #
10
+ # get_current_phase "$feature_json" # Returns current phase number
11
+ # get_total_phases "$feature_json" # Returns total phase count
12
+ # get_phase_action "$feature_json" "$phase" # Returns action name for phase
13
+ # get_phase_info "$feature_json" # Returns "N/M (action)" format
14
+ # set_phase "$feature_json" "$phase" # Sets current_phase
15
+ # advance_phase "$feature_json" # Advances to next phase
16
+ # get_phase_for_action "$feature_json" "$action" # Returns phase number for action
17
+ # =============================================================================
18
+
19
+ # Get current phase number
20
+ get_current_phase() {
21
+ local feature_json="$1"
22
+ if [ ! -f "$feature_json" ]; then
23
+ echo "0"
24
+ return
25
+ fi
26
+ jq -r '.current_phase // 0' "$feature_json"
27
+ }
28
+
29
+ # Get total number of phases
30
+ get_total_phases() {
31
+ local feature_json="$1"
32
+ if [ ! -f "$feature_json" ]; then
33
+ echo "0"
34
+ return
35
+ fi
36
+ jq -r '.next_action | length // 0' "$feature_json"
37
+ }
38
+
39
+ # Get action name for a specific phase
40
+ get_phase_action() {
41
+ local feature_json="$1"
42
+ local phase="$2"
43
+ if [ ! -f "$feature_json" ]; then
44
+ echo "unknown"
45
+ return
46
+ fi
47
+ jq -r --argjson phase "$phase" '.next_action[] | select(.phase == $phase) | .action // "unknown"' "$feature_json"
48
+ }
49
+
50
+ # Get formatted phase info: "N/M (action)"
51
+ get_phase_info() {
52
+ local feature_json="$1"
53
+ if [ ! -f "$feature_json" ]; then
54
+ echo "N/A"
55
+ return
56
+ fi
57
+
58
+ local current_phase=$(get_current_phase "$feature_json")
59
+ local total_phases=$(get_total_phases "$feature_json")
60
+ local action_name=$(get_phase_action "$feature_json" "$current_phase")
61
+
62
+ if [ "$current_phase" = "0" ] || [ "$current_phase" = "null" ]; then
63
+ echo "0/${total_phases} (pending)"
64
+ else
65
+ echo "${current_phase}/${total_phases} (${action_name})"
66
+ fi
67
+ }
68
+
69
+ # Set current phase to a specific value
70
+ set_phase() {
71
+ local feature_json="$1"
72
+ local phase="$2"
73
+
74
+ if [ ! -f "$feature_json" ]; then
75
+ echo "Error: feature.json not found: $feature_json" >&2
76
+ return 1
77
+ fi
78
+
79
+ jq --argjson phase "$phase" '.current_phase = $phase' "$feature_json" > "${feature_json}.tmp"
80
+ mv "${feature_json}.tmp" "$feature_json"
81
+ }
82
+
83
+ # Advance to next phase
84
+ advance_phase() {
85
+ local feature_json="$1"
86
+
87
+ if [ ! -f "$feature_json" ]; then
88
+ echo "Error: feature.json not found: $feature_json" >&2
89
+ return 1
90
+ fi
91
+
92
+ local current=$(get_current_phase "$feature_json")
93
+ local total=$(get_total_phases "$feature_json")
94
+ local next=$((current + 1))
95
+
96
+ if [ "$next" -gt "$total" ]; then
97
+ echo "Warning: Already at final phase" >&2
98
+ return 0
99
+ fi
100
+
101
+ set_phase "$feature_json" "$next"
102
+ }
103
+
104
+ # Get phase number for a specific action name
105
+ get_phase_for_action() {
106
+ local feature_json="$1"
107
+ local action="$2"
108
+
109
+ if [ ! -f "$feature_json" ]; then
110
+ echo "0"
111
+ return
112
+ fi
113
+
114
+ jq -r --arg action "$action" '.next_action[] | select(.action == $action) | .phase // 0' "$feature_json"
115
+ }
116
+
117
+ # Map subagent type to action name
118
+ # Used by hooks to determine which action a subagent corresponds to
119
+ map_subagent_to_action() {
120
+ local subagent_type="$1"
121
+
122
+ case "$subagent_type" in
123
+ implement) echo "implement" ;;
124
+ check) echo "check" ;;
125
+ debug) echo "debug" ;;
126
+ research) echo "research" ;;
127
+ # finish uses check agent but is a different action
128
+ *) echo "$subagent_type" ;;
129
+ esac
130
+ }
131
+
132
+ # Check if a phase is completed (current_phase > phase)
133
+ is_phase_completed() {
134
+ local feature_json="$1"
135
+ local phase="$2"
136
+
137
+ local current=$(get_current_phase "$feature_json")
138
+ [ "$current" -gt "$phase" ]
139
+ }
140
+
141
+ # Check if we're at a specific action
142
+ is_current_action() {
143
+ local feature_json="$1"
144
+ local action="$2"
145
+
146
+ local current=$(get_current_phase "$feature_json")
147
+ local action_phase=$(get_phase_for_action "$feature_json" "$action")
148
+
149
+ [ "$current" = "$action_phase" ]
150
+ }
@@ -0,0 +1,138 @@
1
+ #!/bin/bash
2
+ # Worktree utilities for Multi-Agent Pipeline
3
+ #
4
+ # Usage: source this file in multi-agent scripts
5
+ # source "$(dirname "$0")/../common/worktree.sh"
6
+ #
7
+ # Provides:
8
+ # get_worktree_config - Get worktree.yaml path
9
+ # get_worktree_base_dir - Get worktree storage directory
10
+ # get_worktree_copy_files - Get files to copy list
11
+ # get_worktree_post_create_hooks - Get post-create hooks
12
+ # get_worktree_pre_merge_hooks - Get pre-merge hooks
13
+ # get_agents_dir - Get agents registry directory
14
+ #
15
+ # Requires: paths.sh (for get_repo_root)
16
+
17
+ # Ensure paths.sh is loaded
18
+ if ! type get_repo_root &>/dev/null; then
19
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
20
+ source "$SCRIPT_DIR/paths.sh"
21
+ fi
22
+
23
+ # =============================================================================
24
+ # Worktree Configuration
25
+ # =============================================================================
26
+
27
+ # Worktree config file relative path (relative to repo root)
28
+ WORKTREE_CONFIG_PATH="$DIR_WORKFLOW/worktree.yaml"
29
+
30
+ # Get worktree.yaml config file path
31
+ # Args: $1 - repo_root (optional)
32
+ # Returns: absolute path to config file
33
+ get_worktree_config() {
34
+ local repo_root="${1:-$(get_repo_root)}"
35
+ echo "$repo_root/$WORKTREE_CONFIG_PATH"
36
+ }
37
+
38
+ # Read simple value from worktree.yaml
39
+ # Args: $1 - key, $2 - config_file (optional)
40
+ # Returns: value
41
+ _yaml_get_value() {
42
+ local key="$1"
43
+ local config="${2:-$(get_worktree_config)}"
44
+ grep "^${key}:" "$config" 2>/dev/null | sed "s/^${key}:[[:space:]]*//" | tr -d '"' | tr -d "'"
45
+ }
46
+
47
+ # Read list from worktree.yaml
48
+ # Args: $1 - section, $2 - config_file (optional)
49
+ # Returns: list items (one per line)
50
+ _yaml_get_list() {
51
+ local section="$1"
52
+ local config="${2:-$(get_worktree_config)}"
53
+ local in_section=0
54
+
55
+ while IFS= read -r line; do
56
+ if [[ "$line" =~ ^${section}: ]]; then
57
+ in_section=1
58
+ continue
59
+ fi
60
+
61
+ if [ $in_section -eq 1 ]; then
62
+ # Exit when encountering new top-level key
63
+ if [[ "$line" =~ ^[a-z_]+: ]] && [[ ! "$line" =~ ^[[:space:]] ]]; then
64
+ break
65
+ fi
66
+ # Read list item
67
+ if [[ "$line" =~ ^[[:space:]]*-[[:space:]](.+)$ ]]; then
68
+ echo "${BASH_REMATCH[1]}" | tr -d '"' | tr -d "'"
69
+ fi
70
+ fi
71
+ done < "$config"
72
+ }
73
+
74
+ # Get worktree base directory
75
+ # Args: $1 - repo_root (optional)
76
+ # Returns: absolute path to worktree base directory
77
+ get_worktree_base_dir() {
78
+ local repo_root="${1:-$(get_repo_root)}"
79
+ local config=$(get_worktree_config "$repo_root")
80
+ local worktree_dir=$(_yaml_get_value "worktree_dir" "$config")
81
+
82
+ # Default value
83
+ if [ -z "$worktree_dir" ]; then
84
+ worktree_dir="../worktrees"
85
+ fi
86
+
87
+ # Handle relative path
88
+ if [[ "$worktree_dir" == ../* ]] || [[ "$worktree_dir" == ./* ]]; then
89
+ # Relative to repo_root
90
+ echo "$repo_root/$worktree_dir"
91
+ else
92
+ # Absolute path
93
+ echo "$worktree_dir"
94
+ fi
95
+ }
96
+
97
+ # Get files to copy list
98
+ # Args: $1 - repo_root (optional)
99
+ # Returns: file list (one per line)
100
+ get_worktree_copy_files() {
101
+ local repo_root="${1:-$(get_repo_root)}"
102
+ local config=$(get_worktree_config "$repo_root")
103
+ _yaml_get_list "copy" "$config"
104
+ }
105
+
106
+ # Get post_create hooks
107
+ # Args: $1 - repo_root (optional)
108
+ # Returns: command list (one per line)
109
+ get_worktree_post_create_hooks() {
110
+ local repo_root="${1:-$(get_repo_root)}"
111
+ local config=$(get_worktree_config "$repo_root")
112
+ _yaml_get_list "post_create" "$config"
113
+ }
114
+
115
+ # Get pre_merge hooks
116
+ # Args: $1 - repo_root (optional)
117
+ # Returns: command list (one per line)
118
+ get_worktree_pre_merge_hooks() {
119
+ local repo_root="${1:-$(get_repo_root)}"
120
+ local config=$(get_worktree_config "$repo_root")
121
+ _yaml_get_list "pre_merge" "$config"
122
+ }
123
+
124
+ # =============================================================================
125
+ # Agents Registry
126
+ # =============================================================================
127
+
128
+ # Get agents directory for current developer
129
+ # Args: $1 - repo_root (optional)
130
+ # Returns: absolute path to agents directory
131
+ get_agents_dir() {
132
+ local repo_root="${1:-$(get_repo_root)}"
133
+ local progress_dir=$(get_progress_dir "$repo_root")
134
+
135
+ if [[ -n "$progress_dir" ]]; then
136
+ echo "$progress_dir/.agents"
137
+ fi
138
+ }