aether-colony 1.1.5 → 1.1.8

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 (65) hide show
  1. package/.aether/aether-utils.sh +152 -53
  2. package/.aether/docs/command-playbooks/build-complete.md +0 -5
  3. package/.aether/docs/command-playbooks/build-context.md +5 -3
  4. package/.aether/docs/command-playbooks/build-full.md +14 -44
  5. package/.aether/docs/command-playbooks/build-prep.md +0 -6
  6. package/.aether/docs/command-playbooks/build-verify.md +13 -12
  7. package/.aether/docs/command-playbooks/build-wave.md +12 -31
  8. package/.aether/docs/command-playbooks/continue-finalize.md +28 -18
  9. package/.aether/docs/command-playbooks/continue-full.md +31 -44
  10. package/.aether/docs/command-playbooks/continue-gates.md +4 -16
  11. package/.aether/docs/command-playbooks/continue-verify.md +2 -16
  12. package/.aether/utils/atomic-write.sh +6 -6
  13. package/.aether/utils/file-lock.sh +52 -21
  14. package/.aether/workers.md +9 -1
  15. package/.claude/commands/ant/archaeology.md +0 -8
  16. package/.claude/commands/ant/chaos.md +0 -14
  17. package/.claude/commands/ant/colonize.md +0 -14
  18. package/.claude/commands/ant/council.md +0 -15
  19. package/.claude/commands/ant/dream.md +0 -17
  20. package/.claude/commands/ant/entomb.md +3 -15
  21. package/.claude/commands/ant/help.md +13 -0
  22. package/.claude/commands/ant/init.md +0 -22
  23. package/.claude/commands/ant/lay-eggs.md +0 -11
  24. package/.claude/commands/ant/maturity.md +11 -10
  25. package/.claude/commands/ant/oracle.md +0 -17
  26. package/.claude/commands/ant/organize.md +0 -22
  27. package/.claude/commands/ant/pause-colony.md +0 -15
  28. package/.claude/commands/ant/pheromones.md +0 -15
  29. package/.claude/commands/ant/plan.md +1 -37
  30. package/.claude/commands/ant/resume-colony.md +0 -15
  31. package/.claude/commands/ant/seal.md +0 -16
  32. package/.claude/commands/ant/swarm.md +10 -23
  33. package/.claude/commands/ant/update.md +56 -139
  34. package/.opencode/agents/aether-ambassador.md +1 -1
  35. package/.opencode/agents/aether-builder.md +2 -2
  36. package/.opencode/agents/aether-queen.md +1 -1
  37. package/.opencode/agents/aether-route-setter.md +1 -1
  38. package/.opencode/agents/aether-surveyor-disciplines.md +6 -1
  39. package/.opencode/agents/aether-surveyor-nest.md +6 -1
  40. package/.opencode/agents/aether-surveyor-pathogens.md +6 -1
  41. package/.opencode/agents/aether-surveyor-provisions.md +6 -1
  42. package/.opencode/agents/aether-tracker.md +1 -1
  43. package/.opencode/agents/aether-watcher.md +1 -1
  44. package/.opencode/agents/aether-weaver.md +1 -1
  45. package/.opencode/commands/ant/archaeology.md +0 -8
  46. package/.opencode/commands/ant/build.md +8 -62
  47. package/.opencode/commands/ant/chaos.md +0 -18
  48. package/.opencode/commands/ant/colonize.md +1 -18
  49. package/.opencode/commands/ant/continue.md +518 -62
  50. package/.opencode/commands/ant/council.md +0 -18
  51. package/.opencode/commands/ant/dream.md +0 -19
  52. package/.opencode/commands/ant/entomb.md +0 -18
  53. package/.opencode/commands/ant/init.md +0 -20
  54. package/.opencode/commands/ant/lay-eggs.md +0 -18
  55. package/.opencode/commands/ant/oracle.md +1 -24
  56. package/.opencode/commands/ant/pause-colony.md +0 -18
  57. package/.opencode/commands/ant/pheromones.md +8 -17
  58. package/.opencode/commands/ant/plan.md +2 -35
  59. package/.opencode/commands/ant/resume-colony.md +0 -18
  60. package/.opencode/commands/ant/seal.md +0 -18
  61. package/.opencode/commands/ant/swarm.md +0 -23
  62. package/.opencode/commands/ant/update.md +55 -131
  63. package/bin/cli.js +67 -2
  64. package/bin/lib/update-transaction.js +112 -3
  65. package/package.json +1 -1
@@ -1078,7 +1078,14 @@ case "$cmd" in
1078
1078
  HELP_EOF
1079
1079
  ;;
1080
1080
  version)
1081
- json_ok '"1.0.0"'
1081
+ # Read version from package.json if available, fallback to embedded
1082
+ _pkg_json="$SCRIPT_DIR/../package.json"
1083
+ if [[ -f "$_pkg_json" ]] && command -v jq >/dev/null 2>&1; then
1084
+ _ver=$(jq -r '.version // "unknown"' "$_pkg_json" 2>/dev/null)
1085
+ json_ok "\"$_ver\""
1086
+ else
1087
+ json_ok '"1.1.5"'
1088
+ fi
1082
1089
  ;;
1083
1090
  validate-state)
1084
1091
  # Schema migration helper: auto-upgrades pre-3.0 state files to v3.0
@@ -3428,6 +3435,22 @@ NODESCRIPT
3428
3435
 
3429
3436
  [[ -z "$ant_name" || -z "$caste" || -z "$ant_status" ]] && json_err "$E_VALIDATION_FAILED" "Usage: swarm-display-update <ant_name> <caste> <ant_status> <task> [parent] [tools_json] [tokens] [chamber] [progress]"
3430
3437
 
3438
+ # Tolerate malformed argument ordering from LLM-generated commands.
3439
+ # Common failure mode: tools_json omitted, so tokens/chamber/progress shift left.
3440
+ tools_type=$(echo "$tools_json" | jq -r 'type' 2>/dev/null || echo "invalid")
3441
+ if [[ "$tools_type" != "object" ]]; then
3442
+ if [[ "$tools_json" =~ ^[0-9]+$ ]] && [[ ! "$tokens" =~ ^[0-9]+$ ]] && [[ "$chamber" =~ ^[0-9]+$ ]]; then
3443
+ progress="$chamber"
3444
+ chamber="$tokens"
3445
+ tokens="$tools_json"
3446
+ fi
3447
+ tools_json="{}"
3448
+ fi
3449
+
3450
+ # Ensure numeric fields are always valid for --argjson.
3451
+ [[ "$tokens" =~ ^-?[0-9]+$ ]] || tokens=0
3452
+ [[ "$progress" =~ ^-?[0-9]+$ ]] || progress=0
3453
+
3431
3454
  display_file="$DATA_DIR/swarm-display.json"
3432
3455
 
3433
3456
  # Initialize if doesn't exist
@@ -3489,7 +3512,7 @@ NODESCRIPT
3489
3512
  # Update chamber activity counts
3490
3513
  # Decrement old chamber if changed
3491
3514
  (if $old_chamber != "" and $old_chamber != $new_chamber and has("chambers") and (.chambers | has($old_chamber)) then
3492
- .chambers[$old_chamber].activity = [(.chambers[$old_chamber].activity // 1) - 1, 0] | max
3515
+ .chambers[$old_chamber].activity = ([(.chambers[$old_chamber].activity // 1) - 1, 0] | max)
3493
3516
  else
3494
3517
  .
3495
3518
  end) |
@@ -6339,7 +6362,7 @@ $updated_meta
6339
6362
  normalize-args)
6340
6363
  # Normalize arguments from Claude Code ($ARGUMENTS) or OpenCode ($@)
6341
6364
  # Usage: bash .aether/aether-utils.sh normalize-args [args...]
6342
- # Or: eval "$(bash .aether/aether-utils.sh normalize-args)"
6365
+ # Returns: a plain normalized argument string (safe for direct string parsing)
6343
6366
  #
6344
6367
  # Claude Code passes args in $ARGUMENTS variable
6345
6368
  # OpenCode passes args in $@ (positional parameters)
@@ -6352,21 +6375,17 @@ $updated_meta
6352
6375
  normalized="$ARGUMENTS"
6353
6376
  # Fall back to OpenCode style ($@ positional params)
6354
6377
  elif [ $# -gt 0 ]; then
6355
- # Preserve arguments with spaces by quoting
6356
- for arg in "$@"; do
6357
- if [[ "$arg" == *" "* ]] || [[ "$arg" == *"\t"* ]] || [[ "$arg" == *"\n"* ]]; then
6358
- # Quote arguments containing whitespace
6359
- normalized="$normalized \"$arg\""
6360
- else
6361
- normalized="$normalized $arg"
6362
- fi
6363
- done
6364
- # Trim leading space
6365
- normalized="${normalized# }"
6378
+ # Join positional args into one parseable string without adding synthetic quotes
6379
+ normalized="$*"
6380
+ fi
6381
+
6382
+ # Collapse line breaks and repeated whitespace to avoid shell parse edge cases
6383
+ if [[ -n "$normalized" ]]; then
6384
+ normalized="$(printf '%s' "$normalized" | tr '\r\n' ' ' | sed 's/[[:space:]][[:space:]]*/ /g; s/^ //; s/ $//')"
6366
6385
  fi
6367
6386
 
6368
6387
  # Output normalized arguments
6369
- echo "$normalized"
6388
+ printf '%s\n' "$normalized"
6370
6389
  exit 0
6371
6390
  ;;
6372
6391
 
@@ -6616,9 +6635,9 @@ $updated_meta
6616
6635
  json_ok "{\"command\":\"$command_name\",\"cleared\":\"${cleared// /}\",\"errors\":\"${errors// /}\",\"dry_run\":$([[ "$dry_run" == "--dry-run" ]] && echo "true" || echo "false")}"
6617
6636
  ;;
6618
6637
 
6619
- pheromone-export)
6620
- # Export pheromones to eternal XML format
6621
- # Usage: pheromone-export [input_json] [output_xml]
6638
+ pheromone-export-eternal)
6639
+ # Export pheromones to eternal XML format (distinct from xml-utils.sh pheromone-export function)
6640
+ # Usage: pheromone-export-eternal [input_json] [output_xml]
6622
6641
  # input_json: Path to pheromones.json (default: .aether/data/pheromones.json)
6623
6642
  # output_xml: Path to output XML (default: ~/.aether/eternal/pheromones.xml)
6624
6643
 
@@ -6719,9 +6738,9 @@ $updated_meta
6719
6738
 
6720
6739
  # Generate ID and timestamps
6721
6740
  pw_epoch=$(date +%s)
6722
- pw_epoch_ms="${pw_epoch}000"
6741
+ pw_rand=$(( RANDOM % 10000 ))
6723
6742
  pw_type_lower=$(echo "$pw_type" | tr '[:upper:]' '[:lower:]')
6724
- pw_id="sig_${pw_type_lower}_${pw_epoch_ms}"
6743
+ pw_id="sig_${pw_type_lower}_${pw_epoch}_${pw_rand}"
6725
6744
  pw_created=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
6726
6745
 
6727
6746
  # Compute expires_at from TTL
@@ -7811,28 +7830,43 @@ $updated_meta
7811
7830
  printf '%s\n' '{"version":"1.0.0","entries":[]}' > "$mw_midden_file"
7812
7831
  fi
7813
7832
 
7814
- # Create the new entry
7815
- mw_new_entry=$(printf '{
7816
- "id": "%s",
7817
- "timestamp": "%s",
7818
- "category": "%s",
7819
- "source": "%s",
7820
- "message": "%s",
7821
- "reviewed": false
7822
- }' "$mw_entry_id" "$mw_timestamp" "$mw_category" "$mw_source" "$mw_message")
7823
-
7824
- # Append to midden.json using jq
7825
- mw_updated_midden=$(jq --argjson entry "$mw_new_entry" '
7826
- .entries += [$entry] |
7827
- .entry_count = (.entries | length)
7828
- ' "$mw_midden_file" 2>/dev/null)
7829
-
7830
- if [[ -n "$mw_updated_midden" ]]; then
7831
- printf '%s\n' "$mw_updated_midden" > "$mw_midden_file"
7832
- json_ok "{\"success\":true,\"entry_id\":\"$mw_entry_id\",\"category\":\"$mw_category\",\"midden_total\":$(jq '.entries | length' "$mw_midden_file" 2>/dev/null || echo 0)}"
7833
+ # Create the new entry using jq for safe JSON construction
7834
+ mw_new_entry=$(jq -n \
7835
+ --arg id "$mw_entry_id" \
7836
+ --arg ts "$mw_timestamp" \
7837
+ --arg cat "$mw_category" \
7838
+ --arg src "$mw_source" \
7839
+ --arg msg "$mw_message" \
7840
+ '{id: $id, timestamp: $ts, category: $cat, source: $src, message: $msg, reviewed: false}')
7841
+
7842
+ # Append to midden.json using jq with locking
7843
+ if acquire_lock "$mw_midden_file" 2>/dev/null; then
7844
+ mw_updated_midden=$(jq --argjson entry "$mw_new_entry" '
7845
+ .entries += [$entry] |
7846
+ .entry_count = (.entries | length)
7847
+ ' "$mw_midden_file" 2>/dev/null)
7848
+
7849
+ if [[ -n "$mw_updated_midden" ]]; then
7850
+ printf '%s\n' "$mw_updated_midden" > "$mw_midden_file.tmp" && mv "$mw_midden_file.tmp" "$mw_midden_file"
7851
+ release_lock 2>/dev/null || true
7852
+ json_ok "{\"success\":true,\"entry_id\":\"$mw_entry_id\",\"category\":\"$mw_category\",\"midden_total\":$(jq '.entries | length' "$mw_midden_file" 2>/dev/null || echo 0)}"
7853
+ else
7854
+ release_lock 2>/dev/null || true
7855
+ json_ok "{\"success\":true,\"warning\":\"jq_processing_failed\",\"entry_id\":null}"
7856
+ fi
7833
7857
  else
7834
- # jq failed, but we still return success (graceful degradation)
7835
- json_ok "{\"success\":true,\"warning\":\"jq_processing_failed\",\"entry_id\":null}"
7858
+ # Lock failed graceful degradation, try without lock
7859
+ mw_updated_midden=$(jq --argjson entry "$mw_new_entry" '
7860
+ .entries += [$entry] |
7861
+ .entry_count = (.entries | length)
7862
+ ' "$mw_midden_file" 2>/dev/null)
7863
+
7864
+ if [[ -n "$mw_updated_midden" ]]; then
7865
+ printf '%s\n' "$mw_updated_midden" > "$mw_midden_file.tmp" && mv "$mw_midden_file.tmp" "$mw_midden_file"
7866
+ json_ok "{\"success\":true,\"entry_id\":\"$mw_entry_id\",\"category\":\"$mw_category\",\"warning\":\"lock_unavailable\"}"
7867
+ else
7868
+ json_ok "{\"success\":true,\"warning\":\"jq_processing_failed\",\"entry_id\":null}"
7869
+ fi
7836
7870
  fi
7837
7871
  ;;
7838
7872
 
@@ -8543,7 +8577,7 @@ $updated_meta
8543
8577
  session_file="$DATA_DIR/session.json"
8544
8578
  baseline=$(git rev-parse HEAD 2>/dev/null || echo "")
8545
8579
 
8546
- cat > "$session_file" << EOF
8580
+ cat > "$session_file.tmp" << EOF
8547
8581
  {
8548
8582
  "session_id": "$session_id",
8549
8583
  "started_at": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
@@ -8560,15 +8594,16 @@ $updated_meta
8560
8594
  "summary": "Session initialized"
8561
8595
  }
8562
8596
  EOF
8597
+ mv "$session_file.tmp" "$session_file"
8563
8598
  json_ok "{\"session_id\":\"$session_id\",\"goal\":\"$goal\",\"file\":\"$session_file\"}"
8564
8599
  ;;
8565
8600
 
8566
8601
  session-update)
8567
8602
  # Update session with latest activity
8568
8603
  # Usage: session-update <command> [suggested_next] [summary]
8569
- cmd_run="${2:-}"
8570
- suggested="${3:-}"
8571
- summary="${4:-}"
8604
+ cmd_run="${1:-}"
8605
+ suggested="${2:-}"
8606
+ summary="${3:-}"
8572
8607
 
8573
8608
  session_file="$DATA_DIR/session.json"
8574
8609
 
@@ -8619,7 +8654,7 @@ EOF
8619
8654
  .current_phase = $phase |
8620
8655
  .current_milestone = $milestone |
8621
8656
  .active_todos = $todos |
8622
- .baseline_commit = $baseline' > "$session_file"
8657
+ .baseline_commit = $baseline' > "$session_file.tmp" && mv "$session_file.tmp" "$session_file"
8623
8658
 
8624
8659
  json_ok "{\"updated\":true,\"command\":\"$cmd_run\"}"
8625
8660
  ;;
@@ -8640,7 +8675,9 @@ EOF
8640
8675
  last_cmd_ts=$(echo "$session_data" | jq -r '.last_command_at // .started_at // empty')
8641
8676
  if [[ -n "$last_cmd_ts" ]]; then
8642
8677
  last_epoch=0 now_epoch=0
8643
- last_epoch=$(date -j -f "%Y-%m-%dT%H:%M:%SZ" "$last_cmd_ts" +%s 2>/dev/null || echo 0)
8678
+ last_epoch=$(date -j -f "%Y-%m-%dT%H:%M:%SZ" "$last_cmd_ts" +%s 2>/dev/null \
8679
+ || date -d "$last_cmd_ts" +%s 2>/dev/null \
8680
+ || echo 0)
8644
8681
  now_epoch=$(date +%s)
8645
8682
  age_hours=$(( (now_epoch - last_epoch) / 3600 ))
8646
8683
  [[ $age_hours -gt 24 ]] && is_stale=true || is_stale=false
@@ -8668,7 +8705,10 @@ EOF
8668
8705
  exit 0
8669
8706
  fi
8670
8707
 
8671
- last_epoch=$(date -j -f "%Y-%m-%dT%H:%M:%SZ" "$last_cmd_ts" +%s 2>/dev/null || echo 0)
8708
+ # macOS uses -j -f, Linux uses -d
8709
+ last_epoch=$(date -j -f "%Y-%m-%dT%H:%M:%SZ" "$last_cmd_ts" +%s 2>/dev/null \
8710
+ || date -d "$last_cmd_ts" +%s 2>/dev/null \
8711
+ || echo 0)
8672
8712
  now_epoch=$(date +%s)
8673
8713
  age_hours=$(( (now_epoch - last_epoch) / 3600 ))
8674
8714
 
@@ -8679,8 +8719,8 @@ EOF
8679
8719
  fi
8680
8720
  ;;
8681
8721
 
8682
- session-clear)
8683
- # Mark session as cleared (preserves file but marks context_cleared)
8722
+ session-clear-context)
8723
+ # Mark session context as cleared (preserves file but marks context_cleared)
8684
8724
  preserve="${2:-false}"
8685
8725
  session_file="$DATA_DIR/session.json"
8686
8726
 
@@ -8799,18 +8839,77 @@ EOF
8799
8839
  # ============================================
8800
8840
 
8801
8841
  force-unlock)
8802
- # Emergency lock cleanup — removes all lock files
8803
- # Usage: force-unlock [--yes]
8842
+ # Emergency lock cleanup — remove all locks or stale-only locks
8843
+ # Usage: force-unlock [--yes] [--stale-only]
8804
8844
  # Without --yes, lists locks and asks for confirmation in interactive mode
8805
8845
  lock_dir="${AETHER_ROOT:-.}/.aether/locks"
8806
8846
  auto_yes=false
8807
- [[ "${1:-}" == "--yes" ]] && auto_yes=true
8847
+ stale_only=false
8848
+
8849
+ while [[ $# -gt 0 ]]; do
8850
+ case "$1" in
8851
+ --yes) auto_yes=true ;;
8852
+ --stale-only) stale_only=true ;;
8853
+ esac
8854
+ shift
8855
+ done
8808
8856
 
8809
8857
  if [[ ! -d "$lock_dir" ]]; then
8810
8858
  json_ok '{"removed":0,"message":"No locks directory found"}'
8811
8859
  exit 0
8812
8860
  fi
8813
8861
 
8862
+ if [[ "$stale_only" == "true" ]]; then
8863
+ lock_timeout="${LOCK_TIMEOUT:-300}"
8864
+ scanned=0
8865
+ removed=0
8866
+ skipped_live=0
8867
+
8868
+ is_lock_stale_for_cleanup() {
8869
+ local _lock_file="$1"
8870
+ local _pid_file="${_lock_file}.pid"
8871
+ local _pid
8872
+ _pid=$(cat "$_pid_file" 2>/dev/null || echo "")
8873
+ if [[ -z "$_pid" ]]; then
8874
+ _pid=$(cat "$_lock_file" 2>/dev/null || echo "")
8875
+ fi
8876
+ _pid=$(echo "$_pid" | tr -d '[:space:]')
8877
+ [[ "$_pid" =~ ^[0-9]+$ ]] || _pid=""
8878
+
8879
+ if [[ -n "$_pid" ]]; then
8880
+ kill -0 "$_pid" 2>/dev/null && return 1
8881
+ return 0
8882
+ fi
8883
+
8884
+ local _mtime=0
8885
+ if stat -f %m "$_lock_file" >/dev/null 2>&1; then
8886
+ _mtime=$(stat -f %m "$_lock_file" 2>/dev/null || echo 0)
8887
+ else
8888
+ _mtime=$(stat -c %Y "$_lock_file" 2>/dev/null || echo 0)
8889
+ fi
8890
+ local _age=$(( $(date +%s) - _mtime ))
8891
+ [[ "$_age" -gt "$lock_timeout" ]]
8892
+ }
8893
+
8894
+ for lock_file in "$lock_dir"/*.lock; do
8895
+ [[ -e "$lock_file" ]] || continue
8896
+ scanned=$((scanned + 1))
8897
+ if is_lock_stale_for_cleanup "$lock_file"; then
8898
+ rm -f "$lock_file" "${lock_file}.pid" 2>/dev/null || true
8899
+ removed=$((removed + 1))
8900
+ else
8901
+ skipped_live=$((skipped_live + 1))
8902
+ fi
8903
+ done
8904
+
8905
+ if [[ "$removed" -eq 0 && "$scanned" -eq 0 ]]; then
8906
+ json_ok '{"removed":0,"scanned":0,"skipped_live":0,"message":"No lock files found","mode":"stale-only"}'
8907
+ else
8908
+ json_ok "{\"removed\":$removed,\"scanned\":$scanned,\"skipped_live\":$skipped_live,\"message\":\"Stale locks cleared\",\"mode\":\"stale-only\"}"
8909
+ fi
8910
+ exit 0
8911
+ fi
8912
+
8814
8913
  lock_files=$(find "$lock_dir" -name "*.lock" -o -name "*.lock.pid" 2>/dev/null)
8815
8914
 
8816
8915
  if [[ -z "$lock_files" ]]; then
@@ -251,11 +251,6 @@ Note: This runs regardless of build success/failure. Failed builds may have reco
251
251
 
252
252
  **This step runs ONLY after synthesis is complete. All values come from actual worker results.**
253
253
 
254
- **Update swarm display state (always) and render (in-conversation):**
255
- Run using the Bash tool with description "Recording build completion...": `bash .aether/aether-utils.sh swarm-display-update "Queen" "prime" "completed" "Phase {id} complete" "Colony" '{"read":10,"grep":5,"edit":5,"bash":2}' 100 "fungus_garden" 100`
256
-
257
- If `visual_mode` is true, also run using the Bash tool with description "Rendering final swarm display...": `bash .aether/aether-utils.sh swarm-display-text "$build_id"`
258
-
259
254
  **Display BUILD SUMMARY (always shown, replaces compact/verbose split):**
260
255
 
261
256
  Calculate `total_tools` by summing `tool_count` from all worker return JSONs (builders + watcher + chaos).
@@ -127,7 +127,7 @@ log a warning and continue to Step 5.
127
127
 
128
128
  Generate archaeologist name and dispatch:
129
129
  Run using the Bash tool with description "Naming archaeologist...": `bash .aether/aether-utils.sh generate-ant-name "archaeologist"` (store as `{archaeologist_name}`)
130
- Run using the Bash tool with description "Dispatching archaeologist...": `bash .aether/aether-utils.sh spawn-log "Queen" "scout" "{archaeologist_name}" "Pre-build archaeology scan" && bash .aether/aether-utils.sh swarm-display-update "{archaeologist_name}" "scout" "excavating" "Pre-build archaeology scan" "Queen" '{"read":0,"grep":0,"edit":0,"bash":0}' 0 "fungus_garden" 15`
130
+ Run using the Bash tool with description "Dispatching archaeologist...": `bash .aether/aether-utils.sh spawn-log "Queen" "scout" "{archaeologist_name}" "Pre-build archaeology scan"`
131
131
 
132
132
  Display:
133
133
  ```
@@ -135,6 +135,8 @@ log a warning and continue to Step 5.
135
135
  Scanning history of files to be modified...
136
136
  ```
137
137
 
138
+ > **Platform note**: In Claude Code, use `Task tool with subagent_type`. In OpenCode, use the equivalent agent spawning mechanism for your platform (e.g., invoke the agent definition from `.opencode/agents/`).
139
+
138
140
  Spawn a Scout (using Task tool with `subagent_type="aether-archaeologist"`, include `description: "🏺 Archaeologist {archaeologist_name}: Pre-build history scan"`) with this prompt:
139
141
  # FALLBACK: If "Agent type not found", use general-purpose and inject role: "You are an Archaeologist Ant - git historian that excavates why code exists."
140
142
 
@@ -164,8 +166,8 @@ log a warning and continue to Step 5.
164
166
 
165
167
  **Wait for results** (blocking — use TaskOutput with `block: true`).
166
168
 
167
- Log completion and update swarm display:
168
- Run using the Bash tool with description "Recording archaeologist findings...": `bash .aether/aether-utils.sh spawn-complete "{archaeologist_name}" "completed" "Pre-build archaeology scan" && bash .aether/aether-utils.sh swarm-display-update "{archaeologist_name}" "scout" "completed" "Pre-build archaeology scan" "Queen" '{"read":8,"grep":5,"edit":0,"bash":2}' 100 "fungus_garden" 100`
169
+ Log completion:
170
+ Run using the Bash tool with description "Recording archaeologist findings...": `bash .aether/aether-utils.sh spawn-complete "{archaeologist_name}" "completed" "Pre-build archaeology scan"`
169
171
 
170
172
  3. **Store and display findings:**
171
173
 
@@ -74,12 +74,6 @@ Do not touch during build:
74
74
  - Other agents' config files (only modify files assigned to the current build task)
75
75
  </read_only>
76
76
 
77
- ### Step 0: Version Check (Non-blocking)
78
-
79
- Run using the Bash tool with description "Checking colony version...": `bash .aether/aether-utils.sh version-check-cached 2>/dev/null || true`
80
-
81
- If the command succeeds and the JSON result contains a non-empty string, display it as a one-line notice. Proceed regardless of outcome.
82
-
83
77
  ### Step 0.6: Verify LiteLLM Proxy
84
78
 
85
79
  Check that the LiteLLM proxy is running for model routing:
@@ -381,7 +375,7 @@ log a warning and continue to Step 5.
381
375
 
382
376
  Generate archaeologist name and dispatch:
383
377
  Run using the Bash tool with description "Naming archaeologist...": `bash .aether/aether-utils.sh generate-ant-name "archaeologist"` (store as `{archaeologist_name}`)
384
- Run using the Bash tool with description "Dispatching archaeologist...": `bash .aether/aether-utils.sh spawn-log "Queen" "scout" "{archaeologist_name}" "Pre-build archaeology scan" && bash .aether/aether-utils.sh swarm-display-update "{archaeologist_name}" "scout" "excavating" "Pre-build archaeology scan" "Queen" '{"read":0,"grep":0,"edit":0,"bash":0}' 0 "fungus_garden" 15`
378
+ Run using the Bash tool with description "Dispatching archaeologist...": `bash .aether/aether-utils.sh spawn-log "Queen" "scout" "{archaeologist_name}" "Pre-build archaeology scan"`
385
379
 
386
380
  Display:
387
381
  ```
@@ -419,7 +413,7 @@ log a warning and continue to Step 5.
419
413
  **Wait for results** (blocking — use TaskOutput with `block: true`).
420
414
 
421
415
  Log completion and update swarm display:
422
- Run using the Bash tool with description "Recording archaeologist findings...": `bash .aether/aether-utils.sh spawn-complete "{archaeologist_name}" "completed" "Pre-build archaeology scan" && bash .aether/aether-utils.sh swarm-display-update "{archaeologist_name}" "scout" "completed" "Pre-build archaeology scan" "Queen" '{"read":8,"grep":5,"edit":0,"bash":2}' 100 "fungus_garden" 100`
416
+ Run using the Bash tool with description "Recording archaeologist findings...": `bash .aether/aether-utils.sh spawn-complete "{archaeologist_name}" "completed" "Pre-build archaeology scan"`
423
417
 
424
418
  3. **Store and display findings:**
425
419
 
@@ -441,20 +435,10 @@ log a warning and continue to Step 5.
441
435
 
442
436
  **YOU (the Queen) will spawn workers directly. Do NOT delegate to a single Prime Worker.**
443
437
 
444
- **Initialize visual swarm tracking:**
445
- Run using the Bash tool with description "Initializing build display...":
438
+ **Log phase start:**
439
+ Run using the Bash tool with description "Logging phase start...":
446
440
  ```bash
447
- # Generate unique build ID
448
- build_id="build-$(date +%s)"
449
-
450
- # Initialize swarm display for this build
451
- bash .aether/aether-utils.sh swarm-display-init "$build_id"
452
-
453
- # Log phase start
454
441
  bash .aether/aether-utils.sh activity-log "EXECUTING" "Queen" "Phase {id}: {name} - Queen dispatching workers"
455
-
456
- # Display animated header
457
- bash .aether/aether-utils.sh swarm-display-update "Queen" "prime" "excavating" "Phase {id}: {name}" "Colony" '{"read":0,"grep":0,"edit":0,"bash":0}' 10 "fungus_garden" 0
458
442
  ```
459
443
 
460
444
  **Show real-time display header:**
@@ -598,7 +582,7 @@ If `is_integration_phase` is `"true"`:
598
582
 
599
583
  1. **Generate Ambassador name and dispatch:**
600
584
  Run using the Bash tool with description "Naming ambassador...": `bash .aether/aether-utils.sh generate-ant-name "ambassador"` (store as `{ambassador_name}`)
601
- Run using the Bash tool with description "Dispatching ambassador...": `bash .aether/aether-utils.sh spawn-log "Queen" "ambassador" "{ambassador_name}" "External integration design" && bash .aether/aether-utils.sh swarm-display-update "{ambassador_name}" "ambassador" "negotiating" "External integration design" "Queen" '{"read":0,"grep":0,"edit":0,"bash":0}' 0 "fungus_garden" 30`
585
+ Run using the Bash tool with description "Dispatching ambassador...": `bash .aether/aether-utils.sh spawn-log "Queen" "ambassador" "{ambassador_name}" "External integration design"`
602
586
 
603
587
  Display:
604
588
  ```
@@ -676,7 +660,7 @@ If `is_integration_phase` is `"true"`:
676
660
  Extract from response: `integration_plan`, `env_vars_required`, `error_scenarios_covered`, `blockers`
677
661
 
678
662
  Log completion and update swarm display:
679
- Run using the Bash tool with description "Recording ambassador completion...": `bash .aether/aether-utils.sh spawn-complete "{ambassador_name}" "completed" "Integration design complete" && bash .aether/aether-utils.sh swarm-display-update "{ambassador_name}" "ambassador" "completed" "Integration design complete" "Queen" '{"read":5,"grep":3,"edit":0,"bash":2}' 100 "fungus_garden" 100`
663
+ Run using the Bash tool with description "Recording ambassador completion...": `bash .aether/aether-utils.sh spawn-complete "{ambassador_name}" "completed" "Integration design complete"`
680
664
 
681
665
  **Display Ambassador completion line:**
682
666
  ```
@@ -726,7 +710,7 @@ For each Wave 1 task, use Task tool with `subagent_type="aether-builder"`, inclu
726
710
  - If `grave_context` is non-empty, display a visible line before spawning that worker:
727
711
  `⚰️ Graveyard caution for {ant_name}: {file_1} ({level_1}), {file_2} ({level_2})`
728
712
 
729
- **PER WORKER:** Run using the Bash tool with description "Preparing worker {name}...": `bash .aether/aether-utils.sh spawn-log "Queen" "builder" "{ant_name}" "{task_description}" && bash .aether/aether-utils.sh swarm-display-update "{ant_name}" "builder" "excavating" "{task_description}" "Queen" '{"read":0,"grep":0,"edit":0,"bash":0}' 0 "fungus_garden" 10 && bash .aether/aether-utils.sh context-update worker-spawn "{ant_name}" "builder" "{task_description}"`
713
+ **PER WORKER:** Run using the Bash tool with description "Preparing worker {name}...": `bash .aether/aether-utils.sh spawn-log "Queen" "builder" "{ant_name}" "{task_description}" && bash .aether/aether-utils.sh context-update worker-spawn "{ant_name}" "builder" "{task_description}"`
730
714
 
731
715
  **Builder Worker Prompt (CLEAN OUTPUT):**
732
716
  ```
@@ -759,7 +743,6 @@ If integration_plan is provided above, you MUST:
759
743
 
760
744
  **IMPORTANT:** When using the Bash tool for activity calls, always include a description parameter:
761
745
  - activity-log calls → "Logging {action}..."
762
- - swarm-display-update calls → "Updating build display..."
763
746
  - pheromone-read calls → "Checking colony signals..."
764
747
  - spawn-can-spawn calls → "Checking spawn budget..."
765
748
  - generate-ant-name calls → "Naming sub-worker..."
@@ -854,7 +837,7 @@ bash .aether/aether-utils.sh memory-capture \
854
837
  "worker:builder" 2>/dev/null || true
855
838
  ```
856
839
 
857
- **PER WORKER:** Run using the Bash tool with description "Recording {name} completion...": `bash .aether/aether-utils.sh spawn-complete "{ant_name}" "completed" "{summary}" && bash .aether/aether-utils.sh swarm-display-update "{ant_name}" "builder" "completed" "{task_description}" "Queen" '{"read":5,"grep":3,"edit":2,"bash":1}' 100 "fungus_garden" 100 && bash .aether/aether-utils.sh context-update worker-complete "{ant_name}" "completed"`
840
+ **PER WORKER:** Run using the Bash tool with description "Recording {name} completion...": `bash .aether/aether-utils.sh spawn-complete "{ant_name}" "completed" "{summary}" && bash .aether/aether-utils.sh context-update worker-complete "{ant_name}" "completed"`
858
841
 
859
842
  **Check for total wave failure:**
860
843
 
@@ -915,10 +898,7 @@ If at least one worker succeeded, continue normally to the next wave.
915
898
 
916
899
  **Parse each worker's validated JSON output to collect:** status, files_created, files_modified, blockers
917
900
 
918
- **Visual Mode: Render live display (tmux only):**
919
- If `visual_mode` is true AND the build is running inside a tmux session (`$TMUX` environment variable is set), run using the Bash tool with description "Rendering build progress...": `bash .aether/aether-utils.sh swarm-display-text "$build_id"`
920
-
921
- If `$TMUX` is not set, skip this call entirely — do not attempt it. Chat users see the structured completion lines above instead.
901
+ Chat users see the structured completion lines above.
922
902
 
923
903
  ### Step 5.3: Spawn Wave 2+ Workers (Sequential Waves)
924
904
 
@@ -942,7 +922,7 @@ Repeat Step 5.1-5.2 for each subsequent wave, waiting for previous wave to compl
942
922
 
943
923
  Spawn the Watcher using Task tool with `subagent_type="aether-watcher"`, include `description: "👁️ Watcher {Watcher-Name}: Independent verification"` (DO NOT use run_in_background - task blocks until complete):
944
924
 
945
- Run using the Bash tool with description "Dispatching watcher...": `bash .aether/aether-utils.sh spawn-log "Queen" "watcher" "{watcher_name}" "Independent verification" && bash .aether/aether-utils.sh swarm-display-update "{watcher_name}" "watcher" "observing" "Verification in progress" "Queen" '{"read":0,"grep":0,"edit":0,"bash":0}' 0 "nursery" 50`
925
+ Run using the Bash tool with description "Dispatching watcher...": `bash .aether/aether-utils.sh spawn-log "Queen" "watcher" "{watcher_name}" "Independent verification"`
946
926
 
947
927
  **Watcher Worker Prompt (CLEAN OUTPUT):**
948
928
  ```
@@ -958,7 +938,6 @@ Files to verify:
958
938
 
959
939
  **IMPORTANT:** When using the Bash tool for activity calls, always include a description parameter:
960
940
  - activity-log calls → "Logging {action}..."
961
- - swarm-display-update calls → "Updating build display..."
962
941
  - pheromone-read calls → "Checking colony signals..."
963
942
  - spawn-log calls → "Dispatching sub-worker..."
964
943
 
@@ -1003,9 +982,6 @@ For failed verification:
1003
982
 
1004
983
  **Store results for synthesis in Step 5.7**
1005
984
 
1006
- **Update swarm display when Watcher completes:**
1007
- Run using the Bash tool with description "Recording watcher completion...": `bash .aether/aether-utils.sh swarm-display-update "{watcher_name}" "watcher" "completed" "Verification complete" "Queen" '{"read":3,"grep":2,"edit":0,"bash":1}' 100 "nursery" 100`
1008
-
1009
985
  ### Step 5.5.1: Measurer Performance Agent (Conditional)
1010
986
 
1011
987
  **Conditional step — only runs for performance-sensitive phases.**
@@ -1042,7 +1018,7 @@ Run using the Bash tool with description "Recording watcher completion...": `bas
1042
1018
  3. **Generate Measurer name and dispatch:**
1043
1019
 
1044
1020
  Run using the Bash tool with description "Naming measurer...": `bash .aether/aether-utils.sh generate-ant-name "measurer"` (store as `{measurer_name}`)
1045
- Run using the Bash tool with description "Dispatching measurer...": `bash .aether/aether-utils.sh spawn-log "Queen" "measurer" "{measurer_name}" "Performance baseline measurement" && bash .aether/aether-utils.sh swarm-display-update "{measurer_name}" "measurer" "benchmarking" "Performance baseline measurement" "Queen" '{"read":0,"grep":0,"edit":0,"bash":0}' 0 "fungus_garden" 20`
1021
+ Run using the Bash tool with description "Dispatching measurer...": `bash .aether/aether-utils.sh spawn-log "Queen" "measurer" "{measurer_name}" "Performance baseline measurement"`
1046
1022
 
1047
1023
  Display:
1048
1024
  ```
@@ -1118,7 +1094,7 @@ Run using the Bash tool with description "Recording watcher completion...": `bas
1118
1094
  Extract from response: `baselines_established`, `bottlenecks_identified`, `recommendations`, `tool_count`
1119
1095
 
1120
1096
  Log completion and update swarm display:
1121
- Run using the Bash tool with description "Recording measurer completion...": `bash .aether/aether-utils.sh spawn-complete "{measurer_name}" "completed" "Baselines established, bottlenecks identified" && bash .aether/aether-utils.sh swarm-display-update "{measurer_name}" "measurer" "completed" "Performance measurement complete" "Queen" '{"read":5,"grep":3,"edit":0,"bash":0}' 100 "fungus_garden" 100`
1097
+ Run using the Bash tool with description "Recording measurer completion...": `bash .aether/aether-utils.sh spawn-complete "{measurer_name}" "completed" "Baselines established, bottlenecks identified"`
1122
1098
 
1123
1099
  **Display Measurer completion line:**
1124
1100
  ```
@@ -1165,7 +1141,7 @@ Generate a chaos ant name and dispatch:
1165
1141
  Run using the Bash tool with description "Naming chaos ant...": `bash .aether/aether-utils.sh generate-ant-name "chaos"` (store as `{chaos_name}`)
1166
1142
  Run using the Bash tool with description "Loading existing flags...": `bash .aether/aether-utils.sh flag-list --phase {phase_number}`
1167
1143
  Parse the result and extract unresolved flag titles into a list: `{existing_flag_titles}` (comma-separated titles from `.result.flags[].title`). If no flags exist, set `{existing_flag_titles}` to "None".
1168
- Run using the Bash tool with description "Dispatching chaos ant...": `bash .aether/aether-utils.sh spawn-log "Queen" "chaos" "{chaos_name}" "Resilience testing of Phase {id} work" && bash .aether/aether-utils.sh swarm-display-update "{chaos_name}" "chaos" "probing" "Resilience testing" "Queen" '{"read":0,"grep":0,"edit":0,"bash":0}' 0 "refuse_pile" 75`
1144
+ Run using the Bash tool with description "Dispatching chaos ant...": `bash .aether/aether-utils.sh spawn-log "Queen" "chaos" "{chaos_name}" "Resilience testing of Phase {id} work"`
1169
1145
 
1170
1146
  **Announce the resilience testing wave:**
1171
1147
  ```
@@ -1188,7 +1164,6 @@ Skip these known issues: {existing_flag_titles}
1188
1164
 
1189
1165
  **IMPORTANT:** When using the Bash tool for activity calls, always include a description parameter:
1190
1166
  - activity-log calls → "Logging {action}..."
1191
- - swarm-display-update calls → "Updating build display..."
1192
1167
  - pheromone-read calls → "Checking colony signals..."
1193
1168
 
1194
1169
  Use colony-flavored language, 4-8 words, trailing ellipsis.
@@ -1251,7 +1226,7 @@ bash .aether/aether-utils.sh memory-capture \
1251
1226
  ```
1252
1227
 
1253
1228
  Log chaos ant completion and update swarm display:
1254
- Run using the Bash tool with description "Recording chaos completion...": `bash .aether/aether-utils.sh spawn-complete "{chaos_name}" "completed" "{summary}" && bash .aether/aether-utils.sh swarm-display-update "{chaos_name}" "chaos" "completed" "Resilience testing done" "Queen" '{"read":2,"grep":1,"edit":0,"bash":0}' 100 "refuse_pile" 100`
1229
+ Run using the Bash tool with description "Recording chaos completion...": `bash .aether/aether-utils.sh spawn-complete "{chaos_name}" "completed" "{summary}"`
1255
1230
 
1256
1231
  ### Step 5.8: Create Flags for Verification Failures
1257
1232
 
@@ -1543,11 +1518,6 @@ Note: This runs regardless of build success/failure. Failed builds may have reco
1543
1518
 
1544
1519
  **This step runs ONLY after synthesis is complete. All values come from actual worker results.**
1545
1520
 
1546
- **Update swarm display state (always) and render (tmux only):**
1547
- Run using the Bash tool with description "Recording build completion...": `bash .aether/aether-utils.sh swarm-display-update "Queen" "prime" "completed" "Phase {id} complete" "Colony" '{"read":10,"grep":5,"edit":5,"bash":2}' 100 "fungus_garden" 100`
1548
-
1549
- If `$TMUX` is set, also run using the Bash tool with description "Rendering final swarm display...": `bash .aether/aether-utils.sh swarm-display-text "$build_id"`
1550
-
1551
1521
  **Display BUILD SUMMARY (always shown, replaces compact/verbose split):**
1552
1522
 
1553
1523
  Calculate `total_tools` by summing `tool_count` from all worker return JSONs (builders + watcher + chaos).
@@ -74,12 +74,6 @@ Do not touch during build:
74
74
  - Other agents' config files (only modify files assigned to the current build task)
75
75
  </read_only>
76
76
 
77
- ### Step 0: Version Check (Non-blocking)
78
-
79
- Run using the Bash tool with description "Checking colony version...": `bash .aether/aether-utils.sh version-check-cached 2>/dev/null || true`
80
-
81
- If the command succeeds and the JSON result contains a non-empty string, display it as a one-line notice. Proceed regardless of outcome.
82
-
83
77
  ### Step 0.6: Verify LiteLLM Proxy
84
78
 
85
79
  Check that the LiteLLM proxy is running for model routing: