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
@@ -0,0 +1,97 @@
1
+ #!/bin/bash
2
+ # Curation Archivist — Low-Trust Instinct Archival
3
+ # Archives instincts that have decayed below a trust threshold.
4
+ #
5
+ # Functions:
6
+ # _curation_archivist
7
+ #
8
+ # These functions are sourced by aether-utils.sh at startup.
9
+ # All shared infrastructure (json_ok, json_err, atomic_write, COLONY_DATA_DIR,
10
+ # DATA_DIR, error constants) is available when sourced.
11
+
12
+ # ============================================================================
13
+ # _curation_archivist
14
+ # Archive active instincts with trust_score below threshold.
15
+ # Usage: curation-archivist [--threshold <float>] [--dry-run]
16
+ #
17
+ # Default threshold: 0.25
18
+ # Output: json_ok with {archived:N, below_threshold:N, dry_run:bool}
19
+ # ============================================================================
20
+ _curation_archivist() {
21
+ local ca_threshold="0.25"
22
+ local ca_dry_run="false"
23
+
24
+ while [[ $# -gt 0 ]]; do
25
+ case "$1" in
26
+ --threshold)
27
+ ca_threshold="${2:-0.25}"
28
+ shift 2
29
+ ;;
30
+ --dry-run)
31
+ ca_dry_run="true"
32
+ shift
33
+ ;;
34
+ *)
35
+ shift
36
+ ;;
37
+ esac
38
+ done
39
+
40
+ local ca_data_dir="${COLONY_DATA_DIR:-${DATA_DIR:-}}"
41
+ if [[ -z "$ca_data_dir" ]]; then
42
+ json_err "$E_VALIDATION_FAILED" "curation-archivist: COLONY_DATA_DIR is not set"
43
+ fi
44
+
45
+ local ca_instincts_file="$ca_data_dir/instincts.json"
46
+
47
+ # No instincts file — nothing to archive
48
+ if [[ ! -f "$ca_instincts_file" ]]; then
49
+ json_ok "$(jq -nc \
50
+ --argjson archived 0 \
51
+ --argjson below_threshold 0 \
52
+ --argjson dry_run "$ca_dry_run" \
53
+ '{archived:$archived, below_threshold:$below_threshold, dry_run:$dry_run}')"
54
+ return 0
55
+ fi
56
+
57
+ if ! jq empty "$ca_instincts_file" 2>/dev/null; then
58
+ json_err "$E_JSON_INVALID" "curation-archivist: instincts.json is not valid JSON"
59
+ fi
60
+
61
+ # Count active instincts below threshold
62
+ local ca_below_threshold
63
+ ca_below_threshold=$(jq --argjson thresh "$ca_threshold" \
64
+ '[.instincts[] | select(.archived != true and (.trust_score // .confidence // 0) < $thresh)] | length' \
65
+ "$ca_instincts_file" 2>/dev/null || echo 0)
66
+
67
+ local ca_archived=0
68
+
69
+ if [[ "$ca_dry_run" == "false" && "$ca_below_threshold" -gt 0 ]]; then
70
+ local ca_ts
71
+ ca_ts=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
72
+
73
+ local ca_updated
74
+ ca_updated=$(jq \
75
+ --argjson thresh "$ca_threshold" \
76
+ --arg ts "$ca_ts" \
77
+ '.instincts |= [.[] | if (.archived != true and (.trust_score // .confidence // 0) < $thresh)
78
+ then . + {archived: true, updated_at: $ts}
79
+ else .
80
+ end]' \
81
+ "$ca_instincts_file" 2>/dev/null)
82
+
83
+ if [[ -n "$ca_updated" ]]; then
84
+ atomic_write "$ca_instincts_file" "$ca_updated" 2>/dev/null \
85
+ || json_err "$E_UNKNOWN" "curation-archivist: failed to write instincts.json"
86
+ ca_archived="$ca_below_threshold"
87
+ fi
88
+ elif [[ "$ca_dry_run" == "true" ]]; then
89
+ ca_archived="$ca_below_threshold"
90
+ fi
91
+
92
+ json_ok "$(jq -nc \
93
+ --argjson archived "$ca_archived" \
94
+ --argjson below_threshold "$ca_below_threshold" \
95
+ --argjson dry_run "$ca_dry_run" \
96
+ '{archived:$archived, below_threshold:$below_threshold, dry_run:$dry_run}')"
97
+ }
@@ -0,0 +1,214 @@
1
+ #!/bin/bash
2
+ # Critic curation ant — contradiction detection between instincts
3
+ # Provides: _curation_critic
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, error constants) is available.
8
+ #
9
+ # Subcommand: curation-critic [--auto-resolve]
10
+ # Finds contradicting instincts using text heuristics and graph edges.
11
+
12
+ # ============================================================================
13
+ # _curation_critic_opposing_words
14
+ # Internal helper: check if two action strings oppose each other.
15
+ # Detects "always"/"never" and "do"/"don't" opposites in the same domain.
16
+ # Outputs "true" if opposing, "false" otherwise.
17
+ # ============================================================================
18
+ _curation_critic_opposing_words() {
19
+ local action_a="$1"
20
+ local action_b="$2"
21
+
22
+ local low_a low_b
23
+ low_a=$(echo "$action_a" | tr '[:upper:]' '[:lower:]')
24
+ low_b=$(echo "$action_b" | tr '[:upper:]' '[:lower:]')
25
+
26
+ # "always" in one and "never" in the other
27
+ if [[ "$low_a" == *"always"* && "$low_b" == *"never"* ]]; then
28
+ echo "true"; return
29
+ fi
30
+ if [[ "$low_a" == *"never"* && "$low_b" == *"always"* ]]; then
31
+ echo "true"; return
32
+ fi
33
+
34
+ # "don't" or "do not" in one and plain action (no negation) in the other
35
+ if [[ "$low_a" == *"don't"* || "$low_a" == *"do not"* ]]; then
36
+ # Strip negation from a: "don't add X" -> "add X" — check overlap with b
37
+ local stripped_a
38
+ stripped_a=$(echo "$low_a" | sed "s/don't //g; s/do not //g")
39
+ if [[ "$low_b" == *"$stripped_a"* || "$stripped_a" == *"$low_b"* ]]; then
40
+ # Only flag if they share substantial content (>= 4 chars of overlap)
41
+ local overlap_len=${#stripped_a}
42
+ [[ "$overlap_len" -ge 4 ]] && echo "true" && return
43
+ fi
44
+ fi
45
+ if [[ "$low_b" == *"don't"* || "$low_b" == *"do not"* ]]; then
46
+ local stripped_b
47
+ stripped_b=$(echo "$low_b" | sed "s/don't //g; s/do not //g")
48
+ if [[ "$low_a" == *"$stripped_b"* || "$stripped_b" == *"$low_a"* ]]; then
49
+ local overlap_len=${#stripped_b}
50
+ [[ "$overlap_len" -ge 4 ]] && echo "true" && return
51
+ fi
52
+ fi
53
+
54
+ echo "false"
55
+ }
56
+
57
+ # ============================================================================
58
+ # _curation_critic
59
+ # Find contradicting instincts and optionally auto-resolve them.
60
+ #
61
+ # Usage: curation-critic [--auto-resolve]
62
+ #
63
+ # Contradiction criteria:
64
+ # - Same domain
65
+ # - Opposing triggers (same trigger text) with opposing action keywords
66
+ # - OR existing "contradicts" edge in the graph
67
+ #
68
+ # Auto-resolve: archive the lower-trust instinct, create "contradicts" graph edge.
69
+ #
70
+ # Output: {contradictions: [{instinct_a, instinct_b, reason, resolved}], count: N}
71
+ # ============================================================================
72
+ _curation_critic() {
73
+ local auto_resolve="false"
74
+
75
+ while [[ $# -gt 0 ]]; do
76
+ case "$1" in
77
+ --auto-resolve) auto_resolve="true"; shift ;;
78
+ *) shift ;;
79
+ esac
80
+ done
81
+
82
+ local inst_file="$COLONY_DATA_DIR/instincts.json"
83
+
84
+ if [[ ! -f "$inst_file" ]]; then
85
+ json_ok '{"contradictions":[],"count":0}'
86
+ return
87
+ fi
88
+
89
+ # Load all active instincts into a bash-friendly form
90
+ local active_instincts
91
+ active_instincts=$(jq -c '[.instincts[] | select(.archived == false)]' "$inst_file" 2>/dev/null || echo "[]")
92
+
93
+ local total_active
94
+ total_active=$(echo "$active_instincts" | jq 'length')
95
+
96
+ local contradictions_json="[]"
97
+ local resolved_ids=()
98
+
99
+ if [[ "$total_active" -ge 2 ]]; then
100
+ # Compare all pairs using indexed access
101
+ local i=0
102
+ while [[ $i -lt $((total_active - 1)) ]]; do
103
+ local inst_a
104
+ inst_a=$(echo "$active_instincts" | jq -c ".[$i]")
105
+ local id_a domain_a trigger_a action_a score_a
106
+ id_a=$(echo "$inst_a" | jq -r '.id')
107
+ domain_a=$(echo "$inst_a" | jq -r '.domain // ""')
108
+ trigger_a=$(echo "$inst_a" | jq -r '.trigger // ""')
109
+ action_a=$(echo "$inst_a" | jq -r '.action // ""')
110
+ score_a=$(echo "$inst_a" | jq -r '.trust_score // 0')
111
+
112
+ local j=$((i + 1))
113
+ while [[ $j -lt $total_active ]]; do
114
+ local inst_b
115
+ inst_b=$(echo "$active_instincts" | jq -c ".[$j]")
116
+ local id_b domain_b trigger_b action_b score_b
117
+ id_b=$(echo "$inst_b" | jq -r '.id')
118
+ domain_b=$(echo "$inst_b" | jq -r '.domain // ""')
119
+ trigger_b=$(echo "$inst_b" | jq -r '.trigger // ""')
120
+ action_b=$(echo "$inst_b" | jq -r '.action // ""')
121
+ score_b=$(echo "$inst_b" | jq -r '.trust_score // 0')
122
+
123
+ local contradiction_reason=""
124
+
125
+ # Heuristic 1: Same domain + similar trigger + opposing actions
126
+ if [[ -n "$domain_a" && "$domain_a" == "$domain_b" ]]; then
127
+ # Check if triggers are similar (first 40 chars match or substantial overlap)
128
+ local trig_prefix_a trig_prefix_b
129
+ trig_prefix_a=$(echo "$trigger_a" | cut -c1-40 | tr '[:upper:]' '[:lower:]')
130
+ trig_prefix_b=$(echo "$trigger_b" | cut -c1-40 | tr '[:upper:]' '[:lower:]')
131
+
132
+ if [[ "$trig_prefix_a" == "$trig_prefix_b" && -n "$trig_prefix_a" ]]; then
133
+ local opposing
134
+ opposing=$(_curation_critic_opposing_words "$action_a" "$action_b")
135
+ if [[ "$opposing" == "true" ]]; then
136
+ contradiction_reason="same domain and trigger with opposing actions"
137
+ fi
138
+ fi
139
+ fi
140
+
141
+ # Heuristic 2: Check existing "contradicts" graph edge
142
+ if [[ -z "$contradiction_reason" ]]; then
143
+ local graph_file="$COLONY_DATA_DIR/instinct-graph.json"
144
+ if [[ -f "$graph_file" ]]; then
145
+ local has_edge
146
+ has_edge=$(jq -r \
147
+ --arg a "$id_a" --arg b "$id_b" \
148
+ '[.edges[] | select(
149
+ .relationship == "contradicts" and (
150
+ (.source == $a and .target == $b) or
151
+ (.source == $b and .target == $a)
152
+ )
153
+ )] | length' "$graph_file" 2>/dev/null || echo 0)
154
+ if [[ "$has_edge" -gt 0 ]]; then
155
+ contradiction_reason="existing contradicts graph edge"
156
+ fi
157
+ fi
158
+ fi
159
+
160
+ if [[ -n "$contradiction_reason" ]]; then
161
+ local resolved="false"
162
+
163
+ if [[ "$auto_resolve" == "true" ]]; then
164
+ # Archive the lower-trust instinct
165
+ local lower_id higher_id
166
+ local cmp
167
+ cmp=$(awk "BEGIN{print ($score_a >= $score_b)}" 2>/dev/null || echo "1")
168
+ if [[ "$cmp" == "1" ]]; then
169
+ lower_id="$id_b"
170
+ higher_id="$id_a"
171
+ else
172
+ lower_id="$id_a"
173
+ higher_id="$id_b"
174
+ fi
175
+
176
+ # Only archive if not already scheduled (avoid double-archive)
177
+ local already_resolving="false"
178
+ for rid in "${resolved_ids[@]:-}"; do
179
+ [[ "$rid" == "$lower_id" ]] && already_resolving="true" && break
180
+ done
181
+
182
+ if [[ "$already_resolving" != "true" ]]; then
183
+ _instinct_archive --id "$lower_id" >/dev/null 2>&1 || true
184
+ resolved_ids+=("$lower_id")
185
+ resolved="true"
186
+
187
+ # Create "contradicts" graph edge (best effort)
188
+ _graph_link --source "$higher_id" --target "$lower_id" \
189
+ --relationship contradicts >/dev/null 2>&1 || true
190
+ fi
191
+ fi
192
+
193
+ contradictions_json=$(echo "$contradictions_json" | jq \
194
+ --arg a "$id_a" \
195
+ --arg b "$id_b" \
196
+ --arg reason "$contradiction_reason" \
197
+ --argjson resolved "$([ "$resolved" == "true" ] && echo true || echo false)" \
198
+ '. += [{instinct_a: $a, instinct_b: $b, reason: $reason, resolved: $resolved}]')
199
+ fi
200
+
201
+ j=$((j + 1))
202
+ done
203
+ i=$((i + 1))
204
+ done
205
+ fi
206
+
207
+ local count
208
+ count=$(echo "$contradictions_json" | jq 'length')
209
+
210
+ json_ok "$(jq -n \
211
+ --argjson contradictions "$contradictions_json" \
212
+ --argjson count "$count" \
213
+ '{contradictions: $contradictions, count: $count}')"
214
+ }
@@ -0,0 +1,102 @@
1
+ #!/bin/bash
2
+ # Herald curation ant — QUEEN.md promotion of high-trust instincts
3
+ # Provides: _curation_herald
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, AETHER_ROOT, SCRIPT_DIR, error constants) is available.
8
+ #
9
+ # Subcommand: curation-herald [--min-trust <float>] [--dry-run]
10
+ # Promotes instincts with trust_score >= min-trust to QUEEN.md wisdom.
11
+
12
+ # ============================================================================
13
+ # _curation_herald
14
+ # Promote high-trust instincts to QUEEN.md.
15
+ #
16
+ # Usage: curation-herald [--min-trust <float>] [--dry-run]
17
+ # Default min-trust: 0.75
18
+ #
19
+ # Output: {eligible: N, promoted: N, already_in_queen: N, dry_run: bool}
20
+ # ============================================================================
21
+ _curation_herald() {
22
+ local min_trust="0.75"
23
+ local dry_run="false"
24
+
25
+ while [[ $# -gt 0 ]]; do
26
+ case "$1" in
27
+ --min-trust) min_trust="${2:-0.75}"; shift 2 ;;
28
+ --dry-run) dry_run="true"; shift ;;
29
+ *) shift ;;
30
+ esac
31
+ done
32
+
33
+ local inst_file="$COLONY_DATA_DIR/instincts.json"
34
+
35
+ if [[ ! -f "$inst_file" ]]; then
36
+ json_ok "$(jq -n --argjson dry "$([ "$dry_run" == "true" ] && echo true || echo false)" \
37
+ '{eligible: 0, promoted: 0, already_in_queen: 0, dry_run: $dry}')"
38
+ return
39
+ fi
40
+
41
+ # Collect eligible instincts: active, trust_score >= min_trust
42
+ local eligible_instincts
43
+ eligible_instincts=$(jq -c \
44
+ --argjson min "$min_trust" \
45
+ '[.instincts[] | select(.archived == false and .trust_score >= $min)]' \
46
+ "$inst_file" 2>/dev/null || echo "[]")
47
+
48
+ local eligible_count
49
+ eligible_count=$(echo "$eligible_instincts" | jq 'length')
50
+
51
+ local promoted=0
52
+ local already_in_queen=0
53
+
54
+ if [[ "$eligible_count" -gt 0 && "$dry_run" != "true" ]]; then
55
+ while IFS= read -r inst_json; do
56
+ local trigger action confidence domain
57
+ trigger=$(echo "$inst_json" | jq -r '.trigger // ""')
58
+ action=$(echo "$inst_json" | jq -r '.action // ""')
59
+ confidence=$(echo "$inst_json" | jq -r '.confidence // 0.75')
60
+ domain=$(echo "$inst_json" | jq -r '.domain // "workflow"')
61
+
62
+ [[ -z "$trigger" || -z "$action" ]] && continue
63
+
64
+ local promote_result
65
+ promote_result=$(_queen_promote_instinct "$trigger" "$action" "$confidence" "$domain" 2>/dev/null) || true
66
+
67
+ if echo "$promote_result" | jq -e '.ok == true' >/dev/null 2>&1; then
68
+ local was_promoted
69
+ was_promoted=$(echo "$promote_result" | jq -r '.result.promoted // false')
70
+ local reason
71
+ reason=$(echo "$promote_result" | jq -r '.result.reason // ""')
72
+
73
+ if [[ "$was_promoted" == "true" ]]; then
74
+ promoted=$((promoted + 1))
75
+ elif [[ "$reason" == "duplicate" ]]; then
76
+ already_in_queen=$((already_in_queen + 1))
77
+ fi
78
+ fi
79
+ done < <(echo "$eligible_instincts" | jq -c '.[]')
80
+ elif [[ "$eligible_count" -gt 0 && "$dry_run" == "true" ]]; then
81
+ # Dry run: count what would be promoted vs already present
82
+ local queen_file="${AETHER_ROOT:-}/.aether/QUEEN.md"
83
+ while IFS= read -r inst_json; do
84
+ local action
85
+ action=$(echo "$inst_json" | jq -r '.action // ""')
86
+ [[ -z "$action" ]] && continue
87
+
88
+ if [[ -f "$queen_file" ]] && grep -Fq -- "$action" "$queen_file" 2>/dev/null; then
89
+ already_in_queen=$((already_in_queen + 1))
90
+ else
91
+ promoted=$((promoted + 1))
92
+ fi
93
+ done < <(echo "$eligible_instincts" | jq -c '.[]')
94
+ fi
95
+
96
+ json_ok "$(jq -n \
97
+ --argjson eligible "$eligible_count" \
98
+ --argjson promoted "$promoted" \
99
+ --argjson already "$already_in_queen" \
100
+ --argjson dry "$([ "$dry_run" == "true" ] && echo true || echo false)" \
101
+ '{eligible: $eligible, promoted: $promoted, already_in_queen: $already, dry_run: $dry}')"
102
+ }
@@ -0,0 +1,121 @@
1
+ #!/bin/bash
2
+ # Curation Janitor — Expired Event/Archive Pruning
3
+ # Cleans up expired events and old archived instincts.
4
+ #
5
+ # Functions:
6
+ # _curation_janitor
7
+ #
8
+ # These functions are sourced by aether-utils.sh at startup.
9
+ # All shared infrastructure (json_ok, json_err, atomic_write, COLONY_DATA_DIR,
10
+ # DATA_DIR, error constants) is available when sourced.
11
+
12
+ # ============================================================================
13
+ # _curation_janitor
14
+ # Remove expired events and prune stale data.
15
+ # Usage: curation-janitor [--dry-run] [--max-age-days <N>]
16
+ #
17
+ # Default max-age-days: 90
18
+ # Output: json_ok with {events_removed:N, instincts_pruned:N,
19
+ # observations_pruned:N, dry_run:bool}
20
+ # ============================================================================
21
+ _curation_janitor() {
22
+ local cj_dry_run="false"
23
+ local cj_max_age_days=90
24
+
25
+ while [[ $# -gt 0 ]]; do
26
+ case "$1" in
27
+ --dry-run)
28
+ cj_dry_run="true"
29
+ shift
30
+ ;;
31
+ --max-age-days)
32
+ cj_max_age_days="${2:-90}"
33
+ shift 2
34
+ ;;
35
+ *)
36
+ shift
37
+ ;;
38
+ esac
39
+ done
40
+
41
+ local cj_data_dir="${COLONY_DATA_DIR:-${DATA_DIR:-}}"
42
+ if [[ -z "$cj_data_dir" ]]; then
43
+ json_err "$E_VALIDATION_FAILED" "curation-janitor: COLONY_DATA_DIR is not set"
44
+ fi
45
+
46
+ # Step 1: Clean expired events via event-cleanup subcommand
47
+ local cj_events_removed=0
48
+ local cj_cleanup_dry_run_flag=""
49
+ [[ "$cj_dry_run" == "true" ]] && cj_cleanup_dry_run_flag="--dry-run"
50
+
51
+ local cj_cleanup_result
52
+ if [[ -n "$cj_cleanup_dry_run_flag" ]]; then
53
+ cj_cleanup_result=$(COLONY_DATA_DIR="$cj_data_dir" DATA_DIR="$cj_data_dir" \
54
+ bash "$0" event-cleanup "$cj_cleanup_dry_run_flag" 2>/dev/null) || true
55
+ else
56
+ cj_cleanup_result=$(COLONY_DATA_DIR="$cj_data_dir" DATA_DIR="$cj_data_dir" \
57
+ bash "$0" event-cleanup 2>/dev/null) || true
58
+ fi
59
+ if echo "$cj_cleanup_result" | jq -e '.ok == true' >/dev/null 2>&1; then
60
+ cj_events_removed=$(echo "$cj_cleanup_result" | jq '.result.removed // 0' 2>/dev/null || echo 0)
61
+ fi
62
+
63
+ # Step 2: Prune archived instincts older than max-age-days
64
+ local cj_instincts_pruned=0
65
+ local cj_instincts_file="$cj_data_dir/instincts.json"
66
+
67
+ if [[ -f "$cj_instincts_file" ]] && jq empty "$cj_instincts_file" 2>/dev/null; then
68
+ local cj_cutoff
69
+ cj_cutoff=$(date -u -v"-${cj_max_age_days}d" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null \
70
+ || date -u -d "-${cj_max_age_days} days" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null \
71
+ || echo "1970-01-01T00:00:00Z")
72
+
73
+ cj_instincts_pruned=$(jq --arg cutoff "$cj_cutoff" \
74
+ '[.instincts[] | select(.archived == true and (.updated_at // .created_at) < $cutoff)] | length' \
75
+ "$cj_instincts_file" 2>/dev/null || echo 0)
76
+
77
+ if [[ "$cj_dry_run" == "false" && "$cj_instincts_pruned" -gt 0 ]]; then
78
+ local cj_updated_instincts
79
+ cj_updated_instincts=$(jq --arg cutoff "$cj_cutoff" \
80
+ '.instincts |= [.[] | select(not (.archived == true and (.updated_at // .created_at) < $cutoff))]' \
81
+ "$cj_instincts_file" 2>/dev/null)
82
+ if [[ -n "$cj_updated_instincts" ]]; then
83
+ atomic_write "$cj_instincts_file" "$cj_updated_instincts" 2>/dev/null || true
84
+ fi
85
+ fi
86
+ fi
87
+
88
+ # Step 3: Prune stale learning-observations (observation_count=1, older than 90 days)
89
+ local cj_observations_pruned=0
90
+ local cj_obs_file="$cj_data_dir/learning-observations.json"
91
+ local cj_obs_cutoff_days=90
92
+
93
+ if [[ -f "$cj_obs_file" ]] && jq empty "$cj_obs_file" 2>/dev/null; then
94
+ local cj_obs_cutoff
95
+ cj_obs_cutoff=$(date -u -v"-${cj_obs_cutoff_days}d" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null \
96
+ || date -u -d "-${cj_obs_cutoff_days} days" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null \
97
+ || echo "1970-01-01T00:00:00Z")
98
+
99
+ cj_observations_pruned=$(jq --arg cutoff "$cj_obs_cutoff" \
100
+ '[.observations[] | select((.observation_count // 0) == 1 and (.last_observed // .observed_at // "") < $cutoff)] | length' \
101
+ "$cj_obs_file" 2>/dev/null || echo 0)
102
+
103
+ if [[ "$cj_dry_run" == "false" && "$cj_observations_pruned" -gt 0 ]]; then
104
+ local cj_updated_obs
105
+ cj_updated_obs=$(jq --arg cutoff "$cj_obs_cutoff" \
106
+ '.observations |= [.[] | select(not ((.observation_count // 0) == 1 and (.last_observed // .observed_at // "") < $cutoff))]' \
107
+ "$cj_obs_file" 2>/dev/null)
108
+ if [[ -n "$cj_updated_obs" ]]; then
109
+ atomic_write "$cj_obs_file" "$cj_updated_obs" 2>/dev/null || true
110
+ fi
111
+ fi
112
+ fi
113
+
114
+ json_ok "$(jq -nc \
115
+ --argjson events_removed "$cj_events_removed" \
116
+ --argjson instincts_pruned "$cj_instincts_pruned" \
117
+ --argjson observations_pruned "$cj_observations_pruned" \
118
+ --argjson dry_run "$cj_dry_run" \
119
+ '{events_removed:$events_removed, instincts_pruned:$instincts_pruned,
120
+ observations_pruned:$observations_pruned, dry_run:$dry_run}')"
121
+ }
@@ -0,0 +1,99 @@
1
+ #!/bin/bash
2
+ # Librarian curation ant — inventory statistics across all memory stores
3
+ # Provides: _curation_librarian
4
+ #
5
+ # These functions are sourced by aether-utils.sh at startup.
6
+ # All shared infrastructure (json_ok, json_err, COLONY_DATA_DIR, error constants)
7
+ # is available.
8
+ #
9
+ # Subcommand: curation-librarian
10
+ # Generates inventory statistics for all colony memory stores.
11
+
12
+ # ============================================================================
13
+ # _curation_librarian
14
+ # Generate inventory statistics across all memory stores.
15
+ #
16
+ # Usage: curation-librarian
17
+ #
18
+ # Output:
19
+ # {
20
+ # observations: N,
21
+ # instincts: {total: N, active: N, archived: N},
22
+ # graph_edges: N,
23
+ # events: N,
24
+ # signals: {active: N, total: N},
25
+ # midden: N,
26
+ # generated_at: "ISO8601"
27
+ # }
28
+ # ============================================================================
29
+ _curation_librarian() {
30
+ local obs_file="$COLONY_DATA_DIR/learning-observations.json"
31
+ local inst_file="$COLONY_DATA_DIR/instincts.json"
32
+ local graph_file="$COLONY_DATA_DIR/instinct-graph.json"
33
+ local event_file="$COLONY_DATA_DIR/event-bus.jsonl"
34
+ local pheromone_file="$COLONY_DATA_DIR/pheromones.json"
35
+ local midden_file="$COLONY_DATA_DIR/midden/midden.json"
36
+
37
+ # Observations count
38
+ local obs_count=0
39
+ if [[ -f "$obs_file" ]]; then
40
+ obs_count=$(jq '[.observations[]] | length' "$obs_file" 2>/dev/null || echo 0)
41
+ fi
42
+
43
+ # Instinct counts: total, active, archived
44
+ local inst_total=0 inst_active=0 inst_archived=0
45
+ if [[ -f "$inst_file" ]]; then
46
+ inst_total=$(jq '[.instincts[]] | length' "$inst_file" 2>/dev/null || echo 0)
47
+ inst_active=$(jq '[.instincts[] | select(.archived == false)] | length' "$inst_file" 2>/dev/null || echo 0)
48
+ inst_archived=$(jq '[.instincts[] | select(.archived == true)] | length' "$inst_file" 2>/dev/null || echo 0)
49
+ fi
50
+
51
+ # Graph edge count
52
+ local edge_count=0
53
+ if [[ -f "$graph_file" ]]; then
54
+ edge_count=$(jq '[.edges[]] | length' "$graph_file" 2>/dev/null || echo 0)
55
+ fi
56
+
57
+ # Event count (JSONL — count non-empty lines)
58
+ local event_count=0
59
+ if [[ -f "$event_file" ]]; then
60
+ event_count=$(grep -c '.' "$event_file" 2>/dev/null || echo 0)
61
+ fi
62
+
63
+ # Signal counts: active, total
64
+ local sig_active=0 sig_total=0
65
+ if [[ -f "$pheromone_file" ]]; then
66
+ sig_total=$(jq '[.signals[]] | length' "$pheromone_file" 2>/dev/null || echo 0)
67
+ sig_active=$(jq '[.signals[] | select(.active == true)] | length' "$pheromone_file" 2>/dev/null || echo 0)
68
+ fi
69
+
70
+ # Midden entry count
71
+ local midden_count=0
72
+ if [[ -f "$midden_file" ]]; then
73
+ midden_count=$(jq '[.entries[]] | length' "$midden_file" 2>/dev/null || echo 0)
74
+ fi
75
+
76
+ local generated_at
77
+ generated_at=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
78
+
79
+ json_ok "$(jq -n \
80
+ --argjson obs "$obs_count" \
81
+ --argjson inst_total "$inst_total" \
82
+ --argjson inst_active "$inst_active" \
83
+ --argjson inst_archived "$inst_archived" \
84
+ --argjson edges "$edge_count" \
85
+ --argjson events "$event_count" \
86
+ --argjson sig_active "$sig_active" \
87
+ --argjson sig_total "$sig_total" \
88
+ --argjson midden "$midden_count" \
89
+ --arg generated_at "$generated_at" \
90
+ '{
91
+ observations: $obs,
92
+ instincts: {total: $inst_total, active: $inst_active, archived: $inst_archived},
93
+ graph_edges: $edges,
94
+ events: $events,
95
+ signals: {active: $sig_active, total: $sig_total},
96
+ midden: $midden,
97
+ generated_at: $generated_at
98
+ }')"
99
+ }