aether-colony 5.0.0 → 5.2.1

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 (317) hide show
  1. package/.aether/aether-utils.sh +3226 -3345
  2. package/.aether/agents-claude/aether-ambassador.md +265 -0
  3. package/.aether/agents-claude/aether-archaeologist.md +327 -0
  4. package/.aether/agents-claude/aether-architect.md +236 -0
  5. package/.aether/agents-claude/aether-auditor.md +271 -0
  6. package/.aether/agents-claude/aether-builder.md +224 -0
  7. package/.aether/agents-claude/aether-chaos.md +269 -0
  8. package/.aether/agents-claude/aether-chronicler.md +305 -0
  9. package/.aether/agents-claude/aether-gatekeeper.md +330 -0
  10. package/.aether/agents-claude/aether-includer.md +374 -0
  11. package/.aether/agents-claude/aether-keeper.md +272 -0
  12. package/.aether/agents-claude/aether-measurer.md +322 -0
  13. package/.aether/agents-claude/aether-oracle.md +237 -0
  14. package/.aether/agents-claude/aether-probe.md +211 -0
  15. package/.aether/agents-claude/aether-queen.md +330 -0
  16. package/.aether/agents-claude/aether-route-setter.md +178 -0
  17. package/.aether/agents-claude/aether-sage.md +418 -0
  18. package/.aether/agents-claude/aether-scout.md +179 -0
  19. package/.aether/agents-claude/aether-surveyor-disciplines.md +417 -0
  20. package/.aether/agents-claude/aether-surveyor-nest.md +355 -0
  21. package/.aether/agents-claude/aether-surveyor-pathogens.md +289 -0
  22. package/.aether/agents-claude/aether-surveyor-provisions.md +360 -0
  23. package/.aether/agents-claude/aether-tracker.md +270 -0
  24. package/.aether/agents-claude/aether-watcher.md +280 -0
  25. package/.aether/agents-claude/aether-weaver.md +248 -0
  26. package/.aether/commands/archaeology.yaml +653 -0
  27. package/.aether/commands/build.yaml +1221 -0
  28. package/.aether/commands/chaos.yaml +653 -0
  29. package/.aether/commands/colonize.yaml +442 -0
  30. package/.aether/commands/continue.yaml +1484 -0
  31. package/.aether/commands/council.yaml +509 -0
  32. package/.aether/commands/data-clean.yaml +80 -0
  33. package/.aether/commands/dream.yaml +275 -0
  34. package/.aether/commands/entomb.yaml +863 -0
  35. package/.aether/commands/export-signals.yaml +64 -0
  36. package/.aether/commands/feedback.yaml +158 -0
  37. package/.aether/commands/flag.yaml +160 -0
  38. package/.aether/commands/flags.yaml +177 -0
  39. package/.aether/commands/focus.yaml +112 -0
  40. package/.aether/commands/help.yaml +167 -0
  41. package/.aether/commands/history.yaml +137 -0
  42. package/.aether/commands/import-signals.yaml +79 -0
  43. package/.aether/commands/init.yaml +502 -0
  44. package/.aether/commands/insert-phase.yaml +102 -0
  45. package/.aether/commands/interpret.yaml +285 -0
  46. package/.aether/commands/lay-eggs.yaml +224 -0
  47. package/.aether/commands/maturity.yaml +122 -0
  48. package/.aether/commands/memory-details.yaml +74 -0
  49. package/.aether/commands/migrate-state.yaml +174 -0
  50. package/.aether/commands/oracle.yaml +1224 -0
  51. package/.aether/commands/organize.yaml +446 -0
  52. package/.aether/commands/patrol.yaml +621 -0
  53. package/.aether/commands/pause-colony.yaml +424 -0
  54. package/.aether/commands/phase.yaml +124 -0
  55. package/.aether/commands/pheromones.yaml +153 -0
  56. package/.aether/commands/plan.yaml +1364 -0
  57. package/.aether/commands/preferences.yaml +63 -0
  58. package/.aether/commands/quick.yaml +104 -0
  59. package/.aether/commands/redirect.yaml +123 -0
  60. package/.aether/commands/resume-colony.yaml +375 -0
  61. package/.aether/commands/resume.yaml +407 -0
  62. package/.aether/commands/run.yaml +229 -0
  63. package/.aether/commands/seal.yaml +1214 -0
  64. package/.aether/commands/skill-create.yaml +337 -0
  65. package/.aether/commands/status.yaml +408 -0
  66. package/.aether/commands/swarm.yaml +352 -0
  67. package/.aether/commands/tunnels.yaml +814 -0
  68. package/.aether/commands/update.yaml +131 -0
  69. package/.aether/commands/verify-castes.yaml +159 -0
  70. package/.aether/commands/watch.yaml +454 -0
  71. package/.aether/docs/INCIDENT_TEMPLATE.md +32 -0
  72. package/.aether/docs/QUEEN-SYSTEM.md +11 -11
  73. package/.aether/docs/README.md +32 -2
  74. package/.aether/docs/command-playbooks/README.md +23 -0
  75. package/.aether/docs/command-playbooks/build-complete.md +349 -0
  76. package/.aether/docs/command-playbooks/build-context.md +282 -0
  77. package/.aether/docs/command-playbooks/build-full.md +1683 -0
  78. package/.aether/docs/command-playbooks/build-prep.md +284 -0
  79. package/.aether/docs/command-playbooks/build-verify.md +405 -0
  80. package/.aether/docs/command-playbooks/build-wave.md +749 -0
  81. package/.aether/docs/command-playbooks/continue-advance.md +524 -0
  82. package/.aether/docs/command-playbooks/continue-finalize.md +447 -0
  83. package/.aether/docs/command-playbooks/continue-full.md +1725 -0
  84. package/.aether/docs/command-playbooks/continue-gates.md +686 -0
  85. package/.aether/docs/command-playbooks/continue-verify.md +407 -0
  86. package/.aether/docs/context-continuity.md +84 -0
  87. package/.aether/docs/disciplines/DISCIPLINES.md +9 -7
  88. package/.aether/docs/error-codes.md +1 -1
  89. package/.aether/docs/known-issues.md +34 -173
  90. package/.aether/docs/pheromones.md +86 -6
  91. package/.aether/docs/plans/pheromone-display-plan.md +257 -0
  92. package/.aether/docs/queen-commands.md +10 -9
  93. package/.aether/docs/source-of-truth-map.md +132 -0
  94. package/.aether/docs/xml-utilities.md +47 -0
  95. package/.aether/rules/aether-colony.md +23 -13
  96. package/.aether/scripts/incident-test-add.sh +47 -0
  97. package/.aether/scripts/weekly-audit.sh +79 -0
  98. package/.aether/skills/.index.json +649 -0
  99. package/.aether/skills/colony/.manifest.json +16 -0
  100. package/.aether/skills/colony/build-discipline/SKILL.md +78 -0
  101. package/.aether/skills/colony/colony-interaction/SKILL.md +56 -0
  102. package/.aether/skills/colony/colony-lifecycle/SKILL.md +77 -0
  103. package/.aether/skills/colony/colony-visuals/SKILL.md +112 -0
  104. package/.aether/skills/colony/context-management/SKILL.md +80 -0
  105. package/.aether/skills/colony/error-presentation/SKILL.md +99 -0
  106. package/.aether/skills/colony/pheromone-protocol/SKILL.md +79 -0
  107. package/.aether/skills/colony/pheromone-visibility/SKILL.md +81 -0
  108. package/.aether/skills/colony/state-safety/SKILL.md +84 -0
  109. package/.aether/skills/colony/worker-priming/SKILL.md +82 -0
  110. package/.aether/skills/domain/.manifest.json +24 -0
  111. package/.aether/skills/domain/README.md +33 -0
  112. package/.aether/skills/domain/django/SKILL.md +49 -0
  113. package/.aether/skills/domain/docker/SKILL.md +52 -0
  114. package/.aether/skills/domain/golang/SKILL.md +52 -0
  115. package/.aether/skills/domain/graphql/SKILL.md +51 -0
  116. package/.aether/skills/domain/html-css/SKILL.md +48 -0
  117. package/.aether/skills/domain/nextjs/SKILL.md +45 -0
  118. package/.aether/skills/domain/nodejs/SKILL.md +53 -0
  119. package/.aether/skills/domain/postgresql/SKILL.md +53 -0
  120. package/.aether/skills/domain/prisma/SKILL.md +59 -0
  121. package/.aether/skills/domain/python/SKILL.md +50 -0
  122. package/.aether/skills/domain/rails/SKILL.md +52 -0
  123. package/.aether/skills/domain/react/SKILL.md +45 -0
  124. package/.aether/skills/domain/rest-api/SKILL.md +58 -0
  125. package/.aether/skills/domain/svelte/SKILL.md +47 -0
  126. package/.aether/skills/domain/tailwind/SKILL.md +45 -0
  127. package/.aether/skills/domain/testing/SKILL.md +53 -0
  128. package/.aether/skills/domain/typescript/SKILL.md +58 -0
  129. package/.aether/skills/domain/vue/SKILL.md +49 -0
  130. package/.aether/templates/QUEEN.md.template +23 -41
  131. package/.aether/templates/colony-state-reset.jq.template +1 -0
  132. package/.aether/templates/colony-state.template.json +4 -0
  133. package/.aether/templates/learning-observations.template.json +6 -0
  134. package/.aether/templates/midden.template.json +13 -0
  135. package/.aether/templates/pheromones.template.json +6 -0
  136. package/.aether/templates/session.template.json +9 -0
  137. package/.aether/utils/atomic-write.sh +63 -17
  138. package/.aether/utils/chamber-utils.sh +145 -2
  139. package/.aether/utils/council.sh +425 -0
  140. package/.aether/utils/emoji-audit.sh +166 -0
  141. package/.aether/utils/error-handler.sh +21 -7
  142. package/.aether/utils/file-lock.sh +182 -27
  143. package/.aether/utils/flag.sh +278 -0
  144. package/.aether/utils/hive.sh +572 -0
  145. package/.aether/utils/immune.sh +508 -0
  146. package/.aether/utils/learning.sh +1928 -0
  147. package/.aether/utils/midden.sh +520 -0
  148. package/.aether/utils/oracle/oracle.md +168 -0
  149. package/.aether/utils/oracle/oracle.sh +1023 -0
  150. package/.aether/utils/pheromone.sh +2029 -0
  151. package/.aether/utils/queen.sh +1710 -0
  152. package/.aether/utils/scan.sh +860 -0
  153. package/.aether/utils/semantic-cli.sh +10 -8
  154. package/.aether/utils/session.sh +816 -0
  155. package/.aether/utils/skills.sh +509 -0
  156. package/.aether/utils/spawn-tree.sh +103 -271
  157. package/.aether/utils/spawn.sh +260 -0
  158. package/.aether/utils/state-api.sh +389 -0
  159. package/.aether/utils/state-loader.sh +8 -6
  160. package/.aether/utils/suggest.sh +611 -0
  161. package/.aether/utils/swarm-display.sh +10 -1
  162. package/.aether/utils/swarm.sh +1004 -0
  163. package/.aether/utils/watch-spawn-tree.sh +11 -2
  164. package/.aether/utils/xml-compose.sh +2 -2
  165. package/.aether/utils/xml-convert.sh +9 -5
  166. package/.aether/utils/xml-core.sh +5 -9
  167. package/.aether/utils/xml-query.sh +4 -4
  168. package/.aether/workers.md +86 -67
  169. package/.claude/agents/ant/aether-ambassador.md +2 -1
  170. package/.claude/agents/ant/aether-archaeologist.md +6 -1
  171. package/.claude/agents/ant/aether-architect.md +236 -0
  172. package/.claude/agents/ant/aether-auditor.md +6 -1
  173. package/.claude/agents/ant/aether-builder.md +38 -1
  174. package/.claude/agents/ant/aether-chaos.md +2 -1
  175. package/.claude/agents/ant/aether-chronicler.md +1 -0
  176. package/.claude/agents/ant/aether-gatekeeper.md +6 -1
  177. package/.claude/agents/ant/aether-includer.md +1 -0
  178. package/.claude/agents/ant/aether-keeper.md +1 -0
  179. package/.claude/agents/ant/aether-measurer.md +6 -1
  180. package/.claude/agents/ant/aether-oracle.md +237 -0
  181. package/.claude/agents/ant/aether-probe.md +2 -1
  182. package/.claude/agents/ant/aether-queen.md +6 -1
  183. package/.claude/agents/ant/aether-route-setter.md +6 -1
  184. package/.claude/agents/ant/aether-sage.md +68 -3
  185. package/.claude/agents/ant/aether-scout.md +38 -1
  186. package/.claude/agents/ant/aether-surveyor-disciplines.md +2 -1
  187. package/.claude/agents/ant/aether-surveyor-nest.md +2 -1
  188. package/.claude/agents/ant/aether-surveyor-pathogens.md +2 -1
  189. package/.claude/agents/ant/aether-surveyor-provisions.md +2 -1
  190. package/.claude/agents/ant/aether-tracker.md +6 -1
  191. package/.claude/agents/ant/aether-watcher.md +37 -1
  192. package/.claude/agents/ant/aether-weaver.md +2 -1
  193. package/.claude/commands/ant/archaeology.md +1 -8
  194. package/.claude/commands/ant/build.md +43 -1159
  195. package/.claude/commands/ant/chaos.md +1 -14
  196. package/.claude/commands/ant/colonize.md +3 -14
  197. package/.claude/commands/ant/continue.md +40 -1026
  198. package/.claude/commands/ant/council.md +213 -15
  199. package/.claude/commands/ant/data-clean.md +81 -0
  200. package/.claude/commands/ant/dream.md +12 -9
  201. package/.claude/commands/ant/entomb.md +62 -87
  202. package/.claude/commands/ant/export-signals.md +57 -0
  203. package/.claude/commands/ant/feedback.md +18 -0
  204. package/.claude/commands/ant/flag.md +12 -0
  205. package/.claude/commands/ant/flags.md +22 -8
  206. package/.claude/commands/ant/focus.md +18 -0
  207. package/.claude/commands/ant/help.md +40 -8
  208. package/.claude/commands/ant/history.md +3 -0
  209. package/.claude/commands/ant/import-signals.md +71 -0
  210. package/.claude/commands/ant/init.md +349 -191
  211. package/.claude/commands/ant/insert-phase.md +105 -0
  212. package/.claude/commands/ant/interpret.md +11 -0
  213. package/.claude/commands/ant/lay-eggs.md +167 -158
  214. package/.claude/commands/ant/maturity.md +22 -11
  215. package/.claude/commands/ant/memory-details.md +77 -0
  216. package/.claude/commands/ant/migrate-state.md +6 -0
  217. package/.claude/commands/ant/oracle.md +317 -62
  218. package/.claude/commands/ant/organize.md +10 -5
  219. package/.claude/commands/ant/patrol.md +620 -0
  220. package/.claude/commands/ant/pause-colony.md +8 -22
  221. package/.claude/commands/ant/phase.md +26 -37
  222. package/.claude/commands/ant/pheromones.md +156 -0
  223. package/.claude/commands/ant/plan.md +199 -50
  224. package/.claude/commands/ant/preferences.md +65 -0
  225. package/.claude/commands/ant/quick.md +100 -0
  226. package/.claude/commands/ant/redirect.md +18 -0
  227. package/.claude/commands/ant/resume-colony.md +37 -22
  228. package/.claude/commands/ant/resume.md +60 -7
  229. package/.claude/commands/ant/run.md +231 -0
  230. package/.claude/commands/ant/seal.md +506 -78
  231. package/.claude/commands/ant/skill-create.md +286 -0
  232. package/.claude/commands/ant/status.md +171 -1
  233. package/.claude/commands/ant/swarm.md +11 -23
  234. package/.claude/commands/ant/tunnels.md +1 -0
  235. package/.claude/commands/ant/update.md +58 -135
  236. package/.claude/commands/ant/verify-castes.md +90 -42
  237. package/.claude/commands/ant/watch.md +1 -0
  238. package/.opencode/agents/aether-ambassador.md +1 -1
  239. package/.opencode/agents/aether-architect.md +133 -0
  240. package/.opencode/agents/aether-builder.md +3 -3
  241. package/.opencode/agents/aether-oracle.md +137 -0
  242. package/.opencode/agents/aether-queen.md +1 -1
  243. package/.opencode/agents/aether-route-setter.md +1 -1
  244. package/.opencode/agents/aether-scout.md +1 -1
  245. package/.opencode/agents/aether-surveyor-disciplines.md +6 -1
  246. package/.opencode/agents/aether-surveyor-nest.md +6 -1
  247. package/.opencode/agents/aether-surveyor-pathogens.md +6 -1
  248. package/.opencode/agents/aether-surveyor-provisions.md +6 -1
  249. package/.opencode/agents/aether-tracker.md +1 -1
  250. package/.opencode/agents/aether-watcher.md +1 -1
  251. package/.opencode/agents/aether-weaver.md +1 -1
  252. package/.opencode/commands/ant/archaeology.md +7 -14
  253. package/.opencode/commands/ant/build.md +54 -88
  254. package/.opencode/commands/ant/chaos.md +7 -24
  255. package/.opencode/commands/ant/colonize.md +10 -17
  256. package/.opencode/commands/ant/continue.md +595 -66
  257. package/.opencode/commands/ant/council.md +150 -18
  258. package/.opencode/commands/ant/data-clean.md +77 -0
  259. package/.opencode/commands/ant/dream.md +15 -17
  260. package/.opencode/commands/ant/entomb.md +28 -18
  261. package/.opencode/commands/ant/export-signals.md +54 -0
  262. package/.opencode/commands/ant/feedback.md +24 -5
  263. package/.opencode/commands/ant/flag.md +16 -4
  264. package/.opencode/commands/ant/flags.md +24 -10
  265. package/.opencode/commands/ant/focus.md +22 -5
  266. package/.opencode/commands/ant/help.md +41 -8
  267. package/.opencode/commands/ant/history.md +9 -0
  268. package/.opencode/commands/ant/import-signals.md +68 -0
  269. package/.opencode/commands/ant/init.md +396 -154
  270. package/.opencode/commands/ant/insert-phase.md +111 -0
  271. package/.opencode/commands/ant/interpret.md +16 -0
  272. package/.opencode/commands/ant/lay-eggs.md +184 -112
  273. package/.opencode/commands/ant/maturity.md +18 -2
  274. package/.opencode/commands/ant/memory-details.md +83 -0
  275. package/.opencode/commands/ant/migrate-state.md +12 -0
  276. package/.opencode/commands/ant/oracle.md +322 -67
  277. package/.opencode/commands/ant/organize.md +14 -12
  278. package/.opencode/commands/ant/patrol.md +626 -0
  279. package/.opencode/commands/ant/pause-colony.md +12 -29
  280. package/.opencode/commands/ant/phase.md +30 -40
  281. package/.opencode/commands/ant/pheromones.md +162 -0
  282. package/.opencode/commands/ant/plan.md +210 -57
  283. package/.opencode/commands/ant/preferences.md +71 -0
  284. package/.opencode/commands/ant/quick.md +91 -0
  285. package/.opencode/commands/ant/redirect.md +22 -5
  286. package/.opencode/commands/ant/resume-colony.md +41 -29
  287. package/.opencode/commands/ant/resume.md +80 -20
  288. package/.opencode/commands/ant/run.md +237 -0
  289. package/.opencode/commands/ant/seal.md +230 -25
  290. package/.opencode/commands/ant/skill-create.md +63 -0
  291. package/.opencode/commands/ant/status.md +125 -30
  292. package/.opencode/commands/ant/swarm.md +3 -345
  293. package/.opencode/commands/ant/tunnels.md +3 -9
  294. package/.opencode/commands/ant/update.md +63 -127
  295. package/.opencode/commands/ant/verify-castes.md +96 -42
  296. package/.opencode/commands/ant/watch.md +7 -0
  297. package/CHANGELOG.md +368 -1
  298. package/README.md +195 -324
  299. package/bin/cli.js +236 -429
  300. package/bin/generate-commands.js +186 -0
  301. package/bin/generate-commands.sh +128 -89
  302. package/bin/lib/spawn-logger.js +0 -15
  303. package/bin/lib/update-transaction.js +285 -35
  304. package/bin/npx-install.js +178 -0
  305. package/bin/validate-package.sh +85 -3
  306. package/package.json +16 -4
  307. package/.aether/CONTEXT.md +0 -160
  308. package/.aether/docs/QUEEN.md +0 -84
  309. package/.aether/exchange/colony-registry.xml +0 -11
  310. package/.aether/exchange/pheromones.xml +0 -87
  311. package/.aether/exchange/queen-wisdom.xml +0 -14
  312. package/.aether/model-profiles.yaml +0 -100
  313. package/.aether/utils/spawn-with-model.sh +0 -56
  314. package/bin/lib/model-profiles.js +0 -445
  315. package/bin/lib/model-verify.js +0 -288
  316. package/bin/lib/proxy-health.js +0 -253
  317. package/bin/lib/telemetry.js +0 -441
@@ -0,0 +1,520 @@
1
+ #!/bin/bash
2
+ # Midden (failure tracking) utility functions — extracted from aether-utils.sh
3
+ # Provides: _midden_write, _midden_recent_failures, _midden_review, _midden_acknowledge
4
+ #
5
+ # These functions are sourced by aether-utils.sh at startup.
6
+ # All shared infrastructure (json_ok, json_err, atomic_write, acquire_lock,
7
+ # release_lock, LOCK_DIR, DATA_DIR, SCRIPT_DIR, error constants) is available.
8
+
9
+ _midden_try_write() {
10
+ # Helper: write updated JSON to midden file with retry
11
+ # Usage: _midden_try_write <updated_json> <midden_file>
12
+ # Returns: 0 on success, 1 on failure
13
+ local mtw_json="$1"
14
+ local mtw_file="$2"
15
+ local mtw_tmp="${mtw_file}.tmp.$$"
16
+
17
+ if ! { printf '%s\n' "$mtw_json" > "$mtw_tmp" && mv "$mtw_tmp" "$mtw_file"; }; then
18
+ # Silent retry (once)
19
+ if ! { printf '%s\n' "$mtw_json" > "$mtw_tmp" && mv "$mtw_tmp" "$mtw_file"; }; then
20
+ echo "Warning: Midden write failed after retry -- entry may not have been saved." >&2
21
+ return 1
22
+ fi
23
+ fi
24
+ return 0
25
+ }
26
+
27
+ _midden_write() {
28
+ # Write a warning/observation to the midden for later review
29
+ # Usage: midden-write <category> <message> <source>
30
+ # Example: midden-write "security" "High CVEs found: 3" "gatekeeper"
31
+ # Returns: JSON with success status and entry details
32
+
33
+ mw_category="${1:-general}"
34
+ mw_message="${2:-}"
35
+ mw_source="${3:-unknown}"
36
+
37
+ # Graceful degradation: if no message, return success but note it
38
+ if [[ -z "$mw_message" ]]; then
39
+ json_ok "{\"success\":true,\"warning\":\"no_message_provided\",\"entry_id\":null}"
40
+ return 0
41
+ fi
42
+
43
+ mw_midden_dir="$COLONY_DATA_DIR/midden"
44
+ mw_midden_file="$mw_midden_dir/midden.json"
45
+ mw_timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
46
+ mw_entry_id="midden_$(date +%s)_$$"
47
+
48
+ # Create midden directory if it doesn't exist
49
+ mkdir -p "$mw_midden_dir"
50
+
51
+ # Initialize midden.json if it doesn't exist
52
+ if [[ ! -f "$mw_midden_file" ]]; then
53
+ printf '%s\n' '{"version":"1.0.0","entries":[]}' > "$mw_midden_file"
54
+ fi
55
+
56
+ # Create the new entry using jq for safe JSON construction
57
+ mw_new_entry=$(jq -n \
58
+ --arg id "$mw_entry_id" \
59
+ --arg ts "$mw_timestamp" \
60
+ --arg cat "$mw_category" \
61
+ --arg src "$mw_source" \
62
+ --arg msg "$mw_message" \
63
+ '{id: $id, timestamp: $ts, category: $cat, source: $src, message: $msg, reviewed: false}')
64
+
65
+ # Append to midden.json using jq with locking
66
+ if acquire_lock "$mw_midden_file" 2>/dev/null; then
67
+ mw_updated_midden=$(jq --argjson entry "$mw_new_entry" '
68
+ .entries += [$entry] |
69
+ .entry_count = (.entries | length)
70
+ ' "$mw_midden_file" 2>/dev/null)
71
+
72
+ if [[ -n "$mw_updated_midden" ]]; then
73
+ _midden_try_write "$mw_updated_midden" "$mw_midden_file"
74
+ release_lock 2>/dev/null || true
75
+ mw_total=$(jq '.entries | length' "$mw_midden_file" 2>/dev/null || echo 0)
76
+ json_ok "$(jq -n --arg entry_id "$mw_entry_id" --arg category "$mw_category" --argjson midden_total "$mw_total" \
77
+ '{success: true, entry_id: $entry_id, category: $category, midden_total: $midden_total}')"
78
+ else
79
+ release_lock 2>/dev/null || true
80
+ json_ok "{\"success\":true,\"warning\":\"jq_processing_failed\",\"entry_id\":null}"
81
+ fi
82
+ else
83
+ # Lock failed — graceful degradation, try without lock
84
+ echo "Warning: Midden write completed without lock -- if another write happened at the same time, one entry may be missing." >&2
85
+ mw_updated_midden=$(jq --argjson entry "$mw_new_entry" '
86
+ .entries += [$entry] |
87
+ .entry_count = (.entries | length)
88
+ ' "$mw_midden_file" 2>/dev/null)
89
+
90
+ if [[ -n "$mw_updated_midden" ]]; then
91
+ _midden_try_write "$mw_updated_midden" "$mw_midden_file"
92
+ json_ok "$(jq -n --arg entry_id "$mw_entry_id" --arg category "$mw_category" \
93
+ '{success: true, entry_id: $entry_id, category: $category, warning: "lock_unavailable"}')"
94
+ else
95
+ json_ok "{\"success\":true,\"warning\":\"jq_processing_failed\",\"entry_id\":null}"
96
+ fi
97
+ fi
98
+ }
99
+
100
+ _midden_recent_failures() {
101
+ # Extract recent failure entries from midden.json
102
+ # Usage: midden-recent-failures [limit]
103
+ # Returns: JSON with count and failures array
104
+
105
+ limit="${1:-5}"
106
+ midden_file="$COLONY_DATA_DIR/midden/midden.json"
107
+
108
+ if [[ ! -f "$midden_file" ]]; then
109
+ echo '{"count":0,"failures":[]}'
110
+ return 0
111
+ fi
112
+
113
+ # Extract failures from .entries[], sort by timestamp descending, limit results
114
+ result=$(jq --argjson limit "$limit" '{
115
+ "count": ([.entries[]?] | length),
116
+ "failures": ([.entries[]?] | sort_by(.timestamp) | reverse | .[:$limit] | [.[] | {timestamp, category, source, message}])
117
+ }' "$midden_file" 2>/dev/null)
118
+
119
+ if [[ -z "$result" ]]; then
120
+ echo '{"count":0,"failures":[]}'
121
+ else
122
+ echo "$result"
123
+ fi
124
+ return 0
125
+ }
126
+
127
+ _midden_review() {
128
+ # Review unacknowledged midden entries grouped by category
129
+ # Usage: midden-review [--category <cat>] [--limit N] [--include-acknowledged]
130
+ # Returns: JSON with unacknowledged_count, categories summary, and entries array
131
+
132
+ mr_category=""
133
+ mr_limit=20
134
+ mr_include_ack=false
135
+
136
+ while [[ $# -gt 0 ]]; do
137
+ case "$1" in
138
+ --category) mr_category="${2:-}"; shift 2 ;;
139
+ --limit) mr_limit="${2:-20}"; shift 2 ;;
140
+ --include-acknowledged) mr_include_ack=true; shift ;;
141
+ *) shift ;;
142
+ esac
143
+ done
144
+
145
+ mr_midden_file="$COLONY_DATA_DIR/midden/midden.json"
146
+
147
+ if [[ ! -f "$mr_midden_file" ]]; then
148
+ json_ok '{"unacknowledged_count":0,"categories":{},"entries":[]}'
149
+ return 0
150
+ fi
151
+
152
+ # Build jq filter based on options
153
+ mr_result=$(jq \
154
+ --arg category "$mr_category" \
155
+ --argjson limit "$mr_limit" \
156
+ --argjson include_ack "$mr_include_ack" \
157
+ '
158
+ # Start with all entries
159
+ [.entries // [] | .[] |
160
+ # Filter acknowledged unless --include-acknowledged
161
+ if $include_ack then . else select(.acknowledged != true) end |
162
+ # Filter by category if specified
163
+ if ($category | length) > 0 then select(.category == $category) else . end
164
+ ] |
165
+ # Sort by timestamp descending
166
+ sort_by(.timestamp) | reverse |
167
+ # Compute categories before limiting
168
+ . as $all |
169
+ # Apply limit
170
+ ($all | .[:$limit]) as $limited |
171
+ # Group $all by category for counts
172
+ ($all | group_by(.category) | map({key: .[0].category, value: length}) | from_entries) as $cats |
173
+ {
174
+ unacknowledged_count: ($all | length),
175
+ categories: $cats,
176
+ entries: $limited
177
+ }
178
+ ' "$mr_midden_file" 2>/dev/null)
179
+
180
+ if [[ -z "$mr_result" ]]; then
181
+ json_ok '{"unacknowledged_count":0,"categories":{},"entries":[]}'
182
+ else
183
+ json_ok "$mr_result"
184
+ fi
185
+ return 0
186
+ }
187
+
188
+ _midden_ingest_errors() {
189
+ # Ingest entries from errors.log into midden
190
+ # Usage: midden-ingest-errors [--dry-run]
191
+ # Returns: JSON with count of ingested entries
192
+ # After ingestion, moves errors.log to errors.log.ingested
193
+
194
+ mie_dry_run=false
195
+ while [[ $# -gt 0 ]]; do
196
+ case "$1" in
197
+ --dry-run) mie_dry_run=true; shift ;;
198
+ *) shift ;;
199
+ esac
200
+ done
201
+
202
+ mie_errors_file="$COLONY_DATA_DIR/errors.log"
203
+
204
+ # No errors.log → nothing to ingest
205
+ if [[ ! -f "$mie_errors_file" ]]; then
206
+ json_ok '{"ingested":0}'
207
+ return 0
208
+ fi
209
+
210
+ # Empty file → nothing to ingest
211
+ if [[ ! -s "$mie_errors_file" ]]; then
212
+ json_ok '{"ingested":0}'
213
+ return 0
214
+ fi
215
+
216
+ mie_count=0
217
+
218
+ # Read line by line (avoid pipe-to-while subshell)
219
+ while IFS= read -r mie_line; do
220
+ # Skip blank lines
221
+ [[ -z "$mie_line" ]] && continue
222
+
223
+ # Parse timestamp from [YYYY-...Z] prefix
224
+ mie_timestamp=""
225
+ mie_message="$mie_line"
226
+ if [[ "$mie_line" =~ ^\[([^\]]+)\]\ (.*) ]]; then
227
+ mie_timestamp="${BASH_REMATCH[1]}"
228
+ mie_message="${BASH_REMATCH[2]}"
229
+ fi
230
+
231
+ mie_count=$((mie_count + 1))
232
+
233
+ if [[ "$mie_dry_run" == "false" ]]; then
234
+ _midden_write "error_log" "$mie_message" "error-handler" >/dev/null 2>&1 || true
235
+ fi
236
+ done < "$mie_errors_file"
237
+
238
+ # Move the file (not dry-run only)
239
+ if [[ "$mie_dry_run" == "false" && "$mie_count" -gt 0 ]]; then
240
+ mv "$mie_errors_file" "${mie_errors_file}.ingested"
241
+ fi
242
+
243
+ json_ok "{\"ingested\":$mie_count}"
244
+ return 0
245
+ }
246
+
247
+ _midden_search() {
248
+ # Search midden entries by keyword match in message field
249
+ # Usage: midden-search <query> [--category <cat>] [--source <src>] [--limit N] [--include-acknowledged]
250
+ # Returns: JSON with query, match_count, and entries array
251
+
252
+ ms_query=""
253
+ ms_category=""
254
+ ms_source=""
255
+ ms_limit=10
256
+ ms_include_ack=false
257
+
258
+ # First positional arg is the query
259
+ if [[ $# -gt 0 && "$1" != --* ]]; then
260
+ ms_query="$1"
261
+ shift
262
+ fi
263
+
264
+ while [[ $# -gt 0 ]]; do
265
+ case "$1" in
266
+ --category) ms_category="${2:-}"; shift 2 ;;
267
+ --source) ms_source="${2:-}"; shift 2 ;;
268
+ --limit) ms_limit="${2:-10}"; shift 2 ;;
269
+ --include-acknowledged) ms_include_ack=true; shift ;;
270
+ *) shift ;;
271
+ esac
272
+ done
273
+
274
+ ms_midden_file="$COLONY_DATA_DIR/midden/midden.json"
275
+
276
+ if [[ ! -f "$ms_midden_file" ]]; then
277
+ json_ok "{\"query\":$(printf '%s' "$ms_query" | jq -Rs .),\"match_count\":0,\"entries\":[]}"
278
+ return 0
279
+ fi
280
+
281
+ ms_result=$(jq \
282
+ --arg query "$ms_query" \
283
+ --arg category "$ms_category" \
284
+ --arg source "$ms_source" \
285
+ --argjson limit "$ms_limit" \
286
+ --argjson include_ack "$ms_include_ack" \
287
+ '
288
+ [.entries // [] | .[] |
289
+ # Filter acknowledged unless --include-acknowledged
290
+ if $include_ack then . else select(.acknowledged != true) end |
291
+ # Filter by category if specified
292
+ if ($category | length) > 0 then select(.category == $category) else . end |
293
+ # Filter by source if specified
294
+ if ($source | length) > 0 then select(.source == $source) else . end |
295
+ # Filter by keyword match in message (case-insensitive)
296
+ if ($query | length) > 0 then
297
+ select(.message | ascii_downcase | contains($query | ascii_downcase))
298
+ else
299
+ .
300
+ end
301
+ ] |
302
+ sort_by(.timestamp) | reverse |
303
+ . as $all |
304
+ {
305
+ query: $query,
306
+ match_count: ($all | length),
307
+ entries: ($all | .[:$limit])
308
+ }
309
+ ' "$ms_midden_file" 2>/dev/null)
310
+
311
+ if [[ -z "$ms_result" ]]; then
312
+ json_ok "{\"query\":$(printf '%s' "$ms_query" | jq -Rs .),\"match_count\":0,\"entries\":[]}"
313
+ else
314
+ json_ok "$ms_result"
315
+ fi
316
+ return 0
317
+ }
318
+
319
+ _midden_tag() {
320
+ # Add or remove a tag from a midden entry's tags array
321
+ # Usage: midden-tag --id <entry_id> --tag <tag_name>
322
+ # OR: midden-tag --id <entry_id> --untag <tag_name>
323
+ # Returns: JSON with entry_id, tags array, and action
324
+
325
+ mt_id=""
326
+ mt_tag=""
327
+ mt_untag=""
328
+
329
+ while [[ $# -gt 0 ]]; do
330
+ case "$1" in
331
+ --id) mt_id="${2:-}"; shift 2 ;;
332
+ --tag) mt_tag="${2:-}"; shift 2 ;;
333
+ --untag) mt_untag="${2:-}"; shift 2 ;;
334
+ *) shift ;;
335
+ esac
336
+ done
337
+
338
+ # Validate: need --id
339
+ if [[ -z "$mt_id" ]]; then
340
+ json_err "$E_VALIDATION_FAILED" "midden-tag requires --id"
341
+ fi
342
+
343
+ # Validate: need --tag or --untag (but not both)
344
+ if [[ -z "$mt_tag" && -z "$mt_untag" ]]; then
345
+ json_err "$E_VALIDATION_FAILED" "midden-tag requires --tag or --untag"
346
+ fi
347
+
348
+ if [[ -n "$mt_tag" && -n "$mt_untag" ]]; then
349
+ json_err "$E_VALIDATION_FAILED" "midden-tag requires --tag or --untag, not both"
350
+ fi
351
+
352
+ mt_midden_file="$COLONY_DATA_DIR/midden/midden.json"
353
+
354
+ if [[ ! -f "$mt_midden_file" ]]; then
355
+ json_err "$E_FILE_NOT_FOUND" "midden.json not found"
356
+ fi
357
+
358
+ # Check entry exists
359
+ mt_exists=$(jq --arg id "$mt_id" '[.entries[]? | select(.id == $id)] | length > 0' "$mt_midden_file" 2>/dev/null || echo "false")
360
+ if [[ "$mt_exists" != "true" ]]; then
361
+ json_err "$E_RESOURCE_NOT_FOUND" "Midden entry '$mt_id' not found"
362
+ fi
363
+
364
+ # Acquire lock with trap-based cleanup
365
+ acquire_lock "$mt_midden_file" || {
366
+ json_err "$E_LOCK_FAILED" "Failed to acquire lock on midden.json"
367
+ }
368
+ trap 'release_lock 2>/dev/null || true' EXIT
369
+
370
+ if [[ -n "$mt_tag" ]]; then
371
+ # Add tag — create tags array if absent, append if tag not already present
372
+ mt_updated=$(jq \
373
+ --arg id "$mt_id" \
374
+ --arg tag "$mt_tag" \
375
+ '
376
+ .entries = [.entries[] |
377
+ if .id == $id then
378
+ . + {tags: ((.tags // []) | if contains([$tag]) then . else . + [$tag] end)}
379
+ else
380
+ .
381
+ end
382
+ ]
383
+ ' "$mt_midden_file" 2>/dev/null)
384
+ mt_action="added"
385
+ else
386
+ # Remove tag — remove from tags array if present
387
+ mt_updated=$(jq \
388
+ --arg id "$mt_id" \
389
+ --arg tag "$mt_untag" \
390
+ '
391
+ .entries = [.entries[] |
392
+ if .id == $id then
393
+ . + {tags: ((.tags // []) | map(select(. != $tag)))}
394
+ else
395
+ .
396
+ end
397
+ ]
398
+ ' "$mt_midden_file" 2>/dev/null)
399
+ mt_action="removed"
400
+ mt_tag="$mt_untag"
401
+ fi
402
+
403
+ if [[ -z "$mt_updated" ]]; then
404
+ trap - EXIT
405
+ release_lock 2>/dev/null || true
406
+ json_err "$E_INTERNAL" "Failed to update midden.json"
407
+ fi
408
+
409
+ atomic_write "$mt_midden_file" "$mt_updated"
410
+
411
+ trap - EXIT
412
+ release_lock 2>/dev/null || true
413
+
414
+ # Read back the updated tags for the entry
415
+ mt_tags=$(jq --arg id "$mt_id" '[.entries[]? | select(.id == $id) | .tags // []] | .[0] // []' "$mt_midden_file" 2>/dev/null || echo "[]")
416
+
417
+ json_ok "$(jq -n \
418
+ --arg entry_id "$mt_id" \
419
+ --argjson tags "$mt_tags" \
420
+ --arg action "$mt_action" \
421
+ '{entry_id: $entry_id, tags: $tags, action: $action}')"
422
+ return 0
423
+ }
424
+
425
+ _midden_acknowledge() {
426
+ # Acknowledge midden entries by id or by category
427
+ # Usage: midden-acknowledge --id <entry_id> [--reason <reason>]
428
+ # OR: midden-acknowledge --category <cat> --reason <reason>
429
+ # Returns: JSON with acknowledged=true, count, and reason
430
+
431
+ ma_id=""
432
+ ma_category=""
433
+ ma_reason=""
434
+
435
+ while [[ $# -gt 0 ]]; do
436
+ case "$1" in
437
+ --id) ma_id="${2:-}"; shift 2 ;;
438
+ --category) ma_category="${2:-}"; shift 2 ;;
439
+ --reason) ma_reason="${2:-}"; shift 2 ;;
440
+ *) shift ;;
441
+ esac
442
+ done
443
+
444
+ # Validate: need either --id or --category
445
+ if [[ -z "$ma_id" && -z "$ma_category" ]]; then
446
+ json_err "$E_VALIDATION_FAILED" "midden-acknowledge requires --id or --category"
447
+ fi
448
+
449
+ ma_midden_file="$COLONY_DATA_DIR/midden/midden.json"
450
+
451
+ if [[ ! -f "$ma_midden_file" ]]; then
452
+ json_err "$E_FILE_NOT_FOUND" "midden.json not found"
453
+ fi
454
+
455
+ ma_now=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
456
+
457
+ # Acquire lock with trap-based cleanup
458
+ acquire_lock "$ma_midden_file" || {
459
+ json_err "$E_LOCK_FAILED" "Failed to acquire lock on midden.json"
460
+ }
461
+ trap 'release_lock 2>/dev/null || true' EXIT
462
+
463
+ if [[ -n "$ma_id" ]]; then
464
+ # Acknowledge single entry by id
465
+ ma_exists=$(jq --arg id "$ma_id" '[.entries[]? | select(.id == $id)] | length > 0' "$ma_midden_file" 2>/dev/null || echo "false")
466
+ if [[ "$ma_exists" != "true" ]]; then
467
+ trap - EXIT
468
+ release_lock 2>/dev/null || true
469
+ json_err "$E_RESOURCE_NOT_FOUND" "Midden entry '$ma_id' not found"
470
+ fi
471
+
472
+ ma_updated=$(jq \
473
+ --arg id "$ma_id" \
474
+ --arg now "$ma_now" \
475
+ --arg reason "$ma_reason" \
476
+ '
477
+ .entries = [.entries[] |
478
+ if .id == $id then
479
+ . + {acknowledged: true, acknowledged_at: $now, acknowledge_reason: $reason}
480
+ else
481
+ .
482
+ end
483
+ ]
484
+ ' "$ma_midden_file" 2>/dev/null)
485
+
486
+ ma_count=1
487
+ else
488
+ # Acknowledge all entries matching category
489
+ ma_count=$(jq --arg cat "$ma_category" '[.entries[]? | select(.category == $cat and .acknowledged != true)] | length' "$ma_midden_file" 2>/dev/null || echo "0")
490
+
491
+ ma_updated=$(jq \
492
+ --arg cat "$ma_category" \
493
+ --arg now "$ma_now" \
494
+ --arg reason "$ma_reason" \
495
+ '
496
+ .entries = [.entries[] |
497
+ if .category == $cat and .acknowledged != true then
498
+ . + {acknowledged: true, acknowledged_at: $now, acknowledge_reason: $reason}
499
+ else
500
+ .
501
+ end
502
+ ]
503
+ ' "$ma_midden_file" 2>/dev/null)
504
+ fi
505
+
506
+ if [[ -z "$ma_updated" ]]; then
507
+ trap - EXIT
508
+ release_lock 2>/dev/null || true
509
+ json_err "$E_INTERNAL" "Failed to update midden.json"
510
+ fi
511
+
512
+ atomic_write "$ma_midden_file" "$ma_updated"
513
+
514
+ trap - EXIT
515
+ release_lock 2>/dev/null || true
516
+
517
+ json_ok "$(jq -n --argjson count "$ma_count" --arg reason "$ma_reason" \
518
+ '{acknowledged: true, count: $count, reason: $reason}')"
519
+ return 0
520
+ }
@@ -0,0 +1,168 @@
1
+ You are an **Oracle Ant** -- a deep research agent in the Aether Colony.
2
+
3
+ ## Mission
4
+
5
+ Research a topic thoroughly. Each iteration targets knowledge gaps and deepens
6
+ understanding. You are working through a structured research plan with tracked
7
+ sub-questions, confidence scores, and accumulated findings.
8
+
9
+ ## Phase Directive
10
+
11
+ Your current research phase and specific instructions were provided above this
12
+ prompt. Follow them. The phase determines your strategy for this iteration.
13
+
14
+ ## Steering Signals
15
+
16
+ If steering signals appear above this prompt, they were emitted by the user:
17
+
18
+ - **REDIRECT** signals are HARD CONSTRAINTS. You MUST follow them. If a REDIRECT
19
+ conflicts with your planned approach, change your approach.
20
+ - **FOCUS** signals indicate priority areas. When choosing your target question,
21
+ prefer questions related to focus areas. If no questions match, fall back to
22
+ default targeting (lowest-confidence).
23
+ - **FEEDBACK** signals are gentle adjustments. Incorporate them where appropriate
24
+ into your research approach and output style.
25
+
26
+ If no steering signals appear, follow default targeting as described in Instructions.
27
+
28
+ ## Instructions
29
+
30
+ ### Step 1: Read State Files
31
+
32
+ Read these files to understand the current research state:
33
+
34
+ - `.aether/oracle/state.json` -- Session metadata (topic, scope, iteration, phase, confidence)
35
+ - `.aether/oracle/plan.json` -- Sub-questions with status, confidence, and iteration history
36
+ - `.aether/oracle/gaps.md` -- Current knowledge gaps and contradictions
37
+ - `.aether/oracle/synthesis.md` -- Accumulated findings organized by question
38
+
39
+ Note the current `iteration` and `phase` from state.json. Your phase directive
40
+ above tells you how to behave this iteration.
41
+
42
+ ### Step 2: Identify Target
43
+
44
+ Select your target question based on the current phase:
45
+
46
+ - **Survey phase:** Target questions with empty `iterations_touched` arrays first.
47
+ If all questions have been touched, target the lowest-confidence non-answered question.
48
+ - **Investigate / Synthesize / Verify phases:** Target the lowest-confidence
49
+ non-answered question.
50
+
51
+ If all questions are "answered", proceed to Step 5.
52
+
53
+ ### Step 3: Research
54
+
55
+ **Before writing ANY finding:** READ existing findings for your target question
56
+ in synthesis.md. Know what has already been discovered.
57
+
58
+ **Your new findings MUST contain information NOT already in synthesis.md.** If you
59
+ cannot find new information beyond what exists, write "No new findings beyond
60
+ existing research" and target the next-lowest-confidence question instead.
61
+
62
+ Acceptable new information includes:
63
+ - Specific details not yet captured (numbers, dates, names)
64
+ - Concrete examples or case studies
65
+ - Source citations (URLs, documentation references, code paths)
66
+ - Edge cases and limitations
67
+ - Contradictions with existing findings
68
+
69
+ Use available tools:
70
+ - **Codebase:** Glob, Grep, Read for local files and source code
71
+ - **Web:** WebSearch, WebFetch for external sources and documentation
72
+
73
+ **Source Tracking (MANDATORY):**
74
+ For every new finding, you MUST record:
75
+ - The source URL (or file path for codebase research)
76
+ - The source title/description
77
+ - The date you accessed it
78
+
79
+ Register sources in plan.json under the `sources` object using sequential IDs
80
+ (S1, S2, S3...). Reuse existing source IDs if citing the same URL again.
81
+
82
+ Source types: "documentation", "blog", "github", "academic", "codebase", "forum", "official"
83
+
84
+ For codebase research, use file paths as URLs with type "codebase":
85
+ ```json
86
+ "url": "src/components/Button.tsx",
87
+ "title": "Button component source",
88
+ "type": "codebase"
89
+ ```
90
+
91
+ ### Step 4: Update State Files
92
+
93
+ After researching, update these files:
94
+
95
+ **plan.json:** Update the target question:
96
+ - Set `status` to "partial" (useful info but gaps remain) or "answered" (thoroughly addressed)
97
+ - Update `confidence` (0-100) based on evidence quality -- see Confidence Scoring Rubric below
98
+ - Add findings as OBJECTS (not strings): `{"text": "finding text", "source_ids": ["S1", "S2"], "iteration": <current>}`
99
+ - Every finding MUST have at least one source_id
100
+ - Add new sources to the top-level `sources` registry
101
+ - Reuse existing source IDs for the same URL
102
+ - Add current iteration number to `iterations_touched` array
103
+ - If a question is IRRELEVANT to the topic, REMOVE it from the questions array entirely
104
+ - Do NOT add new questions -- work through the original plan
105
+ - Write the COMPLETE updated plan.json (not a partial update)
106
+
107
+ **gaps.md:** Rewrite with current state:
108
+ - List remaining open questions with confidence levels under "## Open Questions"
109
+ - Note any contradictions discovered under "## Contradictions"
110
+ - Update "## Last Updated" with current iteration number and timestamp
111
+
112
+ **synthesis.md:** Update findings for the question you worked on:
113
+ - Keep the "## Findings by Question" structure
114
+ - Add new findings under the relevant question heading
115
+ - Include question status and confidence in the heading
116
+ - Do NOT duplicate existing findings -- add only new information
117
+ - Do not remove findings from other questions
118
+
119
+ **state.json:** Update:
120
+ - `last_updated` to current ISO-8601 UTC timestamp
121
+ - `overall_confidence` to the average of all remaining questions' confidence values
122
+ - Do NOT change `iteration` or `phase` (oracle.sh manages these)
123
+
124
+ ### Step 5: Assess and Complete
125
+
126
+ State your assessment: "Confidence: X% -- {brief reason}"
127
+
128
+ If `overall_confidence` >= `target_confidence` (from state.json) OR all remaining
129
+ questions are "answered": output `<oracle>COMPLETE</oracle>`
130
+
131
+ Otherwise, end normally for another iteration.
132
+
133
+ ## Confidence Scoring Rubric
134
+
135
+ Use this rubric when scoring question confidence. Anchor scores to evidence quality.
136
+
137
+ | Score | Level | Criteria |
138
+ |-------|-------|----------|
139
+ | 0-20% | Unexplored | No research conducted on this question |
140
+ | 20-40% | Surface level | General information only, no specific details or sources |
141
+ | 40-60% | Partial understanding | Specific details from 1-2 sources, some gaps remain |
142
+ | 60-80% | Good understanding | Multiple sources agree, edge cases identified and documented |
143
+ | 80-95% | Thorough | Primary sources verified, contradictions resolved, limitations known |
144
+ | 95-100% | Exhaustive | All reasonable angles explored, high-quality sources confirmed |
145
+
146
+ **Do NOT inflate confidence.** One blog post = 30%, not 70%. A single source
147
+ without corroboration caps at 50% regardless of detail level.
148
+
149
+ **Do NOT deflate confidence to keep research going.** Score honestly based on
150
+ the evidence you have. If the question is well-answered, say so.
151
+
152
+ **Source-backed confidence rules:**
153
+ - 0 sources: Finding is UNSUPPORTED -- do not record it
154
+ - 1 source: Single-source claim, capped at 50% contribution to question confidence
155
+ - 2+ sources: Multi-source claim, full confidence contribution
156
+ - The overall question confidence should reflect the source backing of its findings
157
+
158
+ ## Important Rules
159
+
160
+ - Target ONE question per iteration
161
+ - Write COMPLETE JSON files, not partial updates (prevents corruption)
162
+ - Do NOT add new sub-questions -- work through the original plan
163
+ - Remove irrelevant questions entirely -- do not mark them as "skipped"
164
+ - Reference existing findings BEFORE writing new ones -- no restatements
165
+ - Do NOT modify any code files or colony state
166
+ - Only write to `.aether/oracle/` directory
167
+ - If this iteration is labeled "SYNTHESIS PASS" in the directive above, follow those instructions instead of the normal research flow -- consolidate and organize existing findings rather than researching new information
168
+ - In synthesis passes, use inline citations [S1], [S2] linking findings to sources. Include a ## Sources section listing all sources with IDs, URLs, titles, and access dates.