aether-colony 5.3.1 → 5.3.3

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 (165) hide show
  1. package/.aether/aether-utils.sh +181 -5
  2. package/.aether/commands/build.yaml +35 -0
  3. package/.aether/commands/entomb.yaml +1 -1
  4. package/.aether/commands/init.yaml +29 -12
  5. package/.aether/commands/oracle.yaml +70 -0
  6. package/.aether/commands/patrol.yaml +2 -2
  7. package/.aether/commands/run.yaml +3 -3
  8. package/.aether/commands/swarm.yaml +1 -1
  9. package/.aether/docs/command-playbooks/build-complete.md +41 -8
  10. package/.aether/docs/command-playbooks/build-full.md +7 -7
  11. package/.aether/docs/command-playbooks/build-prep.md +1 -1
  12. package/.aether/docs/command-playbooks/continue-advance.md +33 -0
  13. package/.aether/docs/command-playbooks/continue-finalize.md +15 -1
  14. package/.aether/docs/command-playbooks/continue-full.md +15 -1
  15. package/.aether/docs/source-of-truth-map.md +10 -10
  16. package/.aether/docs/structural-learning-stack.md +283 -0
  17. package/.aether/utils/consolidation-seal.sh +196 -0
  18. package/.aether/utils/consolidation.sh +127 -0
  19. package/.aether/utils/curation-ants/archivist.sh +97 -0
  20. package/.aether/utils/curation-ants/critic.sh +214 -0
  21. package/.aether/utils/curation-ants/herald.sh +102 -0
  22. package/.aether/utils/curation-ants/janitor.sh +121 -0
  23. package/.aether/utils/curation-ants/librarian.sh +99 -0
  24. package/.aether/utils/curation-ants/nurse.sh +153 -0
  25. package/.aether/utils/curation-ants/orchestrator.sh +181 -0
  26. package/.aether/utils/curation-ants/scribe.sh +164 -0
  27. package/.aether/utils/curation-ants/sentinel.sh +119 -0
  28. package/.aether/utils/event-bus.sh +301 -0
  29. package/.aether/utils/graph.sh +559 -0
  30. package/.aether/utils/instinct-store.sh +401 -0
  31. package/.aether/utils/learning.sh +79 -7
  32. package/.aether/utils/session.sh +13 -0
  33. package/.aether/utils/state-api.sh +1 -1
  34. package/.aether/utils/trust-scoring.sh +347 -0
  35. package/.aether/utils/worktree.sh +97 -0
  36. package/.claude/commands/ant/entomb.md +1 -1
  37. package/.claude/commands/ant/init.md +29 -12
  38. package/.claude/commands/ant/oracle.md +35 -0
  39. package/.claude/commands/ant/patrol.md +2 -2
  40. package/.claude/commands/ant/run.md +3 -3
  41. package/.claude/commands/ant/swarm.md +1 -1
  42. package/.opencode/commands/ant/build.md +35 -0
  43. package/.opencode/commands/ant/init.md +29 -12
  44. package/.opencode/commands/ant/oracle.md +35 -0
  45. package/.opencode/commands/ant/patrol.md +2 -2
  46. package/.opencode/commands/ant/run.md +3 -3
  47. package/CHANGELOG.md +83 -0
  48. package/README.md +34 -37
  49. package/bin/lib/update-transaction.js +8 -3
  50. package/bin/npx-entry.js +0 -0
  51. package/package.json +1 -1
  52. package/.aether/agents/aether-ambassador.md +0 -140
  53. package/.aether/agents/aether-archaeologist.md +0 -108
  54. package/.aether/agents/aether-architect.md +0 -133
  55. package/.aether/agents/aether-auditor.md +0 -144
  56. package/.aether/agents/aether-builder.md +0 -184
  57. package/.aether/agents/aether-chaos.md +0 -115
  58. package/.aether/agents/aether-chronicler.md +0 -122
  59. package/.aether/agents/aether-gatekeeper.md +0 -116
  60. package/.aether/agents/aether-includer.md +0 -117
  61. package/.aether/agents/aether-keeper.md +0 -177
  62. package/.aether/agents/aether-measurer.md +0 -128
  63. package/.aether/agents/aether-oracle.md +0 -137
  64. package/.aether/agents/aether-probe.md +0 -133
  65. package/.aether/agents/aether-queen.md +0 -286
  66. package/.aether/agents/aether-route-setter.md +0 -130
  67. package/.aether/agents/aether-sage.md +0 -106
  68. package/.aether/agents/aether-scout.md +0 -101
  69. package/.aether/agents/aether-surveyor-disciplines.md +0 -391
  70. package/.aether/agents/aether-surveyor-nest.md +0 -329
  71. package/.aether/agents/aether-surveyor-pathogens.md +0 -264
  72. package/.aether/agents/aether-surveyor-provisions.md +0 -334
  73. package/.aether/agents/aether-tracker.md +0 -137
  74. package/.aether/agents/aether-watcher.md +0 -174
  75. package/.aether/agents/aether-weaver.md +0 -130
  76. package/.aether/commands/claude/archaeology.md +0 -334
  77. package/.aether/commands/claude/build.md +0 -65
  78. package/.aether/commands/claude/chaos.md +0 -336
  79. package/.aether/commands/claude/colonize.md +0 -259
  80. package/.aether/commands/claude/continue.md +0 -60
  81. package/.aether/commands/claude/council.md +0 -507
  82. package/.aether/commands/claude/data-clean.md +0 -81
  83. package/.aether/commands/claude/dream.md +0 -268
  84. package/.aether/commands/claude/entomb.md +0 -498
  85. package/.aether/commands/claude/export-signals.md +0 -57
  86. package/.aether/commands/claude/feedback.md +0 -96
  87. package/.aether/commands/claude/flag.md +0 -151
  88. package/.aether/commands/claude/flags.md +0 -169
  89. package/.aether/commands/claude/focus.md +0 -76
  90. package/.aether/commands/claude/help.md +0 -154
  91. package/.aether/commands/claude/history.md +0 -140
  92. package/.aether/commands/claude/import-signals.md +0 -71
  93. package/.aether/commands/claude/init.md +0 -505
  94. package/.aether/commands/claude/insert-phase.md +0 -105
  95. package/.aether/commands/claude/interpret.md +0 -278
  96. package/.aether/commands/claude/lay-eggs.md +0 -210
  97. package/.aether/commands/claude/maturity.md +0 -113
  98. package/.aether/commands/claude/memory-details.md +0 -77
  99. package/.aether/commands/claude/migrate-state.md +0 -171
  100. package/.aether/commands/claude/oracle.md +0 -642
  101. package/.aether/commands/claude/organize.md +0 -232
  102. package/.aether/commands/claude/patrol.md +0 -620
  103. package/.aether/commands/claude/pause-colony.md +0 -233
  104. package/.aether/commands/claude/phase.md +0 -115
  105. package/.aether/commands/claude/pheromones.md +0 -156
  106. package/.aether/commands/claude/plan.md +0 -693
  107. package/.aether/commands/claude/preferences.md +0 -65
  108. package/.aether/commands/claude/quick.md +0 -100
  109. package/.aether/commands/claude/redirect.md +0 -76
  110. package/.aether/commands/claude/resume-colony.md +0 -197
  111. package/.aether/commands/claude/resume.md +0 -388
  112. package/.aether/commands/claude/run.md +0 -231
  113. package/.aether/commands/claude/seal.md +0 -774
  114. package/.aether/commands/claude/skill-create.md +0 -286
  115. package/.aether/commands/claude/status.md +0 -410
  116. package/.aether/commands/claude/swarm.md +0 -349
  117. package/.aether/commands/claude/tunnels.md +0 -426
  118. package/.aether/commands/claude/update.md +0 -132
  119. package/.aether/commands/claude/verify-castes.md +0 -143
  120. package/.aether/commands/claude/watch.md +0 -239
  121. package/.aether/commands/opencode/archaeology.md +0 -331
  122. package/.aether/commands/opencode/build.md +0 -1168
  123. package/.aether/commands/opencode/chaos.md +0 -329
  124. package/.aether/commands/opencode/colonize.md +0 -195
  125. package/.aether/commands/opencode/continue.md +0 -1436
  126. package/.aether/commands/opencode/council.md +0 -437
  127. package/.aether/commands/opencode/data-clean.md +0 -77
  128. package/.aether/commands/opencode/dream.md +0 -260
  129. package/.aether/commands/opencode/entomb.md +0 -377
  130. package/.aether/commands/opencode/export-signals.md +0 -54
  131. package/.aether/commands/opencode/feedback.md +0 -99
  132. package/.aether/commands/opencode/flag.md +0 -149
  133. package/.aether/commands/opencode/flags.md +0 -167
  134. package/.aether/commands/opencode/focus.md +0 -73
  135. package/.aether/commands/opencode/help.md +0 -157
  136. package/.aether/commands/opencode/history.md +0 -136
  137. package/.aether/commands/opencode/import-signals.md +0 -68
  138. package/.aether/commands/opencode/init.md +0 -518
  139. package/.aether/commands/opencode/insert-phase.md +0 -111
  140. package/.aether/commands/opencode/interpret.md +0 -272
  141. package/.aether/commands/opencode/lay-eggs.md +0 -213
  142. package/.aether/commands/opencode/maturity.md +0 -108
  143. package/.aether/commands/opencode/memory-details.md +0 -83
  144. package/.aether/commands/opencode/migrate-state.md +0 -165
  145. package/.aether/commands/opencode/oracle.md +0 -593
  146. package/.aether/commands/opencode/organize.md +0 -226
  147. package/.aether/commands/opencode/patrol.md +0 -626
  148. package/.aether/commands/opencode/pause-colony.md +0 -203
  149. package/.aether/commands/opencode/phase.md +0 -113
  150. package/.aether/commands/opencode/pheromones.md +0 -162
  151. package/.aether/commands/opencode/plan.md +0 -684
  152. package/.aether/commands/opencode/preferences.md +0 -71
  153. package/.aether/commands/opencode/quick.md +0 -91
  154. package/.aether/commands/opencode/redirect.md +0 -84
  155. package/.aether/commands/opencode/resume-colony.md +0 -190
  156. package/.aether/commands/opencode/resume.md +0 -394
  157. package/.aether/commands/opencode/run.md +0 -237
  158. package/.aether/commands/opencode/seal.md +0 -452
  159. package/.aether/commands/opencode/skill-create.md +0 -63
  160. package/.aether/commands/opencode/status.md +0 -307
  161. package/.aether/commands/opencode/swarm.md +0 -15
  162. package/.aether/commands/opencode/tunnels.md +0 -400
  163. package/.aether/commands/opencode/update.md +0 -127
  164. package/.aether/commands/opencode/verify-castes.md +0 -139
  165. package/.aether/commands/opencode/watch.md +0 -227
@@ -0,0 +1,347 @@
1
+ #!/bin/bash
2
+ # Trust Scoring utility functions — Aether Structural Learning Stack
3
+ # Provides: _trust_calculate, _trust_decay, _trust_tier
4
+ #
5
+ # These functions are sourced by aether-utils.sh at startup.
6
+ # All shared infrastructure (json_ok, json_err, json_warn, atomic_write,
7
+ # DATA_DIR, COLONY_DATA_DIR, SCRIPT_DIR, error constants) is available.
8
+ #
9
+ # This is a pure calculation module — no state is read or written.
10
+ # All functions accept --flag <value> arguments and return JSON via json_ok.
11
+
12
+ # ============================================================================
13
+ # _trust_calculate
14
+ # Calculate a weighted trust score from source, evidence, and activity inputs.
15
+ #
16
+ # Weights: source 40%, evidence 35%, activity 25%
17
+ # Activity uses a 60-day half-life decay from days_since_last_use.
18
+ # Floor: score is never below 0.2.
19
+ #
20
+ # Usage: trust-calculate --source <type> --evidence <type> --days-since <N>
21
+ #
22
+ # Source types and weights:
23
+ # user_feedback 1.0
24
+ # error_resolution 0.9
25
+ # success_pattern 0.8
26
+ # observation 0.6
27
+ # heuristic 0.4
28
+ #
29
+ # Evidence types and weights:
30
+ # test_verified 1.0
31
+ # multi_phase 0.9
32
+ # single_phase 0.7
33
+ # anecdotal 0.4
34
+ #
35
+ # Output: {score, source_score, evidence_score, activity_score, tier}
36
+ # ============================================================================
37
+ _trust_calculate() {
38
+ local source_type=""
39
+ local evidence_type=""
40
+ local days_since=""
41
+
42
+ # Parse --flag value arguments
43
+ while [[ $# -gt 0 ]]; do
44
+ case "$1" in
45
+ --source)
46
+ source_type="${2:-}"
47
+ shift 2
48
+ ;;
49
+ --evidence)
50
+ evidence_type="${2:-}"
51
+ shift 2
52
+ ;;
53
+ --days-since)
54
+ days_since="${2:-}"
55
+ shift 2
56
+ ;;
57
+ *)
58
+ json_err "$E_VALIDATION_FAILED" "Usage: trust-calculate --source <type> --evidence <type> --days-since <N>"
59
+ return
60
+ ;;
61
+ esac
62
+ done
63
+
64
+ [[ -z "$source_type" || -z "$evidence_type" || -z "$days_since" ]] && \
65
+ json_err "$E_VALIDATION_FAILED" "Usage: trust-calculate --source <type> --evidence <type> --days-since <N>"
66
+
67
+ # Map source type to score
68
+ local source_score
69
+ case "$source_type" in
70
+ user_feedback) source_score="1.0" ;;
71
+ error_resolution) source_score="0.9" ;;
72
+ success_pattern) source_score="0.8" ;;
73
+ observation) source_score="0.6" ;;
74
+ heuristic) source_score="0.4" ;;
75
+ *)
76
+ json_err "$E_VALIDATION_FAILED" "Unknown source type: $source_type. Valid: user_feedback, error_resolution, success_pattern, observation, heuristic"
77
+ return
78
+ ;;
79
+ esac
80
+
81
+ # Map evidence type to score
82
+ local evidence_score
83
+ case "$evidence_type" in
84
+ test_verified) evidence_score="1.0" ;;
85
+ multi_phase) evidence_score="0.9" ;;
86
+ single_phase) evidence_score="0.7" ;;
87
+ anecdotal) evidence_score="0.4" ;;
88
+ *)
89
+ json_err "$E_VALIDATION_FAILED" "Unknown evidence type: $evidence_type. Valid: test_verified, multi_phase, single_phase, anecdotal"
90
+ return
91
+ ;;
92
+ esac
93
+
94
+ # Validate days_since is a non-negative integer
95
+ if ! [[ "$days_since" =~ ^[0-9]+$ ]]; then
96
+ json_err "$E_VALIDATION_FAILED" "--days-since must be a non-negative integer, got: $days_since"
97
+ return
98
+ fi
99
+
100
+ # Calculate activity score using 60-day half-life decay
101
+ # activity = 0.5 ^ (days / 60)
102
+ local activity_score
103
+ activity_score=$(_trust_halflife_decay "1.0" "$days_since" "60")
104
+
105
+ # Weighted formula: 0.4 * source + 0.35 * evidence + 0.25 * activity
106
+ local raw_score
107
+ if command -v bc &>/dev/null; then
108
+ raw_score=$(echo "scale=6; 0.4 * $source_score + 0.35 * $evidence_score + 0.25 * $activity_score" | bc)
109
+ else
110
+ raw_score=$(awk "BEGIN{printf \"%.6f\", 0.4 * $source_score + 0.35 * $evidence_score + 0.25 * $activity_score}")
111
+ fi
112
+
113
+ # Apply floor of 0.2
114
+ local score
115
+ score=$(_trust_apply_floor "$raw_score" "0.2")
116
+
117
+ # Derive tier from final score
118
+ local tier
119
+ tier=$(_trust_score_to_tier "$score")
120
+
121
+ json_ok "$(jq -n \
122
+ --argjson score "$score" \
123
+ --argjson source_score "$source_score" \
124
+ --argjson evidence_score "$evidence_score" \
125
+ --argjson activity_score "$activity_score" \
126
+ --arg tier "$tier" \
127
+ '{
128
+ score: $score,
129
+ source_score: $source_score,
130
+ evidence_score: $evidence_score,
131
+ activity_score: $activity_score,
132
+ tier: $tier
133
+ }')"
134
+ }
135
+
136
+ # ============================================================================
137
+ # _trust_decay
138
+ # Apply time-based half-life decay to an existing trust score.
139
+ # The score never drops below the floor of 0.2.
140
+ #
141
+ # Formula: decayed = max(0.2, score * (0.5 ^ (days / 60)))
142
+ #
143
+ # Usage: trust-decay --score <float> --days <N>
144
+ # Output: {original, decayed, days, half_life: 60}
145
+ # ============================================================================
146
+ _trust_decay() {
147
+ local score=""
148
+ local days=""
149
+
150
+ while [[ $# -gt 0 ]]; do
151
+ case "$1" in
152
+ --score)
153
+ score="${2:-}"
154
+ shift 2
155
+ ;;
156
+ --days)
157
+ days="${2:-}"
158
+ shift 2
159
+ ;;
160
+ *)
161
+ json_err "$E_VALIDATION_FAILED" "Usage: trust-decay --score <float> --days <N>"
162
+ return
163
+ ;;
164
+ esac
165
+ done
166
+
167
+ [[ -z "$score" || -z "$days" ]] && \
168
+ json_err "$E_VALIDATION_FAILED" "Usage: trust-decay --score <float> --days <N>"
169
+
170
+ # Validate score is a positive number
171
+ if ! [[ "$score" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
172
+ json_err "$E_VALIDATION_FAILED" "--score must be a non-negative number, got: $score"
173
+ return
174
+ fi
175
+
176
+ # Validate days is a non-negative integer
177
+ if ! [[ "$days" =~ ^[0-9]+$ ]]; then
178
+ json_err "$E_VALIDATION_FAILED" "--days must be a non-negative integer, got: $days"
179
+ return
180
+ fi
181
+
182
+ local decayed
183
+ decayed=$(_trust_halflife_decay "$score" "$days" "60")
184
+ local final
185
+ final=$(_trust_apply_floor "$decayed" "0.2")
186
+
187
+ json_ok "$(jq -n \
188
+ --argjson original "$score" \
189
+ --argjson decayed "$final" \
190
+ --argjson days "$days" \
191
+ --argjson half_life 60 \
192
+ '{
193
+ original: $original,
194
+ decayed: $decayed,
195
+ days: $days,
196
+ half_life: $half_life
197
+ }')"
198
+ }
199
+
200
+ # ============================================================================
201
+ # _trust_tier
202
+ # Map a trust score to a named tier.
203
+ #
204
+ # Tier table:
205
+ # 0.90–1.00 canonical (index 0) — proven across multiple contexts
206
+ # 0.80–0.89 trusted (index 1) — reliable with strong evidence
207
+ # 0.70–0.79 established (index 2) — consistent but limited evidence
208
+ # 0.60–0.69 emerging (index 3) — promising, needs more validation
209
+ # 0.45–0.59 provisional (index 4) — early stage, minimal evidence
210
+ # 0.30–0.44 suspect (index 5) — weak evidence or conflicting signals
211
+ # 0.20–0.29 dormant (index 6) — inactive, near floor
212
+ #
213
+ # Usage: trust-tier --score <float>
214
+ # Output: {score, tier, tier_index}
215
+ # ============================================================================
216
+ _trust_tier() {
217
+ local score=""
218
+
219
+ while [[ $# -gt 0 ]]; do
220
+ case "$1" in
221
+ --score)
222
+ score="${2:-}"
223
+ shift 2
224
+ ;;
225
+ *)
226
+ json_err "$E_VALIDATION_FAILED" "Usage: trust-tier --score <float>"
227
+ return
228
+ ;;
229
+ esac
230
+ done
231
+
232
+ [[ -z "$score" ]] && \
233
+ json_err "$E_VALIDATION_FAILED" "Usage: trust-tier --score <float>"
234
+
235
+ # Validate score is a non-negative number
236
+ if ! [[ "$score" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
237
+ json_err "$E_VALIDATION_FAILED" "--score must be a non-negative number, got: $score"
238
+ return
239
+ fi
240
+
241
+ local tier
242
+ local tier_index
243
+ tier=$(_trust_score_to_tier "$score")
244
+ tier_index=$(_trust_tier_to_index "$tier")
245
+
246
+ json_ok "$(jq -n \
247
+ --argjson score "$score" \
248
+ --arg tier "$tier" \
249
+ --argjson tier_index "$tier_index" \
250
+ '{
251
+ score: $score,
252
+ tier: $tier,
253
+ tier_index: $tier_index
254
+ }')"
255
+ }
256
+
257
+ # ============================================================================
258
+ # Internal helpers — not exposed as subcommands
259
+ # ============================================================================
260
+
261
+ # _trust_halflife_decay: compute score * (0.5 ^ (days / half_life))
262
+ # Usage: _trust_halflife_decay <score> <days> <half_life>
263
+ # Outputs the decayed value as a float string
264
+ _trust_halflife_decay() {
265
+ local score="$1"
266
+ local days="$2"
267
+ local half_life="$3"
268
+
269
+ if command -v bc &>/dev/null; then
270
+ echo "scale=6; $score * e(l(0.5) * ($days / $half_life))" | bc -l
271
+ else
272
+ awk "BEGIN{printf \"%.6f\", $score * (0.5 ^ ($days / $half_life))}"
273
+ fi
274
+ }
275
+
276
+ # _trust_apply_floor: return max(floor, value)
277
+ # Usage: _trust_apply_floor <value> <floor>
278
+ # Outputs the floored value as a float string
279
+ _trust_apply_floor() {
280
+ local value="$1"
281
+ local floor="$2"
282
+
283
+ if command -v bc &>/dev/null; then
284
+ local cmp
285
+ cmp=$(echo "$value < $floor" | bc -l)
286
+ if [[ "$cmp" == "1" ]]; then
287
+ echo "$floor"
288
+ else
289
+ echo "$value"
290
+ fi
291
+ else
292
+ awk "BEGIN{v=$value; f=$floor; printf \"%.6f\", (v < f ? f : v)}"
293
+ fi
294
+ }
295
+
296
+ # _trust_score_to_tier: map a numeric score to a tier name
297
+ # Usage: _trust_score_to_tier <score>
298
+ # Outputs the tier name string
299
+ _trust_score_to_tier() {
300
+ local score="$1"
301
+
302
+ if command -v bc &>/dev/null; then
303
+ if [[ $(echo "$score >= 0.90" | bc -l) == "1" ]]; then
304
+ echo "canonical"
305
+ elif [[ $(echo "$score >= 0.80" | bc -l) == "1" ]]; then
306
+ echo "trusted"
307
+ elif [[ $(echo "$score >= 0.70" | bc -l) == "1" ]]; then
308
+ echo "established"
309
+ elif [[ $(echo "$score >= 0.60" | bc -l) == "1" ]]; then
310
+ echo "emerging"
311
+ elif [[ $(echo "$score >= 0.45" | bc -l) == "1" ]]; then
312
+ echo "provisional"
313
+ elif [[ $(echo "$score >= 0.30" | bc -l) == "1" ]]; then
314
+ echo "suspect"
315
+ else
316
+ echo "dormant"
317
+ fi
318
+ else
319
+ awk "BEGIN{
320
+ s = $score
321
+ if (s >= 0.90) print \"canonical\"
322
+ else if (s >= 0.80) print \"trusted\"
323
+ else if (s >= 0.70) print \"established\"
324
+ else if (s >= 0.60) print \"emerging\"
325
+ else if (s >= 0.45) print \"provisional\"
326
+ else if (s >= 0.30) print \"suspect\"
327
+ else print \"dormant\"
328
+ }"
329
+ fi
330
+ }
331
+
332
+ # _trust_tier_to_index: map tier name to integer index
333
+ # Usage: _trust_tier_to_index <tier_name>
334
+ # Outputs the index as an integer string
335
+ _trust_tier_to_index() {
336
+ local tier="$1"
337
+ case "$tier" in
338
+ canonical) echo "0" ;;
339
+ trusted) echo "1" ;;
340
+ established) echo "2" ;;
341
+ emerging) echo "3" ;;
342
+ provisional) echo "4" ;;
343
+ suspect) echo "5" ;;
344
+ dormant) echo "6" ;;
345
+ *) echo "-1" ;;
346
+ esac
347
+ }
@@ -187,3 +187,100 @@ _worktree_cleanup() {
187
187
 
188
188
  json_ok "$result"
189
189
  }
190
+
191
+ # _worktree_merge
192
+ # Merges a worktree branch back to the target branch with safety checks.
193
+ #
194
+ # Usage: _worktree_merge --branch <branch-name> [--target <target-branch>] [--force]
195
+ # Returns JSON: {ok:true, result:{merged, branch, target, sha, commits_merged}}
196
+ _worktree_merge() {
197
+ local branch=""
198
+ local target=""
199
+ local force=false
200
+
201
+ while [[ $# -gt 0 ]]; do
202
+ case "$1" in
203
+ --branch) branch="${2:-}"; shift 2 ;;
204
+ --target) target="${2:-}"; shift 2 ;;
205
+ --force) force=true; shift ;;
206
+ *) shift ;;
207
+ esac
208
+ done
209
+
210
+ if [[ -z "$branch" ]]; then
211
+ json_err "$E_VALIDATION_FAILED" "Usage: worktree-merge --branch <branch-name> [--target <target-branch>]"
212
+ fi
213
+
214
+ # Sanitize branch name
215
+ if [[ "$branch" == *..* ]] || [[ "$branch" == */* ]] || [[ "$branch" == *\\* ]]; then
216
+ json_err "$E_VALIDATION_FAILED" "Branch name must not contain '..', '/', or backslashes"
217
+ fi
218
+
219
+ local worktree_dir="$WORKTREE_BASE_DIR/$branch"
220
+
221
+ # Default target to current branch
222
+ if [[ -z "$target" ]]; then
223
+ target=$(git -C "$AETHER_ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
224
+ fi
225
+
226
+ # Safety check 1: worktree must exist
227
+ if [[ ! -d "$worktree_dir" ]]; then
228
+ json_err "$E_RESOURCE_NOT_FOUND" "No worktree found for branch '$branch'"
229
+ fi
230
+
231
+ # Safety check 2: worktree must have committed changes (unless --force)
232
+ if [[ "$force" == "false" ]]; then
233
+ local dirty_count
234
+ dirty_count=$(git -C "$worktree_dir" status --porcelain 2>/dev/null \
235
+ | grep -v '\.aether/' \
236
+ | wc -l | tr -d ' ') || dirty_count=0
237
+ if [[ "$dirty_count" -gt 0 ]]; then
238
+ json_err "$E_VALIDATION_FAILED" "Worktree '$branch' has $dirty_count uncommitted changes. Commit or stash before merging."
239
+ fi
240
+ fi
241
+
242
+ # Safety check 3: worktree must have commits ahead of target
243
+ local ahead_count
244
+ ahead_count=$(git -C "$AETHER_ROOT" rev-list --count "${target}..${branch}" 2>/dev/null || echo "0")
245
+ if [[ "$ahead_count" -eq 0 ]]; then
246
+ # Nothing to merge — just clean up
247
+ _worktree_cleanup --branch "$branch" --force
248
+ return $?
249
+ fi
250
+
251
+ # Safety check 4: check for merge conflicts (dry run)
252
+ local conflict_check
253
+ conflict_check=$(git -C "$AETHER_ROOT" merge-tree $(git -C "$AETHER_ROOT" merge-base "$target" "$branch") "$target" "$branch" 2>/dev/null | grep -c "changed in both" || echo "0")
254
+ if [[ "$conflict_check" -gt 0 ]] && [[ "$force" == "false" ]]; then
255
+ json_err "$E_VALIDATION_FAILED" "Merge would produce $conflict_check conflict(s). Resolve manually or use --force."
256
+ fi
257
+
258
+ # Perform the merge
259
+ local merge_sha
260
+ if ! git -C "$AETHER_ROOT" merge "$branch" --no-edit --no-ff -m "merge: worktree branch $branch into $target" >/dev/null 2>&1; then
261
+ # Merge failed — abort
262
+ git -C "$AETHER_ROOT" merge --abort 2>/dev/null || true
263
+ json_err "$E_GIT_ERROR" "Merge of '$branch' into '$target' failed. Aborted."
264
+ fi
265
+
266
+ merge_sha=$(git -C "$AETHER_ROOT" rev-parse HEAD 2>/dev/null || echo "unknown")
267
+
268
+ # Export pheromones from the worktree branch before cleanup
269
+ if [[ -f "$worktree_dir/.aether/data/pheromones.json" ]]; then
270
+ mkdir -p "$AETHER_ROOT/.aether/exchange"
271
+ cp "$worktree_dir/.aether/data/pheromones.json" \
272
+ "$AETHER_ROOT/.aether/exchange/pheromone-branch-export.json" 2>/dev/null || true
273
+ fi
274
+
275
+ # Cleanup the worktree
276
+ _worktree_cleanup --branch "$branch" --force 2>/dev/null || true
277
+
278
+ local result
279
+ result=$(jq -n \
280
+ --arg branch "$branch" \
281
+ --arg target "$target" \
282
+ --arg sha "$merge_sha" \
283
+ --argjson ahead "$ahead_count" \
284
+ '{merged: true, branch: $branch, target: $target, sha: $sha, commits_merged: $ahead}')
285
+ json_ok "$result"
286
+ }
@@ -444,7 +444,7 @@ Write the result to .aether/HANDOFF.md using the Write tool.
444
444
  Display:
445
445
  ```
446
446
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
447
- C O L O N Y E N T O M B E D
447
+ ⚰️ C O L O N Y E N T O M B E D
448
448
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
449
449
 
450
450
  Entombed v{colony_version}
@@ -41,7 +41,6 @@ Do not touch during init:
41
41
  - .aether/dreams/ (user notes)
42
42
  - .aether/chambers/ (archived colonies)
43
43
  - .env* files
44
- - .claude/settings.json
45
44
  - .github/workflows/
46
45
  </read_only>
47
46
 
@@ -156,7 +155,7 @@ Strip `(Colony: ...)` suffixes using sed. If grep finds nothing, variables remai
156
155
  Display a brief header:
157
156
  ```
158
157
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
159
- A E T H E R C O L O N Y I N I T
158
+ 🥚 A E T H E R C O L O N Y I N I T
160
159
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
161
160
  ```
162
161
 
@@ -470,30 +469,48 @@ Display "Import skipped. Starting fresh colony." and proceed to Step 8.
470
469
  **If xml_import_available is false (no chambers, no XML, or no xmllint):**
471
470
 
472
471
  Skip silently -- proceed directly to Step 8 without any mention of import (per D-11).
472
+ ### Step 7.5: Install Clash Detection Hook
473
+
474
+ If `.aether/utils/clash-detect.sh` exists, run:
475
+
476
+ ```bash
477
+ bash .aether/aether-utils.sh clash-setup --install 2>/dev/null || true
478
+ ```
479
+
480
+ This installs the PreToolUse hook that prevents conflicting edits across worktrees.
481
+ Non-blocking — if it fails, init continues normally.
482
+
483
+ Also configure the merge driver for package-lock.json:
484
+
485
+ ```bash
486
+ git config merge.lockfile.driver "bash .aether/utils/merge-driver-lockfile.sh %O %A %B" 2>/dev/null || true
487
+ git config merge.lockfile.name "npm lockfile auto-merge" 2>/dev/null || true
488
+ ```
489
+
473
490
  ### Step 8: Display Result
474
491
 
475
492
  Display the success header and result block:
476
493
 
477
494
  ```
478
495
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
479
- A E T H E R C O L O N Y
496
+ 🥚 A E T H E R C O L O N Y
480
497
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
481
498
 
482
- Queen has set the colony's intention
499
+ 👑 Queen has set the colony's intention
483
500
 
484
501
  "{approved_intent}"
485
502
 
486
- Colony Status: READY
503
+ 🟢 Colony Status: READY
487
504
 
488
- {If re-init: " Mode: Re-init (charter updated, state preserved)"}
489
- {If fresh and seeded_count > 0: " Hive wisdom: {seeded_count} cross-colony pattern(s) seeded into QUEEN.md"}
505
+ {If re-init: " 🔄 Mode: Re-init (charter updated, state preserved)"}
506
+ {If fresh and seeded_count > 0: " 🧠 Hive wisdom: {seeded_count} cross-colony pattern(s) seeded into QUEEN.md"}
490
507
 
491
- State persisted -- safe to /clear, then run /ant:plan
508
+ 💾 State persisted -- safe to /clear, then run /ant:plan
492
509
 
493
510
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
494
- Next Up
511
+ 🐜 Next Up
495
512
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
496
- /ant:plan Generate execution plan
497
- /ant:status Check colony state
498
- /ant:focus Set initial focus
513
+ /ant:plan 📊 Generate execution plan
514
+ /ant:status 📋 Check colony state
515
+ /ant:focus 🎯 Set initial focus
499
516
  ```
@@ -278,6 +278,41 @@ Describe the research topic in detail. The more specific, the better the Oracle'
278
278
 
279
279
  (The user will type their topic via the "Other" free-text option.)
280
280
 
281
+ **Question 1.5: Research Brief — Formulate and Approve**
282
+
283
+ Take the user's raw topic (from `$ARGUMENTS` or Question 1) and reformulate it into a structured research brief. The user may have typed casual natural language — your job is to sharpen it into a clear, well-scoped research prompt that will produce better results.
284
+
285
+ Display the brief for approval:
286
+
287
+ ```
288
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
289
+ 🔮 R E S E A R C H B R I E F
290
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
291
+
292
+ **Topic:** {reformulated topic — clear, specific, actionable}
293
+ **Core Question:** {the single most important question this research should answer}
294
+ **Context:** {what we already know from the codebase or user input}
295
+ **Success Criteria:** {what a good answer looks like — what would make this research useful}
296
+ ```
297
+
298
+ Guidelines for formulation:
299
+ - Turn vague topics into specific ones ("auth stuff" → "Authentication architecture: session-based vs token-based for this Node.js API")
300
+ - Add codebase context if relevant (tech stack, existing patterns)
301
+ - Make the core question answerable — not open-ended philosophy
302
+ - Keep success criteria concrete ("A recommendation with trade-offs" not "understand everything")
303
+
304
+ Then ask the user to approve:
305
+
306
+ ```
307
+ Does this capture what you're looking for? (approve / edit)
308
+ ```
309
+
310
+ - If the user approves: use the reformulated topic as the research topic going forward
311
+ - If the user edits: incorporate their changes, display the updated brief, and ask again
312
+ - Max 2 revision rounds (same as init). After 2, ask for final approval or cancel.
313
+
314
+ The approved **Topic** from the brief becomes the topic used in all subsequent steps (state.json, plan.json, research-plan.md).
315
+
281
316
  **Question 2: Research Template**
282
317
 
283
318
  ```
@@ -79,7 +79,7 @@ Extract from COLONY_STATE.json:
79
79
  Display audit header:
80
80
  ```
81
81
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
82
- C O L O N Y A U D I T
82
+ 🔍 C O L O N Y A U D I T
83
83
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
84
84
 
85
85
  Goal: {goal}
@@ -501,7 +501,7 @@ Display the formatted audit summary:
501
501
 
502
502
  ```
503
503
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
504
- A U D I T R E S U L T S
504
+ 📋 A U D I T R E S U L T S
505
505
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
506
506
 
507
507
  Goal: {goal}
@@ -49,7 +49,7 @@ If `--dry-run`: read COLONY_STATE.json, list remaining incomplete phases
49
49
  (applying `--max-phases` cap), display the plan, then stop without executing.
50
50
 
51
51
  ```
52
- ━━━ A U T O P I L O T P R E V I E W ━━━
52
+ ━━━ 🤖 A U T O P I L O T P R E V I E W ━━━
53
53
  Goal: {goal} | Current: Phase {N} | Remaining: {count} | Max: {max or "all"}
54
54
 
55
55
  Phase {id}: {name} ({task_count} tasks) -> build -> continue -> advance
@@ -187,7 +187,7 @@ If `--continue` flag was passed: skip this check entirely (user dismissed replan
187
187
  If `result.should_replan == true`: **PAUSE** with replan suggestion banner:
188
188
 
189
189
  ```
190
- ━━━ R E P L A N S U G G E S T E D ━━━
190
+ ━━━ 🔄 R E P L A N S U G G E S T E D ━━━
191
191
  Phases auto-completed: {N} | Learnings accumulated: {learnings_since_last}
192
192
 
193
193
  The colony has completed {N} phases since the last plan review.
@@ -205,7 +205,7 @@ If `result.should_replan == false`: proceed normally (no pause).
205
205
  ### Step 6: Final Summary
206
206
 
207
207
  ```
208
- ━━━ A U T O P I L O T C O M P L E T E ━━━
208
+ ━━━ A U T O P I L O T C O M P L E T E ━━━
209
209
  Phases completed: {N} | Elapsed: {Xm Ys} | Now at: Phase {current}
210
210
 
211
211
  {all complete} -> Colony goal achieved! Run /ant:seal
@@ -238,7 +238,7 @@ Cross-compare all findings:
238
238
  Rank fix options:
239
239
  ```
240
240
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
241
- S O L U T I O N R A N K I N G
241
+ 🏆 S O L U T I O N R A N K I N G
242
242
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
243
243
 
244
244
  #1 [0.85 confidence] {best solution}
@@ -879,6 +879,41 @@ bash .aether/aether-utils.sh activity-log "FLAG" "Watcher" "Created blocker: {is
879
879
 
880
880
  This ensures verification failures are persisted as blockers that survive context resets. Chaos Ant findings are flagged in Step 5.7.
881
881
 
882
+ ### Stage Audit Gate (Pre-Synthesis Check)
883
+
884
+ **This gate runs before Step 5.9. All build stages must have completed before synthesizing results.**
885
+
886
+ Verify that each of the following stages has a recorded completion status:
887
+
888
+ | Stage | Steps | Required |
889
+ |-------|-------|----------|
890
+ | Builder waves | Steps 5.1–5.3 | At least 1 worker completed (status "completed") |
891
+ | Watcher | Steps 5.4–5.5 | Watcher returned a result (any status) |
892
+ | Chaos | Steps 5.6–5.7 | Chaos ant returned a result (any status) |
893
+
894
+ Check by reviewing the in-memory worker results accumulated during Steps 5.1–5.7:
895
+ - `builder_results` — results from all builder wave tasks
896
+ - `watcher_result` — result from Step 5.5
897
+ - `chaos_result` — result from Step 5.7
898
+
899
+ **If any stage result is absent (stage did not run or returned no result):**
900
+ - HALT — do not proceed to Step 5.9
901
+ - Display:
902
+ ```
903
+ Stage Audit FAILED — cannot synthesize results.
904
+
905
+ Missing or incomplete stages:
906
+ {list each missing stage: "Builders — no results recorded" / "Watcher — did not complete" / "Chaos — did not complete"}
907
+
908
+ Recovery options:
909
+ 1. Re-run /ant:build to restart this phase
910
+ 2. Run /ant:flags to review blockers
911
+ 3. Run /ant:swarm to auto-repair failed tasks
912
+ ```
913
+ - Return `{"status": "failed", "summary": "Stage audit failed — stages did not complete"}` and stop.
914
+
915
+ **If all stages have results (even if some workers failed):** proceed to Step 5.9.
916
+
882
917
  ### Step 5.9: Synthesize Results
883
918
 
884
919
  **This step runs after all worker tasks have completed (Builders, Watcher, Chaos).**