aether-colony 5.3.2 → 5.4.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 (281) hide show
  1. package/.aether/aether-utils.sh +181 -5
  2. package/.aether/commands/archaeology.yaml +3 -3
  3. package/.aether/commands/build.yaml +80 -45
  4. package/.aether/commands/chaos.yaml +7 -7
  5. package/.aether/commands/colonize.yaml +17 -17
  6. package/.aether/commands/continue.yaml +40 -40
  7. package/.aether/commands/council.yaml +6 -6
  8. package/.aether/commands/data-clean.yaml +3 -3
  9. package/.aether/commands/dream.yaml +2 -2
  10. package/.aether/commands/entomb.yaml +12 -12
  11. package/.aether/commands/export-signals.yaml +2 -2
  12. package/.aether/commands/feedback.yaml +6 -6
  13. package/.aether/commands/flag.yaml +2 -2
  14. package/.aether/commands/flags.yaml +4 -4
  15. package/.aether/commands/focus.yaml +6 -6
  16. package/.aether/commands/help.yaml +1 -1
  17. package/.aether/commands/history.yaml +1 -1
  18. package/.aether/commands/import-signals.yaml +2 -2
  19. package/.aether/commands/init.yaml +44 -27
  20. package/.aether/commands/insert-phase.yaml +1 -1
  21. package/.aether/commands/interpret.yaml +2 -2
  22. package/.aether/commands/lay-eggs.yaml +3 -3
  23. package/.aether/commands/maturity.yaml +2 -2
  24. package/.aether/commands/memory-details.yaml +1 -1
  25. package/.aether/commands/migrate-state.yaml +1 -1
  26. package/.aether/commands/oracle.yaml +147 -82
  27. package/.aether/commands/organize.yaml +5 -5
  28. package/.aether/commands/patrol.yaml +8 -8
  29. package/.aether/commands/pause-colony.yaml +7 -7
  30. package/.aether/commands/phase.yaml +1 -1
  31. package/.aether/commands/pheromones.yaml +1 -1
  32. package/.aether/commands/plan.yaml +14 -14
  33. package/.aether/commands/quick.yaml +4 -4
  34. package/.aether/commands/redirect.yaml +6 -6
  35. package/.aether/commands/resume-colony.yaml +9 -9
  36. package/.aether/commands/resume.yaml +5 -38
  37. package/.aether/commands/run.yaml +10 -10
  38. package/.aether/commands/seal.yaml +33 -33
  39. package/.aether/commands/skill-create.yaml +4 -4
  40. package/.aether/commands/status.yaml +14 -14
  41. package/.aether/commands/swarm.yaml +14 -14
  42. package/.aether/commands/tunnels.yaml +7 -7
  43. package/.aether/commands/update.yaml +1 -1
  44. package/.aether/commands/verify-castes.yaml +3 -3
  45. package/.aether/commands/watch.yaml +15 -15
  46. package/.aether/docs/command-playbooks/build-complete.md +48 -15
  47. package/.aether/docs/command-playbooks/build-context.md +11 -11
  48. package/.aether/docs/command-playbooks/build-full.md +76 -76
  49. package/.aether/docs/command-playbooks/build-prep.md +10 -10
  50. package/.aether/docs/command-playbooks/build-verify.md +27 -27
  51. package/.aether/docs/command-playbooks/build-wave.md +38 -38
  52. package/.aether/docs/command-playbooks/continue-advance.md +60 -27
  53. package/.aether/docs/command-playbooks/continue-finalize.md +25 -11
  54. package/.aether/docs/command-playbooks/continue-full.md +60 -46
  55. package/.aether/docs/command-playbooks/continue-gates.md +18 -18
  56. package/.aether/docs/command-playbooks/continue-verify.md +10 -10
  57. package/.aether/docs/source-of-truth-map.md +10 -10
  58. package/.aether/docs/structural-learning-stack.md +283 -0
  59. package/.aether/templates/colony-state-template.json +1 -0
  60. package/.aether/utils/consolidation-seal.sh +196 -0
  61. package/.aether/utils/consolidation.sh +127 -0
  62. package/.aether/utils/curation-ants/archivist.sh +97 -0
  63. package/.aether/utils/curation-ants/critic.sh +214 -0
  64. package/.aether/utils/curation-ants/herald.sh +102 -0
  65. package/.aether/utils/curation-ants/janitor.sh +121 -0
  66. package/.aether/utils/curation-ants/librarian.sh +99 -0
  67. package/.aether/utils/curation-ants/nurse.sh +153 -0
  68. package/.aether/utils/curation-ants/orchestrator.sh +181 -0
  69. package/.aether/utils/curation-ants/scribe.sh +164 -0
  70. package/.aether/utils/curation-ants/sentinel.sh +119 -0
  71. package/.aether/utils/event-bus.sh +301 -0
  72. package/.aether/utils/graph.sh +559 -0
  73. package/.aether/utils/instinct-store.sh +401 -0
  74. package/.aether/utils/learning.sh +79 -7
  75. package/.aether/utils/oracle/oracle-stop-hook.sh +896 -0
  76. package/.aether/utils/session.sh +13 -0
  77. package/.aether/utils/state-api.sh +1 -1
  78. package/.aether/utils/trust-scoring.sh +347 -0
  79. package/.aether/utils/worktree.sh +97 -0
  80. package/.claude/commands/ant/archaeology.md +2 -2
  81. package/.claude/commands/ant/chaos.md +4 -4
  82. package/.claude/commands/ant/colonize.md +9 -9
  83. package/.claude/commands/ant/council.md +6 -6
  84. package/.claude/commands/ant/data-clean.md +3 -3
  85. package/.claude/commands/ant/dream.md +2 -2
  86. package/.claude/commands/ant/entomb.md +9 -9
  87. package/.claude/commands/ant/export-signals.md +2 -2
  88. package/.claude/commands/ant/feedback.md +4 -4
  89. package/.claude/commands/ant/flag.md +2 -2
  90. package/.claude/commands/ant/flags.md +4 -4
  91. package/.claude/commands/ant/focus.md +4 -4
  92. package/.claude/commands/ant/help.md +1 -1
  93. package/.claude/commands/ant/history.md +1 -1
  94. package/.claude/commands/ant/import-signals.md +2 -2
  95. package/.claude/commands/ant/init.md +44 -27
  96. package/.claude/commands/ant/insert-phase.md +1 -1
  97. package/.claude/commands/ant/interpret.md +2 -2
  98. package/.claude/commands/ant/lay-eggs.md +2 -2
  99. package/.claude/commands/ant/maturity.md +2 -2
  100. package/.claude/commands/ant/memory-details.md +1 -1
  101. package/.claude/commands/ant/migrate-state.md +1 -1
  102. package/.claude/commands/ant/oracle.md +78 -42
  103. package/.claude/commands/ant/organize.md +3 -3
  104. package/.claude/commands/ant/patrol.md +8 -8
  105. package/.claude/commands/ant/pause-colony.md +5 -5
  106. package/.claude/commands/ant/phase.md +1 -1
  107. package/.claude/commands/ant/pheromones.md +1 -1
  108. package/.claude/commands/ant/plan.md +8 -8
  109. package/.claude/commands/ant/quick.md +4 -4
  110. package/.claude/commands/ant/redirect.md +4 -4
  111. package/.claude/commands/ant/resume-colony.md +5 -5
  112. package/.claude/commands/ant/resume.md +17 -29
  113. package/.claude/commands/ant/run.md +10 -10
  114. package/.claude/commands/ant/seal.md +25 -25
  115. package/.claude/commands/ant/skill-create.md +2 -2
  116. package/.claude/commands/ant/status.md +14 -14
  117. package/.claude/commands/ant/swarm.md +14 -14
  118. package/.claude/commands/ant/tunnels.md +4 -4
  119. package/.claude/commands/ant/update.md +1 -1
  120. package/.claude/commands/ant/verify-castes.md +2 -2
  121. package/.claude/commands/ant/watch.md +8 -8
  122. package/.opencode/commands/ant/archaeology.md +1 -1
  123. package/.opencode/commands/ant/build.md +80 -45
  124. package/.opencode/commands/ant/chaos.md +3 -3
  125. package/.opencode/commands/ant/colonize.md +8 -8
  126. package/.opencode/commands/ant/continue.md +40 -40
  127. package/.opencode/commands/ant/council.md +5 -5
  128. package/.opencode/commands/ant/data-clean.md +2 -2
  129. package/.opencode/commands/ant/dream.md +1 -1
  130. package/.opencode/commands/ant/entomb.md +3 -3
  131. package/.opencode/commands/ant/export-signals.md +1 -1
  132. package/.opencode/commands/ant/feedback.md +2 -2
  133. package/.opencode/commands/ant/flag.md +1 -1
  134. package/.opencode/commands/ant/flags.md +3 -3
  135. package/.opencode/commands/ant/focus.md +2 -2
  136. package/.opencode/commands/ant/import-signals.md +1 -1
  137. package/.opencode/commands/ant/init.md +44 -27
  138. package/.opencode/commands/ant/insert-phase.md +1 -1
  139. package/.opencode/commands/ant/interpret.md +1 -1
  140. package/.opencode/commands/ant/lay-eggs.md +2 -2
  141. package/.opencode/commands/ant/maturity.md +1 -1
  142. package/.opencode/commands/ant/memory-details.md +1 -1
  143. package/.opencode/commands/ant/oracle.md +69 -40
  144. package/.opencode/commands/ant/organize.md +2 -2
  145. package/.opencode/commands/ant/patrol.md +8 -8
  146. package/.opencode/commands/ant/pause-colony.md +2 -2
  147. package/.opencode/commands/ant/pheromones.md +1 -1
  148. package/.opencode/commands/ant/plan.md +6 -6
  149. package/.opencode/commands/ant/quick.md +4 -4
  150. package/.opencode/commands/ant/redirect.md +2 -2
  151. package/.opencode/commands/ant/resume-colony.md +4 -4
  152. package/.opencode/commands/ant/resume.md +5 -17
  153. package/.opencode/commands/ant/run.md +10 -10
  154. package/.opencode/commands/ant/seal.md +8 -8
  155. package/.opencode/commands/ant/skill-create.md +2 -2
  156. package/.opencode/commands/ant/status.md +10 -10
  157. package/.opencode/commands/ant/tunnels.md +3 -3
  158. package/.opencode/commands/ant/verify-castes.md +1 -1
  159. package/.opencode/commands/ant/watch.md +7 -7
  160. package/CHANGELOG.md +83 -0
  161. package/README.md +22 -9
  162. package/bin/cli.js +118 -3
  163. package/bin/lib/binary-downloader.js +267 -0
  164. package/bin/lib/update-transaction.js +27 -3
  165. package/bin/lib/version-gate.js +179 -0
  166. package/bin/npx-entry.js +0 -0
  167. package/package.json +1 -1
  168. package/.aether/agents/aether-ambassador.md +0 -140
  169. package/.aether/agents/aether-archaeologist.md +0 -108
  170. package/.aether/agents/aether-architect.md +0 -133
  171. package/.aether/agents/aether-auditor.md +0 -144
  172. package/.aether/agents/aether-builder.md +0 -184
  173. package/.aether/agents/aether-chaos.md +0 -115
  174. package/.aether/agents/aether-chronicler.md +0 -122
  175. package/.aether/agents/aether-gatekeeper.md +0 -116
  176. package/.aether/agents/aether-includer.md +0 -117
  177. package/.aether/agents/aether-keeper.md +0 -177
  178. package/.aether/agents/aether-measurer.md +0 -128
  179. package/.aether/agents/aether-oracle.md +0 -137
  180. package/.aether/agents/aether-probe.md +0 -133
  181. package/.aether/agents/aether-queen.md +0 -286
  182. package/.aether/agents/aether-route-setter.md +0 -130
  183. package/.aether/agents/aether-sage.md +0 -106
  184. package/.aether/agents/aether-scout.md +0 -101
  185. package/.aether/agents/aether-surveyor-disciplines.md +0 -391
  186. package/.aether/agents/aether-surveyor-nest.md +0 -329
  187. package/.aether/agents/aether-surveyor-pathogens.md +0 -264
  188. package/.aether/agents/aether-surveyor-provisions.md +0 -334
  189. package/.aether/agents/aether-tracker.md +0 -137
  190. package/.aether/agents/aether-watcher.md +0 -174
  191. package/.aether/agents/aether-weaver.md +0 -130
  192. package/.aether/commands/claude/archaeology.md +0 -334
  193. package/.aether/commands/claude/build.md +0 -65
  194. package/.aether/commands/claude/chaos.md +0 -336
  195. package/.aether/commands/claude/colonize.md +0 -259
  196. package/.aether/commands/claude/continue.md +0 -60
  197. package/.aether/commands/claude/council.md +0 -507
  198. package/.aether/commands/claude/data-clean.md +0 -81
  199. package/.aether/commands/claude/dream.md +0 -268
  200. package/.aether/commands/claude/entomb.md +0 -498
  201. package/.aether/commands/claude/export-signals.md +0 -57
  202. package/.aether/commands/claude/feedback.md +0 -96
  203. package/.aether/commands/claude/flag.md +0 -151
  204. package/.aether/commands/claude/flags.md +0 -169
  205. package/.aether/commands/claude/focus.md +0 -76
  206. package/.aether/commands/claude/help.md +0 -154
  207. package/.aether/commands/claude/history.md +0 -140
  208. package/.aether/commands/claude/import-signals.md +0 -71
  209. package/.aether/commands/claude/init.md +0 -505
  210. package/.aether/commands/claude/insert-phase.md +0 -105
  211. package/.aether/commands/claude/interpret.md +0 -278
  212. package/.aether/commands/claude/lay-eggs.md +0 -210
  213. package/.aether/commands/claude/maturity.md +0 -113
  214. package/.aether/commands/claude/memory-details.md +0 -77
  215. package/.aether/commands/claude/migrate-state.md +0 -171
  216. package/.aether/commands/claude/oracle.md +0 -642
  217. package/.aether/commands/claude/organize.md +0 -232
  218. package/.aether/commands/claude/patrol.md +0 -620
  219. package/.aether/commands/claude/pause-colony.md +0 -233
  220. package/.aether/commands/claude/phase.md +0 -115
  221. package/.aether/commands/claude/pheromones.md +0 -156
  222. package/.aether/commands/claude/plan.md +0 -693
  223. package/.aether/commands/claude/preferences.md +0 -65
  224. package/.aether/commands/claude/quick.md +0 -100
  225. package/.aether/commands/claude/redirect.md +0 -76
  226. package/.aether/commands/claude/resume-colony.md +0 -197
  227. package/.aether/commands/claude/resume.md +0 -388
  228. package/.aether/commands/claude/run.md +0 -231
  229. package/.aether/commands/claude/seal.md +0 -774
  230. package/.aether/commands/claude/skill-create.md +0 -286
  231. package/.aether/commands/claude/status.md +0 -410
  232. package/.aether/commands/claude/swarm.md +0 -349
  233. package/.aether/commands/claude/tunnels.md +0 -426
  234. package/.aether/commands/claude/update.md +0 -132
  235. package/.aether/commands/claude/verify-castes.md +0 -143
  236. package/.aether/commands/claude/watch.md +0 -239
  237. package/.aether/commands/opencode/archaeology.md +0 -331
  238. package/.aether/commands/opencode/build.md +0 -1168
  239. package/.aether/commands/opencode/chaos.md +0 -329
  240. package/.aether/commands/opencode/colonize.md +0 -195
  241. package/.aether/commands/opencode/continue.md +0 -1436
  242. package/.aether/commands/opencode/council.md +0 -437
  243. package/.aether/commands/opencode/data-clean.md +0 -77
  244. package/.aether/commands/opencode/dream.md +0 -260
  245. package/.aether/commands/opencode/entomb.md +0 -377
  246. package/.aether/commands/opencode/export-signals.md +0 -54
  247. package/.aether/commands/opencode/feedback.md +0 -99
  248. package/.aether/commands/opencode/flag.md +0 -149
  249. package/.aether/commands/opencode/flags.md +0 -167
  250. package/.aether/commands/opencode/focus.md +0 -73
  251. package/.aether/commands/opencode/help.md +0 -157
  252. package/.aether/commands/opencode/history.md +0 -136
  253. package/.aether/commands/opencode/import-signals.md +0 -68
  254. package/.aether/commands/opencode/init.md +0 -518
  255. package/.aether/commands/opencode/insert-phase.md +0 -111
  256. package/.aether/commands/opencode/interpret.md +0 -272
  257. package/.aether/commands/opencode/lay-eggs.md +0 -213
  258. package/.aether/commands/opencode/maturity.md +0 -108
  259. package/.aether/commands/opencode/memory-details.md +0 -83
  260. package/.aether/commands/opencode/migrate-state.md +0 -165
  261. package/.aether/commands/opencode/oracle.md +0 -593
  262. package/.aether/commands/opencode/organize.md +0 -226
  263. package/.aether/commands/opencode/patrol.md +0 -626
  264. package/.aether/commands/opencode/pause-colony.md +0 -203
  265. package/.aether/commands/opencode/phase.md +0 -113
  266. package/.aether/commands/opencode/pheromones.md +0 -162
  267. package/.aether/commands/opencode/plan.md +0 -684
  268. package/.aether/commands/opencode/preferences.md +0 -71
  269. package/.aether/commands/opencode/quick.md +0 -91
  270. package/.aether/commands/opencode/redirect.md +0 -84
  271. package/.aether/commands/opencode/resume-colony.md +0 -190
  272. package/.aether/commands/opencode/resume.md +0 -394
  273. package/.aether/commands/opencode/run.md +0 -237
  274. package/.aether/commands/opencode/seal.md +0 -452
  275. package/.aether/commands/opencode/skill-create.md +0 -63
  276. package/.aether/commands/opencode/status.md +0 -307
  277. package/.aether/commands/opencode/swarm.md +0 -15
  278. package/.aether/commands/opencode/tunnels.md +0 -400
  279. package/.aether/commands/opencode/update.md +0 -127
  280. package/.aether/commands/opencode/verify-castes.md +0 -139
  281. package/.aether/commands/opencode/watch.md +0 -227
@@ -36,10 +36,10 @@ Define which files are authoritative for system behavior, which files are derive
36
36
  |---|---|---|
37
37
  | Core deterministic operations | `.aether/aether-utils.sh` | Dispatcher that loads domain modules on demand (~5,200 lines) |
38
38
  | Slash command orchestration | `.claude/commands/ant/*.md` | Includes build/continue orchestrators |
39
- | Worker behavior specs | `.claude/agents/ant/*.md` | 22 Claude agent definitions (Builder, Watcher, etc.) |
39
+ | Worker behavior specs | `.claude/agents/ant/*.md` | 24 Claude agent definitions (Builder, Watcher, etc.) |
40
40
  | Packaged Claude agent mirror | `.aether/agents-claude/*.md` | Distribution mirror; must stay byte-identical with `.claude/agents/ant/*.md` |
41
- | OpenCode command surface | `.opencode/commands/ant/*.md` | 44 OpenCode command files; structure parity with Claude commands |
42
- | OpenCode worker behavior specs | `.opencode/agents/*.md` | 22 OpenCode agent definitions |
41
+ | OpenCode command surface | `.opencode/commands/ant/*.md` | 45 OpenCode command files; structure parity with Claude commands |
42
+ | OpenCode worker behavior specs | `.opencode/agents/*.md` | 24 OpenCode agent definitions |
43
43
  | Domain modules | `.aether/utils/{flag,spawn,session,suggest,queen,swarm,learning,pheromone,state-api}.sh` | Extracted from aether-utils.sh in Phase 13; sourced on demand |
44
44
  | Build/continue split stages | `.aether/docs/command-playbooks/*.md` | Loaded by orchestrators; executable instruction docs |
45
45
  | Output templates | `.aether/templates/*` | Templates for generated state/handoff/wisdom/session artifacts |
@@ -66,8 +66,8 @@ Define which files are authoritative for system behavior, which files are derive
66
66
  - `build.md` and `continue.md` are now orchestrators that load split playbooks under `.aether/docs/command-playbooks/`.
67
67
  - Orchestrators run playbooks as staged instruction sets (Read-tool execution model), not as bash subcommand wrappers.
68
68
  - Cross-platform surfaces are present:
69
- - 44 Claude commands and 44 OpenCode commands
70
- - 22 Claude agents and 22 OpenCode agents
69
+ - 45 Claude commands and 45 OpenCode commands
70
+ - 24 Claude agents and 24 OpenCode agents
71
71
  - Autopilot subcommands (`autopilot-init`, `autopilot-update`, `autopilot-status`, `autopilot-stop`, `autopilot-check-replan`) manage autonomous build/continue cycles via `/ant:run`.
72
72
  - `registry-list` lists all registered repos with metadata including domain tags.
73
73
  - `.aether/agents-claude/*.md` mirrors `.claude/agents/ant/*.md` for packaging/distribution.
@@ -84,11 +84,11 @@ Define which files are authoritative for system behavior, which files are derive
84
84
  | Core utility entrypoint | `.aether/aether-utils.sh` | 1 | Active |
85
85
  | Sourced shell utilities | `.aether/utils/*.sh` | ~29 | Active (9 domain modules + infrastructure + XML) |
86
86
  | XML utility scripts | `.aether/utils/xml-*.sh` | 5 | Active (see drift note) |
87
- | Slash commands (Claude) | `.claude/commands/ant/*.md` | 44 | Active |
88
- | Slash commands (OpenCode) | `.opencode/commands/ant/*.md` | 44 | Active (content differs from Claude variants) |
89
- | Agent definitions (Claude) | `.claude/agents/ant/*.md` | 22 | Active |
90
- | Agent mirror (packaging) | `.aether/agents-claude/*.md` | 22 | Active mirror (must match Claude agent files exactly) |
91
- | Agent definitions (OpenCode) | `.opencode/agents/*.md` | 22 | Active (content differs from Claude variants) |
87
+ | Slash commands (Claude) | `.claude/commands/ant/*.md` | 45 | Active |
88
+ | Slash commands (OpenCode) | `.opencode/commands/ant/*.md` | 45 | Active (content differs from Claude variants) |
89
+ | Agent definitions (Claude) | `.claude/agents/ant/*.md` | 24 | Active |
90
+ | Agent mirror (packaging) | `.aether/agents-claude/*.md` | 24 | Active mirror (must match Claude agent files exactly) |
91
+ | Agent definitions (OpenCode) | `.opencode/agents/*.md` | 24 | Active (content differs from Claude variants) |
92
92
  | Command playbooks | `.aether/docs/command-playbooks/*.md` | 9 | Active (5 build + 4 continue; excludes full/README) |
93
93
  | Templates (all types) | `.aether/templates/*` | 12 | Active |
94
94
  | Disciplines | `.aether/docs/disciplines/*.md` | 7 | Active |
@@ -0,0 +1,283 @@
1
+ # Structural Learning Stack
2
+
3
+ > Memory consolidation pipeline: from raw observations to trusted wisdom.
4
+
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ The Structural Learning Stack is how Aether converts raw, repeated observations into
10
+ colony wisdom that workers can act on. Each stage adds structure: trust scores quantify
11
+ reliability, the graph records relationships between instincts, curation ants clean and
12
+ promote, and the event bus connects everything loosely.
13
+
14
+ The stack runs automatically at phase-end and seal — workers never call it directly.
15
+
16
+ ---
17
+
18
+ ## Architecture Diagram
19
+
20
+ ```
21
+ learning-observe
22
+
23
+ [learning-observations.json]
24
+
25
+ trust-calculate
26
+
27
+
28
+ [instinct-store] ──────────► [instinct-graph.json]
29
+ │ (graph-link edges)
30
+
31
+ ┌──────────▼──────────┐
32
+ │ Curation Ants │
33
+ │ (phase-end / seal) │
34
+ └──────────┬──────────┘
35
+
36
+ ┌───────────────┼───────────────┐
37
+ ▼ ▼ ▼
38
+ [QUEEN.md] [event-bus.jsonl] [archived]
39
+ (via herald) (consolidation (low-trust
40
+ events) instincts)
41
+ ```
42
+
43
+ ---
44
+
45
+ ## Pipeline Stages
46
+
47
+ ### 1. Observation (learning.sh — `_learning_observe`)
48
+
49
+ Records an observation of a learning pattern into `.aether/data/learning-observations.json`.
50
+
51
+ - **Deduplication:** A SHA-256 hash of the content is used as the key. If an identical observation already exists, `observation_count` is incremented and `last_seen` is updated rather than creating a duplicate entry.
52
+ - **Trust score on write:** For new observations, `trust-calculate` is called immediately using the provided `source_type` and `evidence_type` (defaults: `observation` / `anecdotal`). The computed score is stored as `trust_score`.
53
+ - **Backup rotation:** A 3-file rotating backup (`*.bak.1`, `*.bak.2`, `*.bak.3`) is maintained on every write. On read, if the file is corrupt, the most recent valid backup is restored automatically.
54
+ - **Valid wisdom types:** `philosophy`, `pattern`, `redirect`, `stack`, `decree`, `failure`
55
+
56
+ Observation schema fields: `content_hash`, `content`, `wisdom_type`, `observation_count`, `first_seen`, `last_seen`, `colonies`, `trust_score`, `source_type`, `evidence_type`, `compression_level`.
57
+
58
+ ---
59
+
60
+ ### 2. Trust Scoring Engine (trust-scoring.sh)
61
+
62
+ A pure calculation module. No state is read or written. All functions accept `--flag value` arguments and return JSON.
63
+
64
+ **Weighted formula:**
65
+ ```
66
+ score = 0.40 × source_score + 0.35 × evidence_score + 0.25 × activity_score
67
+ ```
68
+
69
+ **Source types (40% weight):**
70
+
71
+ | Type | Score |
72
+ |------|-------|
73
+ | user_feedback | 1.0 |
74
+ | error_resolution | 0.9 |
75
+ | success_pattern | 0.8 |
76
+ | observation | 0.6 |
77
+ | heuristic | 0.4 |
78
+
79
+ **Evidence types (35% weight):**
80
+
81
+ | Type | Score |
82
+ |------|-------|
83
+ | test_verified | 1.0 |
84
+ | multi_phase | 0.9 |
85
+ | single_phase | 0.7 |
86
+ | anecdotal | 0.4 |
87
+
88
+ **Activity score (25% weight):** `0.5 ^ (days_since_last_use / 60)` — a 60-day half-life decay from the last observed use.
89
+
90
+ **Floor:** Score is never below `0.2`.
91
+
92
+ **Trust tiers:**
93
+
94
+ | Score range | Tier | Index |
95
+ |-------------|------|-------|
96
+ | 0.90 – 1.00 | canonical | 0 |
97
+ | 0.80 – 0.89 | trusted | 1 |
98
+ | 0.70 – 0.79 | established | 2 |
99
+ | 0.60 – 0.69 | emerging | 3 |
100
+ | 0.45 – 0.59 | provisional | 4 |
101
+ | 0.30 – 0.44 | suspect | 5 |
102
+ | 0.20 – 0.29 | dormant | 6 |
103
+
104
+ ---
105
+
106
+ ### 3. Event Bus (event-bus.sh)
107
+
108
+ A JSONL append-log at `.aether/data/event-bus.jsonl`. Each line is one JSON event object.
109
+
110
+ **Event fields:** `id`, `topic`, `payload`, `source`, `timestamp`, `ttl_days`, `expires_at`
111
+
112
+ - **Pub/sub pattern:** Publish to a topic with `event-publish`; subscribe by topic pattern with `event-subscribe`. Patterns support exact match or prefix wildcard (e.g., `"consolidation.*"`).
113
+ - **TTL:** Default 30 days per event. Events with `expires_at` in the past are excluded from subscriptions and removed by cleanup.
114
+ - **Concurrency:** File locking via `acquire_lock`/`release_lock` on every append and cleanup rewrite.
115
+ - **Replay:** `event-replay` returns events for a topic from a given ISO-8601 timestamp, sorted chronologically.
116
+ - **Cleanup:** `event-cleanup` atomically rewrites the JSONL file, keeping only non-expired events. Supports `--dry-run`.
117
+
118
+ ---
119
+
120
+ ### 4. Instinct Storage (instinct-store.sh)
121
+
122
+ Persistent trust-scored instincts at `.aether/data/instincts.json` (schema version 1.0).
123
+
124
+ **Instinct schema:**
125
+ ```json
126
+ {
127
+ "id": "inst_<timestamp>_<hex>",
128
+ "trigger": "...",
129
+ "action": "...",
130
+ "domain": "...",
131
+ "trust_score": 0.75,
132
+ "trust_tier": "established",
133
+ "confidence": 0.8,
134
+ "provenance": {
135
+ "source": "...",
136
+ "source_type": "observation",
137
+ "evidence": "...",
138
+ "created_at": "<ISO8601>",
139
+ "last_applied": null,
140
+ "application_count": 0
141
+ },
142
+ "application_history": [],
143
+ "related_instincts": [],
144
+ "archived": false
145
+ }
146
+ ```
147
+
148
+ - **Deduplication:** First 50 characters of `trigger` are matched against existing active entries. On match, confidence is boosted to `max(existing, new)` and the trust score is recomputed.
149
+ - **50-instinct cap:** When active count exceeds 50 after insert, the entry with the lowest `trust_score` is soft-deleted (`archived: true`).
150
+ - **Decay:** `instinct-decay-all` applies the same 60-day half-life decay to all active entries. Entries whose decayed score falls below `0.25` are automatically archived.
151
+ - **Read:** `instinct-read-trusted` returns active entries filtered by `min-score` (default 0.5), optionally by domain, sorted by `trust_score` descending.
152
+
153
+ ---
154
+
155
+ ### 5. Graph Layer (graph.sh)
156
+
157
+ Tracks directed relationships between instincts at `.aether/data/instinct-graph.json`.
158
+
159
+ **Edge schema:** `edge_id`, `source`, `target`, `relationship`, `weight`, `created_at`
160
+
161
+ **Relationship types:** `reinforces`, `contradicts`, `extends`, `supersedes`, `related`
162
+
163
+ **Operations:**
164
+
165
+ | Function | Description |
166
+ |----------|-------------|
167
+ | `graph-link` | Create or update a directed edge. Duplicate `source+target+relationship` updates the weight. Default weight: 0.5. |
168
+ | `graph-neighbors` | 1-hop lookup. Direction: `out`, `in`, or `both`. Optional relationship filter. |
169
+ | `graph-reach` | BFS traversal up to N hops (max 3). Returns `{id, hop, path}` for each reachable node. Optional `--min-weight` filter. Early exit when no new nodes are found. |
170
+ | `graph-cluster` | Finds clusters of strongly connected instincts using greedy union-find over qualifying edges. Defaults: `min-edges=2`, `min-weight=0.3`. Returns `{nodes, edge_count, avg_weight}` per cluster. |
171
+
172
+ ---
173
+
174
+ ### 6. Curation Ants
175
+
176
+ Eight specialized ants that maintain memory quality. The orchestrator (`curation-run`) runs all eight in sequence. Sentinel can abort the run early if critical corruption is detected.
177
+
178
+ **Execution order:**
179
+
180
+ ```
181
+ sentinel → nurse → critic → herald → janitor → archivist → librarian → scribe
182
+ ```
183
+
184
+ **Ant responsibilities:**
185
+
186
+ | Ant | Responsibility |
187
+ |-----|---------------|
188
+ | sentinel | Health check on all memory stores. Aborts subsequent steps if critical corruption is found. |
189
+ | nurse | Recalculates trust scores for observations and instincts using current elapsed days. |
190
+ | critic | Detects contradictions between instincts (overlapping triggers with conflicting actions). |
191
+ | herald | Promotes high-trust instincts to QUEEN.md Patterns/Philosophies section. |
192
+ | janitor | Removes expired events from the event bus; prunes old archived instincts. |
193
+ | archivist | Archives active instincts whose trust score has fallen below a configurable threshold (default: 0.3 at seal). |
194
+ | librarian | Collects inventory statistics across all memory stores. |
195
+ | scribe | Generates a markdown consolidation report. |
196
+
197
+ All steps are non-blocking — a failure in one step is logged and execution continues.
198
+
199
+ ---
200
+
201
+ ### 7. Consolidation Pipeline
202
+
203
+ Two consolidation modes, each calling into the curation ants.
204
+
205
+ **Phase-end (lightweight) — `consolidation-phase-end`:**
206
+
207
+ Runs at the end of every phase (`/ant:continue`). Executes three ants only: `nurse → herald → janitor`. Publishes a `consolidation.phase_end` event on the event bus. All three steps are non-blocking.
208
+
209
+ **Seal (full) — `consolidation-seal`:**
210
+
211
+ Runs once during `/ant:seal`. Executes five steps:
212
+
213
+ 1. `curation-run` — full 8-ant orchestration
214
+ 2. `instinct-decay-all` — final trust decay pass across all active instincts
215
+ 3. `curation-archivist --threshold 0.3` — archive borderline instincts
216
+ 4. `event-publish` — publish `consolidation.seal` event
217
+ 5. `curation-scribe` — generate final consolidation report
218
+
219
+ All steps are non-blocking. The seal report path is returned in the output.
220
+
221
+ ---
222
+
223
+ ## Integration Points
224
+
225
+ | Trigger | Stack call | Effect |
226
+ |---------|-----------|--------|
227
+ | `/ant:continue` | `consolidation-phase-end` | nurse + herald + janitor; phase_end event |
228
+ | `/ant:seal` | `consolidation-seal` | full 8-ant curation + decay + archive + seal event + report |
229
+ | `/ant:build` (pattern capture) | `learning-observe` | Records observation with trust score |
230
+ | `colony-prime` | `instinct-read-trusted` | Injects trusted instincts into worker prompts |
231
+
232
+ ---
233
+
234
+ ## Subcommand Reference
235
+
236
+ | Subcommand | Module | Usage |
237
+ |-----------|--------|-------|
238
+ | `trust-calculate` | trust-scoring.sh | `--source <type> --evidence <type> --days-since <N>` |
239
+ | `trust-decay` | trust-scoring.sh | `--score <float> --days <N>` |
240
+ | `trust-tier` | trust-scoring.sh | `--score <float>` |
241
+ | `event-publish` | event-bus.sh | `--topic <topic> --payload <json> [--source <src>] [--ttl <days>]` |
242
+ | `event-subscribe` | event-bus.sh | `--topic <pattern> [--since <ISO>] [--limit <N>]` |
243
+ | `event-cleanup` | event-bus.sh | `[--dry-run]` |
244
+ | `event-replay` | event-bus.sh | `--topic <topic> --since <ISO> [--limit <N>]` |
245
+ | `instinct-store` | instinct-store.sh | `--trigger <t> --action <a> --domain <d> --confidence <f> --source <s> --evidence <e> [--source-type <type>]` |
246
+ | `instinct-read-trusted` | instinct-store.sh | `[--min-score <f>] [--domain <d>] [--limit <N>]` |
247
+ | `instinct-decay-all` | instinct-store.sh | `[--days <N>] [--dry-run]` |
248
+ | `instinct-archive` | instinct-store.sh | `--id <id>` |
249
+ | `graph-link` | graph.sh | `--source <id> --target <id> --relationship <type> [--weight <float>]` |
250
+ | `graph-neighbors` | graph.sh | `--id <id> [--direction out\|in\|both] [--relationship <type>]` |
251
+ | `graph-reach` | graph.sh | `--id <id> --hops <N> [--min-weight <float>]` |
252
+ | `graph-cluster` | graph.sh | `[--min-edges <N>] [--min-weight <float>]` |
253
+ | `curation-sentinel` | curation-ants/sentinel.sh | `[--dry-run]` |
254
+ | `curation-nurse` | curation-ants/nurse.sh | `[--dry-run]` |
255
+ | `curation-critic` | curation-ants/critic.sh | `[--dry-run]` |
256
+ | `curation-herald` | curation-ants/herald.sh | `[--dry-run]` |
257
+ | `curation-janitor` | curation-ants/janitor.sh | `[--dry-run]` |
258
+ | `curation-archivist` | curation-ants/archivist.sh | `[--threshold <f>] [--dry-run]` |
259
+ | `curation-librarian` | curation-ants/librarian.sh | `[--dry-run]` |
260
+ | `curation-scribe` | curation-ants/scribe.sh | `[--dry-run]` |
261
+ | `curation-run` | curation-ants/orchestrator.sh | `[--dry-run] [--verbose]` |
262
+ | `consolidation-phase-end` | consolidation.sh | `[--dry-run]` |
263
+ | `consolidation-seal` | consolidation-seal.sh | `[--dry-run]` |
264
+
265
+ ---
266
+
267
+ ## Test Coverage
268
+
269
+ | Test file | What it covers |
270
+ |-----------|---------------|
271
+ | `tests/bash/test-trust-scoring.sh` | `trust-calculate`, `trust-decay`, `trust-tier`; formula weights, floor, tiers |
272
+ | `tests/bash/test-event-bus.sh` | `event-publish`, `event-subscribe`, `event-cleanup`, `event-replay`; TTL, locking, wildcard patterns |
273
+ | `tests/bash/test-instinct-store.sh` | `instinct-store`, `instinct-read-trusted`, `instinct-decay-all`, `instinct-archive`; 50-cap, dedup, decay archival |
274
+ | `tests/bash/test-instinct-apply.sh` | Instinct application and provenance tracking |
275
+ | `tests/bash/test-graph.sh` | `graph-link`, `graph-neighbors`, `graph-reach`, `graph-cluster`; BFS traversal, cluster detection |
276
+ | `tests/bash/test-curation-core.sh` | Core curation ant behavior (sentinel, nurse, critic) |
277
+ | `tests/bash/test-curation-ops.sh` | Operational curation ants (herald, janitor, archivist, librarian, scribe) |
278
+ | `tests/bash/test-curation-orchestrator.sh` | `curation-run` full sequence, sentinel abort path |
279
+ | `tests/bash/test-consolidation.sh` | `consolidation-phase-end`; phase-end step sequence, event publishing |
280
+ | `tests/bash/test-consolidation-seal.sh` | `consolidation-seal`; full seal sequence, dry-run mode |
281
+ | `tests/bash/test-learning-module.sh` | `learning-observe`; trust score on write, deduplication, observation_count increment |
282
+ | `tests/bash/test-learning-recovery.sh` | Backup rotation and corrupt-file recovery logic |
283
+ | `tests/bash/test-oracle-trust.sh` | Trust scoring integration with oracle/research paths |
@@ -0,0 +1,196 @@
1
+ #!/bin/bash
2
+ # Consolidation Seal — Full seal-ceremony consolidation
3
+ # Provides: _consolidation_seal
4
+ #
5
+ # Runs once during /ant:seal. Orchestrates curation-run, instinct-decay-all,
6
+ # curation-archivist, event publish, and curation-scribe in sequence.
7
+ # Each step is non-blocking: failures are logged but do not stop the seal.
8
+ #
9
+ # These functions are sourced by aether-utils.sh at startup.
10
+ # All shared infrastructure (json_ok, json_err, COLONY_DATA_DIR, DATA_DIR,
11
+ # error constants) is available when sourced.
12
+
13
+ # ============================================================================
14
+ # _consolidation_seal
15
+ # Full consolidation for the seal ceremony.
16
+ #
17
+ # Usage: consolidation-seal [--dry-run]
18
+ #
19
+ # Steps:
20
+ # 1. curation-run — full 8-ant orchestration
21
+ # 2. instinct-decay-all — final trust decay pass
22
+ # 3. curation-archivist — archive borderline instincts (threshold 0.3)
23
+ # 4. event-publish — publish consolidation.seal event
24
+ # 5. curation-scribe — generate final report
25
+ #
26
+ # Output: json_ok with {type, steps, event_published, dry_run}
27
+ # ============================================================================
28
+ _consolidation_seal() {
29
+ local dry_run="false"
30
+
31
+ while [[ $# -gt 0 ]]; do
32
+ case "$1" in
33
+ --dry-run) dry_run="true"; shift ;;
34
+ *) shift ;;
35
+ esac
36
+ done
37
+
38
+ local steps_json="[]"
39
+ local event_published="false"
40
+
41
+ # _cs_step <name> <subcommand> [extra_args...]
42
+ # Runs the subcommand non-blocking (failures logged, not fatal).
43
+ # Appends a step entry to steps_json.
44
+ _cs_step() {
45
+ local step_name="$1"
46
+ shift
47
+ local subcmd="$1"
48
+ shift
49
+ # Remaining positional args are passed to the subcommand
50
+
51
+ local step_result step_status step_summary step_report_path="null"
52
+
53
+ # Build argument array respecting dry_run
54
+ local -a args=("$subcmd")
55
+ if [[ "$dry_run" == "true" ]]; then
56
+ args+=("--dry-run")
57
+ fi
58
+ # Append any extra args
59
+ while [[ $# -gt 0 ]]; do
60
+ args+=("$1")
61
+ shift
62
+ done
63
+
64
+ step_result=$(bash "$0" "${args[@]}" 2>/dev/null) || true
65
+
66
+ if echo "$step_result" | jq -e '.ok == true' >/dev/null 2>&1; then
67
+ step_status="ok"
68
+ step_summary=$(echo "$step_result" | jq -r '
69
+ .result |
70
+ if type == "object" then
71
+ [ to_entries[] | "\(.key) \(.value)" ] | join(", ")
72
+ else
73
+ tostring
74
+ end
75
+ ' 2>/dev/null | head -c 120 || echo "ok")
76
+ [[ -z "$step_summary" ]] && step_summary="ok"
77
+
78
+ # Extract report_path if present (scribe step)
79
+ step_report_path=$(echo "$step_result" | jq -r '.result.report_path // "null"' 2>/dev/null || echo "null")
80
+ else
81
+ step_status="failed"
82
+ local err_msg
83
+ err_msg=$(echo "$step_result" | jq -r '.error // "unknown error"' 2>/dev/null || echo "unknown error")
84
+ step_summary="$err_msg"
85
+ fi
86
+
87
+ steps_json=$(echo "$steps_json" | jq \
88
+ --arg name "$step_name" \
89
+ --arg status "$step_status" \
90
+ --arg summary "$step_summary" \
91
+ --arg rp "$step_report_path" \
92
+ '. += [{
93
+ "name": $name,
94
+ "status": $status,
95
+ "summary": $summary,
96
+ "report_path": (if $rp == "null" then null else $rp end)
97
+ }]')
98
+ }
99
+
100
+ # ── Step 1: Full 8-ant curation run ────────────────────────────────────────
101
+ _cs_step "curation-run" "curation-run"
102
+
103
+ # ── Step 2: Final trust decay pass ─────────────────────────────────────────
104
+ _cs_step "instinct-decay-all" "instinct-decay-all"
105
+
106
+ # ── Step 3: Archive borderline instincts (threshold 0.3) ───────────────────
107
+ # Note: --dry-run is injected by _cs_step; but archivist also takes --threshold
108
+ # We cannot let _cs_step inject --dry-run before --threshold so we handle manually
109
+ local arch_result arch_status arch_summary
110
+ local -a arch_args=("curation-archivist" "--threshold" "0.3")
111
+ if [[ "$dry_run" == "true" ]]; then
112
+ arch_args+=("--dry-run")
113
+ fi
114
+ arch_result=$(bash "$0" "${arch_args[@]}" 2>/dev/null) || true
115
+ if echo "$arch_result" | jq -e '.ok == true' >/dev/null 2>&1; then
116
+ arch_status="ok"
117
+ arch_summary=$(echo "$arch_result" | jq -r '
118
+ .result |
119
+ if type == "object" then
120
+ [ to_entries[] | "\(.key) \(.value)" ] | join(", ")
121
+ else tostring end
122
+ ' 2>/dev/null | head -c 120 || echo "ok")
123
+ [[ -z "$arch_summary" ]] && arch_summary="ok"
124
+ else
125
+ arch_status="failed"
126
+ arch_summary=$(echo "$arch_result" | jq -r '.error // "unknown error"' 2>/dev/null || echo "unknown error")
127
+ fi
128
+ steps_json=$(echo "$steps_json" | jq \
129
+ --arg status "$arch_status" \
130
+ --arg summary "$arch_summary" \
131
+ '. += [{"name":"archivist","status":$status,"summary":$summary,"report_path":null}]')
132
+
133
+ # ── Step 4: Publish consolidation.seal event ───────────────────────────────
134
+ if [[ "$dry_run" != "true" ]]; then
135
+ local payload
136
+ payload=$(jq -nc \
137
+ --arg ts "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
138
+ --argjson steps "$steps_json" \
139
+ '{"timestamp":$ts,"steps":$steps}')
140
+ local ep_result
141
+ ep_result=$(bash "$0" event-publish \
142
+ --topic "consolidation.seal" \
143
+ --payload "$payload" \
144
+ --source "consolidation-seal" 2>/dev/null) || true
145
+ if echo "$ep_result" | jq -e '.ok == true' >/dev/null 2>&1; then
146
+ event_published="true"
147
+ fi
148
+ else
149
+ # In dry-run mode, report event as published (no side effects)
150
+ event_published="true"
151
+ fi
152
+
153
+ # ── Step 5: Generate final scribe report ───────────────────────────────────
154
+ local scribe_result scribe_status scribe_summary scribe_report_path="null"
155
+ local -a scribe_args=("curation-scribe")
156
+ if [[ "$dry_run" == "true" ]]; then
157
+ scribe_args+=("--dry-run")
158
+ fi
159
+ scribe_result=$(bash "$0" "${scribe_args[@]}" 2>/dev/null) || true
160
+ if echo "$scribe_result" | jq -e '.ok == true' >/dev/null 2>&1; then
161
+ scribe_status="ok"
162
+ scribe_summary=$(echo "$scribe_result" | jq -r '
163
+ .result |
164
+ if type == "object" then
165
+ [ to_entries[] | "\(.key) \(.value)" ] | join(", ")
166
+ else tostring end
167
+ ' 2>/dev/null | head -c 120 || echo "ok")
168
+ [[ -z "$scribe_summary" ]] && scribe_summary="ok"
169
+ scribe_report_path=$(echo "$scribe_result" | jq -r '.result.report_path // "null"' 2>/dev/null || echo "null")
170
+ else
171
+ scribe_status="failed"
172
+ scribe_summary=$(echo "$scribe_result" | jq -r '.error // "unknown error"' 2>/dev/null || echo "unknown error")
173
+ fi
174
+ steps_json=$(echo "$steps_json" | jq \
175
+ --arg status "$scribe_status" \
176
+ --arg summary "$scribe_summary" \
177
+ --arg rp "$scribe_report_path" \
178
+ '. += [{
179
+ "name": "scribe",
180
+ "status": $status,
181
+ "summary": $summary,
182
+ "report_path": (if $rp == "null" then null else $rp end)
183
+ }]')
184
+
185
+ # ── Output ─────────────────────────────────────────────────────────────────
186
+ json_ok "$(jq -n \
187
+ --argjson steps "$steps_json" \
188
+ --argjson event_published "$([ "$event_published" == "true" ] && echo true || echo false)" \
189
+ --argjson dry "$([ "$dry_run" == "true" ] && echo true || echo false)" \
190
+ '{
191
+ "type": "seal",
192
+ "steps": $steps,
193
+ "event_published": $event_published,
194
+ "dry_run": $dry
195
+ }')"
196
+ }
@@ -0,0 +1,127 @@
1
+ #!/bin/bash
2
+ # Consolidation utility — lightweight end-of-phase consolidation
3
+ # Provides: _consolidation_phase_end
4
+ #
5
+ # These functions are sourced by aether-utils.sh at startup.
6
+ # All shared infrastructure (json_ok, json_err, atomic_write,
7
+ # COLONY_DATA_DIR, SCRIPT_DIR, error constants) is available.
8
+ #
9
+ # Subcommand: consolidation-phase-end [--dry-run]
10
+ # Runs nurse + herald + janitor curation ants in sequence,
11
+ # then publishes a consolidation.phase_end event to the event bus.
12
+ # Each step is non-blocking: failures are logged and execution continues.
13
+
14
+ # ============================================================================
15
+ # _consolidation_phase_end
16
+ # Run lightweight end-of-phase consolidation.
17
+ #
18
+ # Usage: consolidation-phase-end [--dry-run]
19
+ #
20
+ # Output: json_ok with:
21
+ # {type, steps:[{name, status, summary}], event_published, dry_run}
22
+ # ============================================================================
23
+ _consolidation_phase_end() {
24
+ local dry_run="false"
25
+
26
+ while [[ $# -gt 0 ]]; do
27
+ case "$1" in
28
+ --dry-run) dry_run="true"; shift ;;
29
+ *) shift ;;
30
+ esac
31
+ done
32
+
33
+ local dry_run_flag=""
34
+ [[ "$dry_run" == "true" ]] && dry_run_flag="--dry-run"
35
+
36
+ local steps_json="[]"
37
+
38
+ # ── Step 1: curation-nurse (trust recalculation) ──────────────────────────
39
+ local nurse_status="ok"
40
+ local nurse_summary=""
41
+ local nurse_result
42
+ # shellcheck disable=SC2086
43
+ nurse_result=$(bash "$0" curation-nurse $dry_run_flag 2>/dev/null) || nurse_status="failed"
44
+
45
+ if [[ "$nurse_status" == "ok" ]]; then
46
+ nurse_summary=$(echo "$nurse_result" | jq -r \
47
+ '"observations_updated=\(.result.observations_updated // 0) instincts_updated=\(.result.instincts_updated // 0)"' \
48
+ 2>/dev/null || echo "completed")
49
+ else
50
+ nurse_summary="nurse step failed; continuing"
51
+ fi
52
+
53
+ steps_json=$(echo "$steps_json" | jq -c \
54
+ --arg name "nurse" \
55
+ --arg status "$nurse_status" \
56
+ --arg summary "$nurse_summary" \
57
+ '. + [{name:$name,status:$status,summary:$summary}]')
58
+
59
+ # ── Step 2: curation-herald (promote high-trust to QUEEN.md) ─────────────
60
+ local herald_status="ok"
61
+ local herald_summary=""
62
+ local herald_result
63
+ # shellcheck disable=SC2086
64
+ herald_result=$(bash "$0" curation-herald $dry_run_flag 2>/dev/null) || herald_status="failed"
65
+
66
+ if [[ "$herald_status" == "ok" ]]; then
67
+ herald_summary=$(echo "$herald_result" | jq -r \
68
+ '"eligible=\(.result.eligible // 0) promoted=\(.result.promoted // 0)"' \
69
+ 2>/dev/null || echo "completed")
70
+ else
71
+ herald_summary="herald step failed; continuing"
72
+ fi
73
+
74
+ steps_json=$(echo "$steps_json" | jq -c \
75
+ --arg name "herald" \
76
+ --arg status "$herald_status" \
77
+ --arg summary "$herald_summary" \
78
+ '. + [{name:$name,status:$status,summary:$summary}]')
79
+
80
+ # ── Step 3: curation-janitor (clean expired) ─────────────────────────────
81
+ local janitor_status="ok"
82
+ local janitor_summary=""
83
+ local janitor_result
84
+ # shellcheck disable=SC2086
85
+ janitor_result=$(bash "$0" curation-janitor $dry_run_flag 2>/dev/null) || janitor_status="failed"
86
+
87
+ if [[ "$janitor_status" == "ok" ]]; then
88
+ janitor_summary=$(echo "$janitor_result" | jq -r \
89
+ '"events_removed=\(.result.events_removed // 0) instincts_pruned=\(.result.instincts_pruned // 0)"' \
90
+ 2>/dev/null || echo "completed")
91
+ else
92
+ janitor_summary="janitor step failed; continuing"
93
+ fi
94
+
95
+ steps_json=$(echo "$steps_json" | jq -c \
96
+ --arg name "janitor" \
97
+ --arg status "$janitor_status" \
98
+ --arg summary "$janitor_summary" \
99
+ '. + [{name:$name,status:$status,summary:$summary}]')
100
+
101
+ # ── Step 4: publish event to event bus ───────────────────────────────────
102
+ local event_published="false"
103
+
104
+ local current_phase
105
+ current_phase=$(jq -r '.current_phase // 0' "$COLONY_DATA_DIR/COLONY_STATE.json" 2>/dev/null || echo "0")
106
+
107
+ local payload
108
+ payload=$(jq -nc \
109
+ --argjson phase "$current_phase" \
110
+ --argjson dry_run "$dry_run" \
111
+ --argjson steps "$steps_json" \
112
+ '{phase:$phase,dry_run:$dry_run,steps:$steps}')
113
+
114
+ if bash "$0" event-publish \
115
+ --topic "consolidation.phase_end" \
116
+ --payload "$payload" \
117
+ --source "consolidation" \
118
+ > /dev/null 2>&1; then
119
+ event_published="true"
120
+ fi
121
+
122
+ json_ok "$(jq -nc \
123
+ --argjson steps "$steps_json" \
124
+ --argjson event_published "$event_published" \
125
+ --argjson dry_run "$dry_run" \
126
+ '{type:"phase_end",steps:$steps,event_published:$event_published,dry_run:$dry_run}')"
127
+ }