aether-colony 1.1.0

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 (207) hide show
  1. package/.aether/CONTEXT.md +160 -0
  2. package/.aether/QUEEN.md +84 -0
  3. package/.aether/aether-utils.sh +7749 -0
  4. package/.aether/docs/QUEEN-SYSTEM.md +211 -0
  5. package/.aether/docs/README.md +68 -0
  6. package/.aether/docs/caste-system.md +48 -0
  7. package/.aether/docs/disciplines/DISCIPLINES.md +93 -0
  8. package/.aether/docs/disciplines/coding-standards.md +197 -0
  9. package/.aether/docs/disciplines/debugging.md +207 -0
  10. package/.aether/docs/disciplines/learning.md +254 -0
  11. package/.aether/docs/disciplines/tdd.md +257 -0
  12. package/.aether/docs/disciplines/verification-loop.md +167 -0
  13. package/.aether/docs/disciplines/verification.md +116 -0
  14. package/.aether/docs/error-codes.md +268 -0
  15. package/.aether/docs/known-issues.md +233 -0
  16. package/.aether/docs/pheromones.md +205 -0
  17. package/.aether/docs/queen-commands.md +97 -0
  18. package/.aether/exchange/colony-registry.xml +11 -0
  19. package/.aether/exchange/pheromone-xml.sh +575 -0
  20. package/.aether/exchange/pheromones.xml +87 -0
  21. package/.aether/exchange/queen-wisdom.xml +14 -0
  22. package/.aether/exchange/registry-xml.sh +273 -0
  23. package/.aether/exchange/wisdom-xml.sh +319 -0
  24. package/.aether/midden/approach-changes.md +5 -0
  25. package/.aether/midden/build-failures.md +5 -0
  26. package/.aether/midden/test-failures.md +5 -0
  27. package/.aether/model-profiles.yaml +100 -0
  28. package/.aether/rules/aether-colony.md +134 -0
  29. package/.aether/schemas/aether-types.xsd +255 -0
  30. package/.aether/schemas/colony-registry.xsd +309 -0
  31. package/.aether/schemas/example-prompt-builder.xml +234 -0
  32. package/.aether/schemas/pheromone.xsd +163 -0
  33. package/.aether/schemas/prompt.xsd +416 -0
  34. package/.aether/schemas/queen-wisdom.xsd +325 -0
  35. package/.aether/schemas/worker-priming.xsd +276 -0
  36. package/.aether/templates/QUEEN.md.template +79 -0
  37. package/.aether/templates/colony-state-reset.jq.template +22 -0
  38. package/.aether/templates/colony-state.template.json +35 -0
  39. package/.aether/templates/constraints.template.json +9 -0
  40. package/.aether/templates/crowned-anthill.template.md +36 -0
  41. package/.aether/templates/handoff-build-error.template.md +30 -0
  42. package/.aether/templates/handoff-build-success.template.md +39 -0
  43. package/.aether/templates/handoff.template.md +40 -0
  44. package/.aether/templates/learning-observations.template.json +6 -0
  45. package/.aether/templates/midden.template.json +7 -0
  46. package/.aether/templates/pheromones.template.json +6 -0
  47. package/.aether/templates/session.template.json +9 -0
  48. package/.aether/utils/atomic-write.sh +219 -0
  49. package/.aether/utils/chamber-compare.sh +193 -0
  50. package/.aether/utils/chamber-utils.sh +297 -0
  51. package/.aether/utils/colorize-log.sh +132 -0
  52. package/.aether/utils/error-handler.sh +212 -0
  53. package/.aether/utils/file-lock.sh +158 -0
  54. package/.aether/utils/queen-to-md.xsl +395 -0
  55. package/.aether/utils/semantic-cli.sh +413 -0
  56. package/.aether/utils/spawn-tree.sh +428 -0
  57. package/.aether/utils/spawn-with-model.sh +56 -0
  58. package/.aether/utils/state-loader.sh +215 -0
  59. package/.aether/utils/swarm-display.sh +268 -0
  60. package/.aether/utils/watch-spawn-tree.sh +253 -0
  61. package/.aether/utils/xml-compose.sh +253 -0
  62. package/.aether/utils/xml-convert.sh +273 -0
  63. package/.aether/utils/xml-core.sh +186 -0
  64. package/.aether/utils/xml-query.sh +201 -0
  65. package/.aether/utils/xml-utils.sh +110 -0
  66. package/.aether/workers.md +765 -0
  67. package/.claude/agents/ant/aether-ambassador.md +264 -0
  68. package/.claude/agents/ant/aether-archaeologist.md +322 -0
  69. package/.claude/agents/ant/aether-auditor.md +266 -0
  70. package/.claude/agents/ant/aether-builder.md +187 -0
  71. package/.claude/agents/ant/aether-chaos.md +268 -0
  72. package/.claude/agents/ant/aether-chronicler.md +304 -0
  73. package/.claude/agents/ant/aether-gatekeeper.md +325 -0
  74. package/.claude/agents/ant/aether-includer.md +373 -0
  75. package/.claude/agents/ant/aether-keeper.md +271 -0
  76. package/.claude/agents/ant/aether-measurer.md +317 -0
  77. package/.claude/agents/ant/aether-probe.md +210 -0
  78. package/.claude/agents/ant/aether-queen.md +325 -0
  79. package/.claude/agents/ant/aether-route-setter.md +173 -0
  80. package/.claude/agents/ant/aether-sage.md +353 -0
  81. package/.claude/agents/ant/aether-scout.md +142 -0
  82. package/.claude/agents/ant/aether-surveyor-disciplines.md +416 -0
  83. package/.claude/agents/ant/aether-surveyor-nest.md +354 -0
  84. package/.claude/agents/ant/aether-surveyor-pathogens.md +288 -0
  85. package/.claude/agents/ant/aether-surveyor-provisions.md +359 -0
  86. package/.claude/agents/ant/aether-tracker.md +265 -0
  87. package/.claude/agents/ant/aether-watcher.md +244 -0
  88. package/.claude/agents/ant/aether-weaver.md +247 -0
  89. package/.claude/commands/ant/archaeology.md +341 -0
  90. package/.claude/commands/ant/build.md +1160 -0
  91. package/.claude/commands/ant/chaos.md +349 -0
  92. package/.claude/commands/ant/colonize.md +270 -0
  93. package/.claude/commands/ant/continue.md +1070 -0
  94. package/.claude/commands/ant/council.md +309 -0
  95. package/.claude/commands/ant/dream.md +265 -0
  96. package/.claude/commands/ant/entomb.md +487 -0
  97. package/.claude/commands/ant/feedback.md +78 -0
  98. package/.claude/commands/ant/flag.md +139 -0
  99. package/.claude/commands/ant/flags.md +155 -0
  100. package/.claude/commands/ant/focus.md +58 -0
  101. package/.claude/commands/ant/help.md +122 -0
  102. package/.claude/commands/ant/history.md +137 -0
  103. package/.claude/commands/ant/init.md +409 -0
  104. package/.claude/commands/ant/interpret.md +267 -0
  105. package/.claude/commands/ant/lay-eggs.md +201 -0
  106. package/.claude/commands/ant/maturity.md +102 -0
  107. package/.claude/commands/ant/memory-details.md +77 -0
  108. package/.claude/commands/ant/migrate-state.md +165 -0
  109. package/.claude/commands/ant/oracle.md +387 -0
  110. package/.claude/commands/ant/organize.md +227 -0
  111. package/.claude/commands/ant/pause-colony.md +247 -0
  112. package/.claude/commands/ant/phase.md +126 -0
  113. package/.claude/commands/ant/plan.md +544 -0
  114. package/.claude/commands/ant/redirect.md +58 -0
  115. package/.claude/commands/ant/resume-colony.md +182 -0
  116. package/.claude/commands/ant/resume.md +363 -0
  117. package/.claude/commands/ant/seal.md +306 -0
  118. package/.claude/commands/ant/status.md +272 -0
  119. package/.claude/commands/ant/swarm.md +361 -0
  120. package/.claude/commands/ant/tunnels.md +425 -0
  121. package/.claude/commands/ant/update.md +209 -0
  122. package/.claude/commands/ant/verify-castes.md +95 -0
  123. package/.claude/commands/ant/watch.md +238 -0
  124. package/.opencode/agents/aether-ambassador.md +140 -0
  125. package/.opencode/agents/aether-archaeologist.md +108 -0
  126. package/.opencode/agents/aether-auditor.md +144 -0
  127. package/.opencode/agents/aether-builder.md +184 -0
  128. package/.opencode/agents/aether-chaos.md +115 -0
  129. package/.opencode/agents/aether-chronicler.md +122 -0
  130. package/.opencode/agents/aether-gatekeeper.md +116 -0
  131. package/.opencode/agents/aether-includer.md +117 -0
  132. package/.opencode/agents/aether-keeper.md +177 -0
  133. package/.opencode/agents/aether-measurer.md +128 -0
  134. package/.opencode/agents/aether-probe.md +133 -0
  135. package/.opencode/agents/aether-queen.md +286 -0
  136. package/.opencode/agents/aether-route-setter.md +130 -0
  137. package/.opencode/agents/aether-sage.md +106 -0
  138. package/.opencode/agents/aether-scout.md +101 -0
  139. package/.opencode/agents/aether-surveyor-disciplines.md +386 -0
  140. package/.opencode/agents/aether-surveyor-nest.md +324 -0
  141. package/.opencode/agents/aether-surveyor-pathogens.md +259 -0
  142. package/.opencode/agents/aether-surveyor-provisions.md +329 -0
  143. package/.opencode/agents/aether-tracker.md +137 -0
  144. package/.opencode/agents/aether-watcher.md +174 -0
  145. package/.opencode/agents/aether-weaver.md +130 -0
  146. package/.opencode/commands/ant/archaeology.md +338 -0
  147. package/.opencode/commands/ant/build.md +1200 -0
  148. package/.opencode/commands/ant/chaos.md +346 -0
  149. package/.opencode/commands/ant/colonize.md +202 -0
  150. package/.opencode/commands/ant/continue.md +938 -0
  151. package/.opencode/commands/ant/council.md +305 -0
  152. package/.opencode/commands/ant/dream.md +262 -0
  153. package/.opencode/commands/ant/entomb.md +367 -0
  154. package/.opencode/commands/ant/feedback.md +80 -0
  155. package/.opencode/commands/ant/flag.md +137 -0
  156. package/.opencode/commands/ant/flags.md +153 -0
  157. package/.opencode/commands/ant/focus.md +56 -0
  158. package/.opencode/commands/ant/help.md +124 -0
  159. package/.opencode/commands/ant/history.md +127 -0
  160. package/.opencode/commands/ant/init.md +337 -0
  161. package/.opencode/commands/ant/interpret.md +256 -0
  162. package/.opencode/commands/ant/lay-eggs.md +141 -0
  163. package/.opencode/commands/ant/maturity.md +92 -0
  164. package/.opencode/commands/ant/memory-details.md +77 -0
  165. package/.opencode/commands/ant/migrate-state.md +153 -0
  166. package/.opencode/commands/ant/oracle.md +338 -0
  167. package/.opencode/commands/ant/organize.md +224 -0
  168. package/.opencode/commands/ant/pause-colony.md +220 -0
  169. package/.opencode/commands/ant/phase.md +123 -0
  170. package/.opencode/commands/ant/plan.md +531 -0
  171. package/.opencode/commands/ant/redirect.md +67 -0
  172. package/.opencode/commands/ant/resume-colony.md +178 -0
  173. package/.opencode/commands/ant/resume.md +363 -0
  174. package/.opencode/commands/ant/seal.md +247 -0
  175. package/.opencode/commands/ant/status.md +272 -0
  176. package/.opencode/commands/ant/swarm.md +357 -0
  177. package/.opencode/commands/ant/tunnels.md +406 -0
  178. package/.opencode/commands/ant/update.md +191 -0
  179. package/.opencode/commands/ant/verify-castes.md +85 -0
  180. package/.opencode/commands/ant/watch.md +220 -0
  181. package/.opencode/opencode.json +3 -0
  182. package/CHANGELOG.md +325 -0
  183. package/DISCLAIMER.md +74 -0
  184. package/LICENSE +21 -0
  185. package/README.md +258 -0
  186. package/bin/cli.js +2436 -0
  187. package/bin/generate-commands.sh +291 -0
  188. package/bin/lib/caste-colors.js +57 -0
  189. package/bin/lib/colors.js +76 -0
  190. package/bin/lib/errors.js +255 -0
  191. package/bin/lib/event-types.js +190 -0
  192. package/bin/lib/file-lock.js +695 -0
  193. package/bin/lib/init.js +454 -0
  194. package/bin/lib/logger.js +242 -0
  195. package/bin/lib/model-profiles.js +445 -0
  196. package/bin/lib/model-verify.js +288 -0
  197. package/bin/lib/nestmate-loader.js +130 -0
  198. package/bin/lib/proxy-health.js +253 -0
  199. package/bin/lib/spawn-logger.js +266 -0
  200. package/bin/lib/state-guard.js +602 -0
  201. package/bin/lib/state-sync.js +516 -0
  202. package/bin/lib/telemetry.js +441 -0
  203. package/bin/lib/update-transaction.js +1454 -0
  204. package/bin/npx-install.js +178 -0
  205. package/bin/sync-to-runtime.sh +6 -0
  206. package/bin/validate-package.sh +88 -0
  207. package/package.json +70 -0
@@ -0,0 +1,268 @@
1
+ #!/bin/bash
2
+ # Real-time swarm activity display
3
+ # Usage: bash swarm-display.sh [swarm_id]
4
+
5
+ SWARM_ID="${1:-current}"
6
+ DATA_DIR="${DATA_DIR:-.aether/data}"
7
+ DISPLAY_FILE="$DATA_DIR/swarm-display.json"
8
+
9
+ # ANSI colors (matching caste-colors.js)
10
+ BLUE='\033[34m'
11
+ GREEN='\033[32m'
12
+ YELLOW='\033[33m'
13
+ RED='\033[31m'
14
+ MAGENTA='\033[35m'
15
+ BOLD='\033[1m'
16
+ UNDERLINE='\033[4m'
17
+ DIM='\033[2m'
18
+ RESET='\033[0m'
19
+
20
+ # Caste colors (must match caste-colors.js)
21
+ get_caste_color() {
22
+ case "$1" in
23
+ builder) echo "$BLUE" ;;
24
+ watcher) echo "$GREEN" ;;
25
+ scout) echo "$YELLOW" ;;
26
+ chaos) echo "$RED" ;;
27
+ prime) echo "$MAGENTA" ;;
28
+ *) echo "$RESET" ;;
29
+ esac
30
+ }
31
+
32
+ # Caste emojis (must match aether-utils.sh)
33
+ get_caste_emoji() {
34
+ case "$1" in
35
+ builder) echo "🔨🐜" ;;
36
+ watcher) echo "👁️🐜" ;;
37
+ scout) echo "🔍🐜" ;;
38
+ chaos) echo "🎲🐜" ;;
39
+ prime) echo "👑🐜" ;;
40
+ *) echo "🐜" ;;
41
+ esac
42
+ }
43
+
44
+ # Animated status phrases
45
+ get_status_phrase() {
46
+ local caste="$1"
47
+ local idx=$(($(date +%s) % 4))
48
+ case "$caste" in
49
+ builder)
50
+ phrases=("excavating..." "building..." "forging..." "constructing...")
51
+ ;;
52
+ watcher)
53
+ phrases=("observing..." "monitoring..." "watching..." "tracking...")
54
+ ;;
55
+ scout)
56
+ phrases=("exploring..." "searching..." "investigating..." "probing...")
57
+ ;;
58
+ chaos)
59
+ phrases=("disrupting..." "testing..." "probing..." "stressing...")
60
+ ;;
61
+ *)
62
+ phrases=("working..." "foraging..." "excavating..." "tunneling...")
63
+ ;;
64
+ esac
65
+ echo "${phrases[$idx]}"
66
+ }
67
+
68
+ # Format tool usage: "📖5 🔍3 ✏️2 ⚡1"
69
+ format_tools() {
70
+ local read="${1:-0}"
71
+ local grep="${2:-0}"
72
+ local edit="${3:-0}"
73
+ local bash="${4:-0}"
74
+ local result=""
75
+ [[ "$read" -gt 0 ]] && result="${result}📖${read} "
76
+ [[ "$grep" -gt 0 ]] && result="${result}🔍${grep} "
77
+ [[ "$edit" -gt 0 ]] && result="${result}✏️${edit} "
78
+ [[ "$bash" -gt 0 ]] && result="${result}⚡${bash}"
79
+ echo "$result"
80
+ }
81
+
82
+ # Format duration from seconds
83
+ format_duration() {
84
+ local seconds="${1:-0}"
85
+ if [[ "$seconds" -lt 60 ]]; then
86
+ echo "${seconds}s"
87
+ else
88
+ local mins=$((seconds / 60))
89
+ local secs=$((seconds % 60))
90
+ echo "${mins}m${secs}s"
91
+ fi
92
+ }
93
+
94
+ # Render progress bar
95
+ render_progress_bar() {
96
+ local percent="${1:-0}"
97
+ local width="${2:-20}"
98
+
99
+ # Clamp percent to 0-100
100
+ [[ "$percent" -lt 0 ]] && percent=0
101
+ [[ "$percent" -gt 100 ]] && percent=100
102
+
103
+ local filled=$((percent * width / 100))
104
+ local empty=$((width - filled))
105
+
106
+ local bar=""
107
+ for ((i=0; i<filled; i++)); do bar+="█"; done
108
+ for ((i=0; i<empty; i++)); do bar+="░"; done
109
+
110
+ echo "[$bar] $percent%"
111
+ }
112
+
113
+ # Get animated spinner
114
+ get_spinner() {
115
+ local spinners=("⠋" "⠙" "⠹" "⠸" "⠼" "⠴" "⠦" "⠧" "⠇" "⠏")
116
+ local idx=$(($(date +%s) % 10))
117
+ echo "${spinners[$idx]}"
118
+ }
119
+
120
+ # Get excavation phrase based on progress
121
+ get_excavation_phrase() {
122
+ local caste="$1"
123
+ local progress="${2:-0}"
124
+
125
+ if [[ "$progress" -lt 25 ]]; then
126
+ echo "🚧 Starting excavation..."
127
+ elif [[ "$progress" -lt 50 ]]; then
128
+ echo "⛏️ Digging deeper..."
129
+ elif [[ "$progress" -lt 75 ]]; then
130
+ echo "🪨 Moving earth..."
131
+ elif [[ "$progress" -lt 100 ]]; then
132
+ echo "🏗️ Almost there..."
133
+ else
134
+ echo "✅ Excavation complete!"
135
+ fi
136
+ }
137
+
138
+ # Render the swarm display
139
+ render_swarm() {
140
+ clear
141
+
142
+ # Header
143
+ echo -e "${BOLD}${MAGENTA}"
144
+ cat << 'EOF'
145
+ .-.
146
+ (o o) AETHER COLONY
147
+ | O | Swarm Activity
148
+ `-`
149
+ EOF
150
+ echo -e "${RESET}"
151
+ echo -e "${DIM}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
152
+ echo ""
153
+
154
+ if [[ ! -f "$DISPLAY_FILE" ]]; then
155
+ echo -e "${DIM}Waiting for swarm activity...${RESET}"
156
+ echo ""
157
+ echo -e "${DIM}0 foragers excavating...${RESET}"
158
+ return
159
+ fi
160
+
161
+ # Read swarm data
162
+ local swarm_data=$(cat "$DISPLAY_FILE" 2>/dev/null)
163
+ if [[ -z "$swarm_data" ]]; then
164
+ echo -e "${DIM}No active swarm data${RESET}"
165
+ return
166
+ fi
167
+
168
+ # Check if we have active ants
169
+ local total_active=$(echo "$swarm_data" | jq -r '.summary.total_active // 0')
170
+
171
+ if [[ "$total_active" -eq 0 ]]; then
172
+ echo -e "${DIM}No active foragers${RESET}"
173
+ echo ""
174
+ echo -e "${DIM}0 foragers excavating...${RESET}"
175
+ return
176
+ fi
177
+
178
+ # Render each active ant
179
+ echo "$swarm_data" | jq -r '.active_ants[] |
180
+ "\(.name)|\(.caste)|\(.status)|\(.task // "")|\(.tools.read // 0)|\(.tools.grep // 0)|\(.tools.edit // 0)|\(.tools.bash // 0)|\(.tokens // 0)|\(.started_at // "")|\(.parent // "Queen")|\(.progress // 0)"' 2>/dev/null | \
181
+ while IFS='|' read -r name caste status task read_count grep_count edit_count bash_count tokens started_at parent progress; do
182
+ color=$(get_caste_color "$caste")
183
+ emoji=$(get_caste_emoji "$caste")
184
+ phrase=$(get_status_phrase "$caste")
185
+
186
+ # Parent ants: bold + underline
187
+ if [[ "$parent" == "Queen" ]] || [[ "$parent" == "Prime"* ]]; then
188
+ style="${BOLD}${UNDERLINE}"
189
+ else
190
+ style="${BOLD}"
191
+ fi
192
+
193
+ # Format tools
194
+ tools_str=$(format_tools "$read_count" "$grep_count" "$edit_count" "$bash_count")
195
+
196
+ # Calculate elapsed time
197
+ elapsed_str=""
198
+ if [[ -n "$started_at" ]]; then
199
+ started_ts=$(date -j -f "%Y-%m-%dT%H:%M:%SZ" "$started_at" +%s 2>/dev/null || date -d "$started_at" +%s 2>/dev/null || echo "0")
200
+ now_ts=$(date +%s)
201
+ elapsed=$((now_ts - started_ts))
202
+ if [[ $elapsed -gt 0 ]]; then
203
+ elapsed_str="${DIM}($(format_duration $elapsed))${RESET}"
204
+ fi
205
+ fi
206
+
207
+ # Trophallaxis (token) indicator
208
+ token_str=""
209
+ if [[ "$tokens" -gt 0 ]]; then
210
+ token_str="${DIM}🍯${tokens}${RESET}"
211
+ fi
212
+
213
+ # Truncate task if too long
214
+ display_task="$task"
215
+ [[ ${#display_task} -gt 35 ]] && display_task="${display_task:0:32}..."
216
+
217
+ # Output line: "🔨 Builder: excavating... Implement auth 📖5 🔍3 (2m3s) 🍯1250"
218
+ echo -e "${color}${emoji} ${style}${name}${RESET}${color}: ${phrase}${RESET} ${display_task}"
219
+ echo -e " ${tools_str} ${elapsed_str} ${token_str}"
220
+
221
+ # Show progress bar if progress > 0
222
+ if [[ "$progress" -gt 0 ]]; then
223
+ progress_bar=$(render_progress_bar "$progress" 15)
224
+ excavation_phrase=$(get_excavation_phrase "$caste" "$progress")
225
+ echo -e " ${DIM}${progress_bar}${RESET}"
226
+ echo -e " ${DIM}$(get_spinner) ${excavation_phrase}${RESET}"
227
+ fi
228
+
229
+ echo ""
230
+ done
231
+
232
+ # Chamber activity map (VIZ-07)
233
+ echo -e "${DIM}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
234
+ echo ""
235
+ echo -e "${BOLD}Chamber Activity:${RESET}"
236
+
237
+ # Show active chambers with fire intensity
238
+ echo "$swarm_data" | jq -r '.chambers | to_entries[] | "\(.key)|\(.value.activity)|\(.value.icon)"' 2>/dev/null | \
239
+ while IFS='|' read -r chamber activity icon; do
240
+ if [[ "$activity" -gt 0 ]]; then
241
+ # Fire intensity based on activity count
242
+ if [[ "$activity" -ge 5 ]]; then
243
+ fires="🔥🔥🔥"
244
+ elif [[ "$activity" -ge 3 ]]; then
245
+ fires="🔥🔥"
246
+ else
247
+ fires="🔥"
248
+ fi
249
+ echo -e " ${icon} ${chamber//_/ } ${fires} (${activity} ants)"
250
+ fi
251
+ done
252
+
253
+ # Summary line (VIZ-06: ant-themed presentation)
254
+ echo ""
255
+ echo -e "${DIM}${total_active} forager$([[ "$total_active" -eq 1 ]] || echo "s") excavating...${RESET}"
256
+ }
257
+
258
+ # Main loop with file watching
259
+ render_swarm
260
+
261
+ if command -v fswatch &>/dev/null; then
262
+ fswatch -o "$DISPLAY_FILE" 2>/dev/null | while read; do render_swarm; done
263
+ elif command -v inotifywait &>/dev/null; then
264
+ while inotifywait -q -e modify "$DISPLAY_FILE" 2>/dev/null; do render_swarm; done
265
+ else
266
+ # Fallback: poll every 2 seconds
267
+ while true; do sleep 2; render_swarm; done
268
+ fi
@@ -0,0 +1,253 @@
1
+ #!/bin/bash
2
+ # Live spawn tree visualization for tmux watch pane
3
+ # Usage: bash watch-spawn-tree.sh [data_dir]
4
+
5
+ DATA_DIR="${1:-.aether/data}"
6
+ SPAWN_FILE="$DATA_DIR/spawn-tree.txt"
7
+ VIEW_STATE_FILE="$DATA_DIR/view-state.json"
8
+
9
+ # ANSI colors
10
+ YELLOW='\033[33m'
11
+ GREEN='\033[32m'
12
+ RED='\033[31m'
13
+ CYAN='\033[36m'
14
+ MAGENTA='\033[35m'
15
+ BOLD='\033[1m'
16
+ DIM='\033[2m'
17
+ RESET='\033[0m'
18
+
19
+ # Caste emojis
20
+ get_emoji() {
21
+ case "$1" in
22
+ builder) echo "🔨" ;;
23
+ watcher) echo "👁️ " ;;
24
+ scout) echo "🔍" ;;
25
+ colonizer) echo "🗺️ " ;;
26
+ architect) echo "🏛️ " ;;
27
+ prime) echo "👑" ;;
28
+ *) echo "🐜" ;;
29
+ esac
30
+ }
31
+
32
+ # Load view state
33
+ load_view_state() {
34
+ if [[ -f "$VIEW_STATE_FILE" ]]; then
35
+ cat "$VIEW_STATE_FILE" 2>/dev/null || echo '{}'
36
+ else
37
+ echo '{"tunnel_view":{"expanded":[],"collapsed":["__depth_3_plus__"],"default_expand_depth":2,"show_completed":true}}'
38
+ fi
39
+ }
40
+
41
+ # Check if item is expanded
42
+ is_expanded() {
43
+ local item="$1"
44
+ local depth="${2:-1}"
45
+ local view_state=$(load_view_state)
46
+
47
+ # Check if explicitly expanded
48
+ if echo "$view_state" | jq -e ".tunnel_view.expanded | contains([\"$item\"])" >/dev/null 2>&1; then
49
+ return 0
50
+ fi
51
+
52
+ # Check if depth-based auto-collapse applies
53
+ local default_depth=$(echo "$view_state" | jq -r '.tunnel_view.default_expand_depth // 2')
54
+ if [[ "$depth" -gt "$default_depth" ]]; then
55
+ # Check if __depth_3_plus__ is in collapsed (indicating auto-collapse enabled)
56
+ if echo "$view_state" | jq -e '.tunnel_view.collapsed | contains(["__depth_3_plus__"])' >/dev/null 2>&1; then
57
+ return 1 # Collapsed by depth
58
+ fi
59
+ fi
60
+
61
+ # Check if explicitly collapsed
62
+ if echo "$view_state" | jq -e ".tunnel_view.collapsed | contains([\"$item\"])" >/dev/null 2>&1; then
63
+ return 1
64
+ fi
65
+
66
+ return 0 # Default to expanded
67
+ }
68
+
69
+ # Status colors
70
+ get_status_color() {
71
+ case "$1" in
72
+ completed) echo "$GREEN" ;;
73
+ failed) echo "$RED" ;;
74
+ spawned) echo "$YELLOW" ;;
75
+ *) echo "$CYAN" ;;
76
+ esac
77
+ }
78
+
79
+ render_tree() {
80
+ clear
81
+
82
+ # Header
83
+ echo -e "${BOLD}${CYAN}"
84
+ cat << 'EOF'
85
+ .-.
86
+ (o o) AETHER COLONY
87
+ | O | Spawn Tree (Collapsible)
88
+ `-`
89
+ EOF
90
+ echo -e "${RESET}"
91
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
92
+ echo ""
93
+
94
+ # Always show Queen at depth 0
95
+ echo -e " ${BOLD}👑 Queen${RESET} ${DIM}(depth 0)${RESET}"
96
+ echo -e " ${DIM}│${RESET}"
97
+
98
+ if [[ ! -f "$SPAWN_FILE" ]]; then
99
+ echo -e " ${DIM}└── (no workers spawned yet)${RESET}"
100
+ return
101
+ fi
102
+
103
+ # Parse spawn tree file
104
+ # Format: timestamp|parent_id|child_caste|child_name|task_summary|status
105
+ declare -A workers
106
+ declare -A worker_status
107
+ declare -A worker_task
108
+ declare -A worker_caste
109
+ declare -a roots
110
+
111
+ while IFS='|' read -r ts parent caste name task status rest; do
112
+ [[ -z "$name" ]] && continue
113
+
114
+ # Check if this is a status update (only 4 fields)
115
+ if [[ -z "$task" && -n "$caste" ]]; then
116
+ # This is a status update: ts|name|status|summary
117
+ worker_status["$parent"]="$caste"
118
+ continue
119
+ fi
120
+
121
+ workers["$name"]="$parent"
122
+ worker_caste["$name"]="$caste"
123
+ worker_task["$name"]="$task"
124
+ worker_status["$name"]="${status:-spawned}"
125
+
126
+ # Track root workers (spawned by Prime or Queen)
127
+ if [[ "$parent" == "Prime"* || "$parent" == "prime"* || "$parent" == "Queen" ]]; then
128
+ roots+=("$name")
129
+ fi
130
+ done < "$SPAWN_FILE"
131
+
132
+ # Render workers in tree structure
133
+ # Group by parent to show hierarchy
134
+ printed=()
135
+
136
+ # Function to render a worker and its children
137
+ render_worker() {
138
+ local name="$1"
139
+ local indent="$2"
140
+ local depth="$3"
141
+ local is_last="$4"
142
+
143
+ [[ " ${printed[*]} " =~ " $name " ]] && return
144
+ printed+=("$name")
145
+
146
+ emoji=$(get_emoji "${worker_caste[$name]}")
147
+ status="${worker_status[$name]}"
148
+ color=$(get_status_color "$status")
149
+ task="${worker_task[$name]}"
150
+
151
+ # Check if collapsed
152
+ local collapsed=false
153
+ local child_count=0
154
+
155
+ # Count children
156
+ for child in "${!workers[@]}"; do
157
+ if [[ "${workers[$child]}" == "$name" ]]; then
158
+ child_count=$((child_count + 1))
159
+ fi
160
+ done
161
+
162
+ # Check collapse state (only if has children)
163
+ if [[ $child_count -gt 0 ]] && ! is_expanded "$name" "$depth"; then
164
+ collapsed=true
165
+ fi
166
+
167
+ # Truncate task for display
168
+ [[ ${#task} -gt 30 ]] && task="${task:0:27}..."
169
+
170
+ # Tree connectors
171
+ if [[ "$is_last" == "true" ]]; then
172
+ connector="└──"
173
+ else
174
+ connector="├──"
175
+ fi
176
+
177
+ # Show expand/collapse indicator
178
+ local expand_indicator=""
179
+ if [[ $child_count -gt 0 ]]; then
180
+ if [[ "$collapsed" == "true" ]]; then
181
+ expand_indicator="▶ [$child_count hidden] "
182
+ else
183
+ expand_indicator="▼ "
184
+ fi
185
+ fi
186
+
187
+ echo -e "${indent}${DIM}${connector}${RESET} ${emoji} ${color}${name}${RESET}: ${expand_indicator}${task} ${DIM}[depth $depth]${RESET}"
188
+
189
+ # Render children if not collapsed
190
+ if [[ "$collapsed" != "true" ]]; then
191
+ local children=()
192
+ for child in "${!workers[@]}"; do
193
+ if [[ "${workers[$child]}" == "$name" ]]; then
194
+ children+=("$child")
195
+ fi
196
+ done
197
+
198
+ local child_count=${#children[@]}
199
+ local child_idx=0
200
+ for child in "${children[@]}"; do
201
+ child_idx=$((child_idx + 1))
202
+ local child_is_last="false"
203
+ [[ $child_idx -eq $child_count ]] && child_is_last="true"
204
+
205
+ local child_indent="${indent} "
206
+ if [[ "$is_last" != "true" ]]; then
207
+ child_indent="${indent}${DIM}│${RESET} "
208
+ fi
209
+
210
+ render_worker "$child" "$child_indent" $((depth + 1)) "$child_is_last"
211
+ done
212
+ fi
213
+ }
214
+
215
+ # Render root workers (spawned by Queen) at depth 1
216
+ local root_count=${#roots[@]}
217
+ local root_idx=0
218
+ for name in "${roots[@]}"; do
219
+ root_idx=$((root_idx + 1))
220
+ local is_last="false"
221
+ [[ $root_idx -eq $root_count ]] && is_last="true"
222
+ render_worker "$name" " " 1 "$is_last"
223
+ done
224
+
225
+ # Summary
226
+ echo ""
227
+ echo -e "${DIM}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
228
+ completed=$(grep -c "completed" "$SPAWN_FILE" 2>/dev/null || echo "0")
229
+ active=$(grep -c "spawned" "$SPAWN_FILE" 2>/dev/null || echo "0")
230
+ echo -e "Workers: ${GREEN}$completed completed${RESET} | ${YELLOW}$active active${RESET}"
231
+ echo ""
232
+ echo -e "${DIM}Controls: e+<name> to expand, c+<name> to collapse${RESET}"
233
+ }
234
+
235
+ # Initial render
236
+ render_tree
237
+
238
+ # Watch for changes and re-render
239
+ if command -v fswatch &>/dev/null; then
240
+ fswatch -o "$SPAWN_FILE" 2>/dev/null | while read; do
241
+ render_tree
242
+ done
243
+ elif command -v inotifywait &>/dev/null; then
244
+ while inotifywait -q -e modify "$SPAWN_FILE" 2>/dev/null; do
245
+ render_tree
246
+ done
247
+ else
248
+ # Fallback: poll every 2 seconds
249
+ while true; do
250
+ sleep 2
251
+ render_tree
252
+ done
253
+ fi