aether-colony 3.1.17 → 5.1.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 (378) hide show
  1. package/.aether/aether-utils.sh +5354 -0
  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 +438 -0
  30. package/.aether/commands/continue.yaml +1484 -0
  31. package/.aether/commands/council.yaml +304 -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 +469 -0
  44. package/.aether/commands/insert-phase.yaml +98 -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 +1313 -0
  57. package/.aether/commands/preferences.yaml +63 -0
  58. package/.aether/commands/redirect.yaml +123 -0
  59. package/.aether/commands/resume-colony.yaml +373 -0
  60. package/.aether/commands/resume.yaml +398 -0
  61. package/.aether/commands/run.yaml +193 -0
  62. package/.aether/commands/seal.yaml +1205 -0
  63. package/.aether/commands/skill-create.yaml +337 -0
  64. package/.aether/commands/status.yaml +364 -0
  65. package/.aether/commands/swarm.yaml +352 -0
  66. package/.aether/commands/tunnels.yaml +814 -0
  67. package/.aether/commands/update.yaml +131 -0
  68. package/.aether/commands/verify-castes.yaml +159 -0
  69. package/.aether/commands/watch.yaml +454 -0
  70. package/.aether/docs/INCIDENT_TEMPLATE.md +32 -0
  71. package/.aether/docs/QUEEN-SYSTEM.md +211 -0
  72. package/.aether/docs/README.md +98 -0
  73. package/.aether/docs/caste-system.md +48 -0
  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 +1682 -0
  78. package/.aether/docs/command-playbooks/build-prep.md +283 -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 +1724 -0
  84. package/.aether/docs/command-playbooks/continue-gates.md +686 -0
  85. package/.aether/docs/command-playbooks/continue-verify.md +406 -0
  86. package/.aether/docs/context-continuity.md +84 -0
  87. package/{runtime → .aether/docs/disciplines}/DISCIPLINES.md +13 -11
  88. package/.aether/docs/error-codes.md +268 -0
  89. package/.aether/docs/known-issues.md +94 -0
  90. package/{runtime → .aether}/docs/pheromones.md +86 -6
  91. package/.aether/docs/plans/pheromone-display-plan.md +257 -0
  92. package/.aether/docs/queen-commands.md +98 -0
  93. package/.aether/docs/source-of-truth-map.md +132 -0
  94. package/.aether/docs/xml-utilities.md +47 -0
  95. package/{runtime → .aether}/exchange/pheromone-xml.sh +2 -1
  96. package/{runtime → .aether}/exchange/registry-xml.sh +7 -3
  97. package/{runtime → .aether}/exchange/wisdom-xml.sh +11 -4
  98. package/.aether/rules/aether-colony.md +144 -0
  99. package/.aether/schemas/example-prompt-builder.xml +234 -0
  100. package/.aether/scripts/incident-test-add.sh +47 -0
  101. package/.aether/scripts/weekly-audit.sh +79 -0
  102. package/.aether/skills/.index.json +649 -0
  103. package/.aether/skills/colony/.manifest.json +16 -0
  104. package/.aether/skills/colony/build-discipline/SKILL.md +78 -0
  105. package/.aether/skills/colony/colony-interaction/SKILL.md +56 -0
  106. package/.aether/skills/colony/colony-lifecycle/SKILL.md +77 -0
  107. package/.aether/skills/colony/colony-visuals/SKILL.md +112 -0
  108. package/.aether/skills/colony/context-management/SKILL.md +80 -0
  109. package/.aether/skills/colony/error-presentation/SKILL.md +99 -0
  110. package/.aether/skills/colony/pheromone-protocol/SKILL.md +79 -0
  111. package/.aether/skills/colony/pheromone-visibility/SKILL.md +81 -0
  112. package/.aether/skills/colony/state-safety/SKILL.md +84 -0
  113. package/.aether/skills/colony/worker-priming/SKILL.md +82 -0
  114. package/.aether/skills/domain/.manifest.json +24 -0
  115. package/.aether/skills/domain/README.md +33 -0
  116. package/.aether/skills/domain/django/SKILL.md +49 -0
  117. package/.aether/skills/domain/docker/SKILL.md +52 -0
  118. package/.aether/skills/domain/golang/SKILL.md +52 -0
  119. package/.aether/skills/domain/graphql/SKILL.md +51 -0
  120. package/.aether/skills/domain/html-css/SKILL.md +48 -0
  121. package/.aether/skills/domain/nextjs/SKILL.md +45 -0
  122. package/.aether/skills/domain/nodejs/SKILL.md +53 -0
  123. package/.aether/skills/domain/postgresql/SKILL.md +53 -0
  124. package/.aether/skills/domain/prisma/SKILL.md +59 -0
  125. package/.aether/skills/domain/python/SKILL.md +50 -0
  126. package/.aether/skills/domain/rails/SKILL.md +52 -0
  127. package/.aether/skills/domain/react/SKILL.md +45 -0
  128. package/.aether/skills/domain/rest-api/SKILL.md +58 -0
  129. package/.aether/skills/domain/svelte/SKILL.md +47 -0
  130. package/.aether/skills/domain/tailwind/SKILL.md +45 -0
  131. package/.aether/skills/domain/testing/SKILL.md +53 -0
  132. package/.aether/skills/domain/typescript/SKILL.md +58 -0
  133. package/.aether/skills/domain/vue/SKILL.md +49 -0
  134. package/.aether/templates/QUEEN.md.template +61 -0
  135. package/.aether/templates/colony-state-reset.jq.template +23 -0
  136. package/.aether/templates/colony-state.template.json +39 -0
  137. package/.aether/templates/constraints.template.json +9 -0
  138. package/.aether/templates/crowned-anthill.template.md +36 -0
  139. package/.aether/templates/handoff-build-error.template.md +30 -0
  140. package/.aether/templates/handoff-build-success.template.md +39 -0
  141. package/.aether/templates/handoff.template.md +40 -0
  142. package/.aether/templates/learning-observations.template.json +6 -0
  143. package/.aether/templates/midden.template.json +13 -0
  144. package/.aether/templates/pheromones.template.json +6 -0
  145. package/.aether/templates/session.template.json +9 -0
  146. package/{runtime → .aether}/utils/atomic-write.sh +68 -22
  147. package/{runtime → .aether}/utils/chamber-compare.sh +23 -10
  148. package/.aether/utils/chamber-utils.sh +440 -0
  149. package/.aether/utils/emoji-audit.sh +166 -0
  150. package/{runtime → .aether}/utils/error-handler.sh +34 -8
  151. package/.aether/utils/file-lock.sh +313 -0
  152. package/.aether/utils/flag.sh +267 -0
  153. package/.aether/utils/hive.sh +572 -0
  154. package/.aether/utils/learning.sh +1928 -0
  155. package/.aether/utils/midden.sh +342 -0
  156. package/.aether/utils/oracle/oracle.md +168 -0
  157. package/.aether/utils/oracle/oracle.sh +1023 -0
  158. package/.aether/utils/pheromone.sh +2029 -0
  159. package/.aether/utils/queen.sh +1698 -0
  160. package/.aether/utils/scan.sh +860 -0
  161. package/.aether/utils/semantic-cli.sh +415 -0
  162. package/.aether/utils/session.sh +552 -0
  163. package/.aether/utils/skills.sh +509 -0
  164. package/.aether/utils/spawn-tree.sh +260 -0
  165. package/.aether/utils/spawn.sh +260 -0
  166. package/.aether/utils/state-api.sh +199 -0
  167. package/{runtime → .aether}/utils/state-loader.sh +8 -6
  168. package/.aether/utils/suggest.sh +611 -0
  169. package/{runtime → .aether}/utils/swarm-display.sh +10 -1
  170. package/.aether/utils/swarm.sh +1004 -0
  171. package/{runtime → .aether}/utils/watch-spawn-tree.sh +11 -2
  172. package/{runtime → .aether}/utils/xml-compose.sh +9 -3
  173. package/.aether/utils/xml-convert.sh +277 -0
  174. package/{runtime → .aether}/utils/xml-core.sh +5 -9
  175. package/.aether/utils/xml-query.sh +201 -0
  176. package/.aether/utils/xml-utils.sh +110 -0
  177. package/{runtime → .aether}/workers.md +97 -81
  178. package/.claude/agents/ant/aether-ambassador.md +265 -0
  179. package/.claude/agents/ant/aether-archaeologist.md +327 -0
  180. package/.claude/agents/ant/aether-architect.md +236 -0
  181. package/.claude/agents/ant/aether-auditor.md +271 -0
  182. package/.claude/agents/ant/aether-builder.md +224 -0
  183. package/.claude/agents/ant/aether-chaos.md +269 -0
  184. package/.claude/agents/ant/aether-chronicler.md +305 -0
  185. package/.claude/agents/ant/aether-gatekeeper.md +330 -0
  186. package/.claude/agents/ant/aether-includer.md +374 -0
  187. package/.claude/agents/ant/aether-keeper.md +272 -0
  188. package/.claude/agents/ant/aether-measurer.md +322 -0
  189. package/.claude/agents/ant/aether-oracle.md +237 -0
  190. package/.claude/agents/ant/aether-probe.md +211 -0
  191. package/.claude/agents/ant/aether-queen.md +330 -0
  192. package/.claude/agents/ant/aether-route-setter.md +178 -0
  193. package/.claude/agents/ant/aether-sage.md +418 -0
  194. package/.claude/agents/ant/aether-scout.md +179 -0
  195. package/.claude/agents/ant/aether-surveyor-disciplines.md +417 -0
  196. package/.claude/agents/ant/aether-surveyor-nest.md +355 -0
  197. package/.claude/agents/ant/aether-surveyor-pathogens.md +289 -0
  198. package/.claude/agents/ant/aether-surveyor-provisions.md +360 -0
  199. package/.claude/agents/ant/aether-tracker.md +270 -0
  200. package/.claude/agents/ant/aether-watcher.md +280 -0
  201. package/.claude/agents/ant/aether-weaver.md +248 -0
  202. package/.claude/commands/ant/archaeology.md +16 -14
  203. package/.claude/commands/ant/build.md +43 -1028
  204. package/.claude/commands/ant/chaos.md +19 -23
  205. package/.claude/commands/ant/colonize.md +52 -31
  206. package/.claude/commands/ant/continue.md +40 -1016
  207. package/.claude/commands/ant/council.md +21 -18
  208. package/.claude/commands/ant/data-clean.md +81 -0
  209. package/.claude/commands/ant/dream.md +27 -15
  210. package/.claude/commands/ant/entomb.md +317 -225
  211. package/.claude/commands/ant/export-signals.md +57 -0
  212. package/.claude/commands/ant/feedback.md +48 -26
  213. package/.claude/commands/ant/flag.md +30 -10
  214. package/.claude/commands/ant/flags.md +34 -12
  215. package/.claude/commands/ant/focus.md +45 -19
  216. package/.claude/commands/ant/help.md +50 -8
  217. package/.claude/commands/ant/history.md +13 -0
  218. package/.claude/commands/ant/import-signals.md +71 -0
  219. package/.claude/commands/ant/init.md +345 -194
  220. package/.claude/commands/ant/insert-phase.md +101 -0
  221. package/.claude/commands/ant/interpret.md +26 -4
  222. package/.claude/commands/ant/lay-eggs.md +184 -127
  223. package/.claude/commands/ant/maturity.md +32 -11
  224. package/.claude/commands/ant/memory-details.md +77 -0
  225. package/.claude/commands/ant/migrate-state.md +20 -2
  226. package/.claude/commands/ant/oracle.md +337 -74
  227. package/.claude/commands/ant/organize.md +39 -25
  228. package/.claude/commands/ant/patrol.md +620 -0
  229. package/.claude/commands/ant/pause-colony.md +23 -27
  230. package/.claude/commands/ant/phase.md +40 -42
  231. package/.claude/commands/ant/pheromones.md +156 -0
  232. package/.claude/commands/ant/plan.md +185 -51
  233. package/.claude/commands/ant/preferences.md +65 -0
  234. package/.claude/commands/ant/redirect.md +45 -30
  235. package/.claude/commands/ant/resume-colony.md +51 -27
  236. package/.claude/commands/ant/resume.md +314 -94
  237. package/.claude/commands/ant/run.md +195 -0
  238. package/.claude/commands/ant/seal.md +650 -221
  239. package/.claude/commands/ant/skill-create.md +286 -0
  240. package/.claude/commands/ant/status.md +196 -31
  241. package/.claude/commands/ant/swarm.md +16 -46
  242. package/.claude/commands/ant/tunnels.md +280 -105
  243. package/.claude/commands/ant/update.md +73 -89
  244. package/.claude/commands/ant/verify-castes.md +100 -42
  245. package/.claude/commands/ant/watch.md +14 -12
  246. package/.opencode/agents/aether-ambassador.md +63 -20
  247. package/.opencode/agents/aether-archaeologist.md +29 -12
  248. package/.opencode/agents/aether-architect.md +103 -36
  249. package/.opencode/agents/aether-auditor.md +51 -18
  250. package/.opencode/agents/aether-builder.md +70 -20
  251. package/.opencode/agents/aether-chaos.md +29 -12
  252. package/.opencode/agents/aether-chronicler.md +60 -18
  253. package/.opencode/agents/aether-gatekeeper.md +27 -18
  254. package/.opencode/agents/aether-includer.md +27 -18
  255. package/.opencode/agents/aether-keeper.md +89 -18
  256. package/.opencode/agents/aether-measurer.md +27 -18
  257. package/.opencode/agents/aether-oracle.md +137 -0
  258. package/.opencode/agents/aether-probe.md +60 -18
  259. package/.opencode/agents/aether-queen.md +172 -24
  260. package/.opencode/agents/aether-route-setter.md +57 -12
  261. package/.opencode/agents/aether-sage.md +26 -18
  262. package/.opencode/agents/aether-scout.md +28 -20
  263. package/.opencode/agents/aether-surveyor-disciplines.md +59 -2
  264. package/.opencode/agents/aether-surveyor-nest.md +59 -2
  265. package/.opencode/agents/aether-surveyor-pathogens.md +57 -2
  266. package/.opencode/agents/aether-surveyor-provisions.md +59 -2
  267. package/.opencode/agents/aether-tracker.md +64 -18
  268. package/.opencode/agents/aether-watcher.md +66 -19
  269. package/.opencode/agents/aether-weaver.md +61 -18
  270. package/.opencode/commands/ant/archaeology.md +7 -14
  271. package/.opencode/commands/ant/build.md +437 -257
  272. package/.opencode/commands/ant/chaos.md +7 -24
  273. package/.opencode/commands/ant/colonize.md +8 -17
  274. package/.opencode/commands/ant/continue.md +661 -142
  275. package/.opencode/commands/ant/council.md +11 -22
  276. package/.opencode/commands/ant/data-clean.md +77 -0
  277. package/.opencode/commands/ant/dream.md +15 -17
  278. package/.opencode/commands/ant/entomb.md +133 -62
  279. package/.opencode/commands/ant/export-signals.md +54 -0
  280. package/.opencode/commands/ant/feedback.md +24 -5
  281. package/.opencode/commands/ant/flag.md +16 -4
  282. package/.opencode/commands/ant/flags.md +24 -10
  283. package/.opencode/commands/ant/focus.md +22 -5
  284. package/.opencode/commands/ant/help.md +41 -8
  285. package/.opencode/commands/ant/history.md +9 -0
  286. package/.opencode/commands/ant/import-signals.md +68 -0
  287. package/.opencode/commands/ant/init.md +374 -167
  288. package/.opencode/commands/ant/insert-phase.md +107 -0
  289. package/.opencode/commands/ant/interpret.md +16 -0
  290. package/.opencode/commands/ant/lay-eggs.md +184 -112
  291. package/.opencode/commands/ant/maturity.md +18 -2
  292. package/.opencode/commands/ant/memory-details.md +83 -0
  293. package/.opencode/commands/ant/migrate-state.md +12 -0
  294. package/.opencode/commands/ant/oracle.md +322 -67
  295. package/.opencode/commands/ant/organize.md +18 -16
  296. package/.opencode/commands/ant/patrol.md +626 -0
  297. package/.opencode/commands/ant/pause-colony.md +12 -29
  298. package/.opencode/commands/ant/phase.md +30 -40
  299. package/.opencode/commands/ant/pheromones.md +162 -0
  300. package/.opencode/commands/ant/plan.md +184 -56
  301. package/.opencode/commands/ant/preferences.md +71 -0
  302. package/.opencode/commands/ant/redirect.md +22 -5
  303. package/.opencode/commands/ant/resume-colony.md +38 -27
  304. package/.opencode/commands/ant/resume.md +385 -0
  305. package/.opencode/commands/ant/run.md +201 -0
  306. package/.opencode/commands/ant/seal.md +259 -45
  307. package/.opencode/commands/ant/skill-create.md +63 -0
  308. package/.opencode/commands/ant/status.md +135 -31
  309. package/.opencode/commands/ant/swarm.md +3 -345
  310. package/.opencode/commands/ant/tunnels.md +152 -9
  311. package/.opencode/commands/ant/update.md +70 -91
  312. package/.opencode/commands/ant/verify-castes.md +96 -42
  313. package/.opencode/commands/ant/watch.md +7 -0
  314. package/CHANGELOG.md +356 -0
  315. package/README.md +203 -573
  316. package/bin/cli.js +455 -527
  317. package/bin/generate-commands.js +186 -0
  318. package/bin/generate-commands.sh +127 -88
  319. package/bin/lib/init.js +13 -3
  320. package/bin/lib/spawn-logger.js +0 -15
  321. package/bin/lib/update-transaction.js +392 -140
  322. package/bin/npx-install.js +178 -0
  323. package/bin/sync-to-runtime.sh +5 -137
  324. package/bin/validate-package.sh +166 -0
  325. package/package.json +14 -7
  326. package/.opencode/agents/aether-guardian.md +0 -107
  327. package/.opencode/agents/workers.md +0 -1034
  328. package/bin/lib/model-profiles.js +0 -445
  329. package/bin/lib/model-verify.js +0 -288
  330. package/bin/lib/proxy-health.js +0 -253
  331. package/bin/lib/telemetry.js +0 -441
  332. package/runtime/CONTEXT.md +0 -160
  333. package/runtime/QUEEN_ANT_ARCHITECTURE.md +0 -402
  334. package/runtime/aether-utils.sh +0 -3879
  335. package/runtime/data/signatures.json +0 -41
  336. package/runtime/docs/AETHER-2.0-IMPLEMENTATION-PLAN.md +0 -1343
  337. package/runtime/docs/AETHER-PHEROMONE-SYSTEM-MASTER-SPEC.md +0 -2642
  338. package/runtime/docs/PHEROMONE-INJECTION.md +0 -240
  339. package/runtime/docs/PHEROMONE-INTEGRATION.md +0 -192
  340. package/runtime/docs/PHEROMONE-SYSTEM-DESIGN.md +0 -426
  341. package/runtime/docs/README.md +0 -94
  342. package/runtime/docs/VISUAL-OUTPUT-SPEC.md +0 -219
  343. package/runtime/docs/biological-reference.md +0 -272
  344. package/runtime/docs/codebase-review.md +0 -399
  345. package/runtime/docs/command-sync.md +0 -164
  346. package/runtime/docs/constraints.md +0 -116
  347. package/runtime/docs/implementation-learnings.md +0 -89
  348. package/runtime/docs/known-issues.md +0 -217
  349. package/runtime/docs/namespace.md +0 -148
  350. package/runtime/docs/pathogen-schema-example.json +0 -36
  351. package/runtime/docs/pathogen-schema.md +0 -111
  352. package/runtime/docs/planning-discipline.md +0 -159
  353. package/runtime/docs/progressive-disclosure.md +0 -184
  354. package/runtime/lib/queen-utils.sh +0 -729
  355. package/runtime/model-profiles.yaml +0 -100
  356. package/runtime/planning.md +0 -159
  357. package/runtime/recover.sh +0 -136
  358. package/runtime/templates/QUEEN.md.template +0 -79
  359. package/runtime/utils/chamber-utils.sh +0 -285
  360. package/runtime/utils/file-lock.sh +0 -122
  361. package/runtime/utils/spawn-tree.sh +0 -428
  362. package/runtime/utils/spawn-with-model.sh +0 -56
  363. package/runtime/utils/xml-utils.sh +0 -2196
  364. package/runtime/workers-new-castes.md +0 -516
  365. /package/{runtime → .aether/docs/disciplines}/coding-standards.md +0 -0
  366. /package/{runtime → .aether/docs/disciplines}/debugging.md +0 -0
  367. /package/{runtime → .aether/docs/disciplines}/learning.md +0 -0
  368. /package/{runtime → .aether/docs/disciplines}/tdd.md +0 -0
  369. /package/{runtime → .aether/docs/disciplines}/verification-loop.md +0 -0
  370. /package/{runtime → .aether/docs/disciplines}/verification.md +0 -0
  371. /package/{runtime → .aether}/schemas/aether-types.xsd +0 -0
  372. /package/{runtime → .aether}/schemas/colony-registry.xsd +0 -0
  373. /package/{runtime → .aether}/schemas/pheromone.xsd +0 -0
  374. /package/{runtime → .aether}/schemas/prompt.xsd +0 -0
  375. /package/{runtime → .aether}/schemas/queen-wisdom.xsd +0 -0
  376. /package/{runtime → .aether}/schemas/worker-priming.xsd +0 -0
  377. /package/{runtime → .aether}/utils/colorize-log.sh +0 -0
  378. /package/{runtime → .aether}/utils/queen-to-md.xsl +0 -0
@@ -3,8 +3,17 @@
3
3
  # Usage: bash watch-spawn-tree.sh [data_dir]
4
4
 
5
5
  DATA_DIR="${1:-.aether/data}"
6
- SPAWN_FILE="$DATA_DIR/spawn-tree.txt"
7
- VIEW_STATE_FILE="$DATA_DIR/view-state.json"
6
+ # Resolve COLONY_DATA_DIR for per-colony files (standalone script)
7
+ COLONY_DATA_DIR="${COLONY_DATA_DIR:-$DATA_DIR}"
8
+ if [[ -f "$DATA_DIR/COLONY_STATE.json" ]]; then
9
+ _cn=$(jq -r '.colony_name // empty' "$DATA_DIR/COLONY_STATE.json" 2>/dev/null)
10
+ if [[ -n "$_cn" ]]; then
11
+ _cn_safe=$(echo "$_cn" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//')
12
+ [[ -n "$_cn_safe" ]] && COLONY_DATA_DIR="$DATA_DIR/colonies/$_cn_safe"
13
+ fi
14
+ fi
15
+ SPAWN_FILE="$COLONY_DATA_DIR/spawn-tree.txt"
16
+ VIEW_STATE_FILE="$COLONY_DATA_DIR/view-state.json"
8
17
 
9
18
  # ANSI colors
10
19
  YELLOW='\033[33m'
@@ -5,14 +5,20 @@
5
5
  # Usage: source .aether/utils/xml-compose.sh
6
6
  # xml-compose <input_xml> [output_xml]
7
7
  # xml-compose-worker-priming <priming_xml> [output_xml]
8
+ # xml-list-includes <xml_file>
8
9
  #
9
10
  # These functions enable declarative composition of worker configurations
10
11
  # using XInclude directives to merge queen-wisdom, active-trails, and stack-profiles.
11
12
 
12
13
  set -euo pipefail
13
14
 
14
- # Note: This file should be sourced AFTER xml-utils.sh
15
+ # Note: This file should be sourced AFTER xml-utils.sh or xml-core.sh
15
16
  # It relies on xml_json_ok, xml_json_err, and XMLLINT_AVAILABLE variables
17
+ # Source xml-core.sh for JSON helpers and tool detection if not already loaded
18
+ if ! type xml_json_ok &>/dev/null; then
19
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
20
+ source "$SCRIPT_DIR/xml-core.sh"
21
+ fi
16
22
 
17
23
  # ============================================================================
18
24
  # Path Validation (Security)
@@ -107,12 +113,12 @@ xml-compose() {
107
113
  echo "$composed" > "$output_xml"
108
114
  local escaped_output
109
115
  escaped_output=$(echo "$output_xml" | jq -Rs '.[:-1]')
110
- xml_json_ok "{\"composed\":true,\"output\":$escaped_output,\"sources_resolved\":\"auto\"}"
116
+ xml_json_ok "$(jq -n --argjson output "$escaped_output" '{composed: true, output: $output, sources_resolved: "auto"}')"
111
117
  else
112
118
  # Output to stdout wrapped in JSON
113
119
  local escaped_composed
114
120
  escaped_composed=$(echo "$composed" | jq -Rs '.')
115
- xml_json_ok "{\"composed\":true,\"xml\":$escaped_composed,\"sources_resolved\":\"auto\"}"
121
+ xml_json_ok "$(jq -n --argjson xml "$escaped_composed" '{composed: true, xml: $xml, sources_resolved: "auto"}')"
116
122
  fi
117
123
  return 0
118
124
  fi
@@ -0,0 +1,277 @@
1
+ #!/bin/bash
2
+ # XML Conversion Utilities
3
+ # Bidirectional JSON/XML conversion and document merging
4
+ #
5
+ # Usage: source .aether/utils/xml-convert.sh
6
+ # xml-to-json <xml_file> [--pretty]
7
+ # json-to-xml <json_file> [root_element]
8
+ # xml-merge <output_file> <main_xml_file>
9
+ # xml-convert-detect-format <file>
10
+
11
+ set -euo pipefail
12
+
13
+ # Source xml-core.sh for JSON helpers and tool detection
14
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
15
+ source "$SCRIPT_DIR/xml-core.sh"
16
+
17
+ # Additional tool detection for conversion
18
+ XML2JSON_AVAILABLE=false
19
+ if command -v xml2json >/dev/null 2>&1; then
20
+ XML2JSON_AVAILABLE=true
21
+ fi
22
+
23
+ # ============================================================================
24
+ # Format Detection
25
+ # ============================================================================
26
+
27
+ # xml-convert-detect-format: Detect if file is XML or JSON
28
+ # Usage: xml-convert-detect-format <file>
29
+ # Returns: {"ok":true,"result":{"format":"xml|json|unknown","confidence":"high|medium|low"}}
30
+ xml-convert-detect-format() {
31
+ local file="${1:-}"
32
+
33
+ [[ -z "$file" ]] && { xml_json_err "MISSING_ARG" "Missing file argument"; return 1; }
34
+ [[ -f "$file" ]] || { xml_json_err "FILE_NOT_FOUND" "File not found: $file"; return 1; }
35
+
36
+ # Read first 1KB for analysis
37
+ local header
38
+ header=$(head -c 1024 "$file" 2>/dev/null || head -c 1024 < "$file")
39
+
40
+ # Check for XML signatures
41
+ if echo "$header" | grep -qE '^\s*<\?xml\s+version'; then
42
+ xml_json_ok '{"format":"xml","confidence":"high","signature":"xml_declaration"}'
43
+ return 0
44
+ fi
45
+
46
+ if echo "$header" | grep -qE '^\s*<[a-zA-Z_][a-zA-Z0-9_]*[\s>]'; then
47
+ xml_json_ok '{"format":"xml","confidence":"medium","signature":"root_element"}'
48
+ return 0
49
+ fi
50
+
51
+ # Check for JSON signatures
52
+ if echo "$header" | grep -qE '^\s*(\{|\[)'; then
53
+ # Verify it's valid JSON
54
+ if jq empty "$file" 2>/dev/null; then
55
+ xml_json_ok '{"format":"json","confidence":"high","signature":"valid_json"}'
56
+ return 0
57
+ else
58
+ xml_json_ok '{"format":"json","confidence":"low","signature":"json_like","note":"Invalid JSON syntax"}'
59
+ return 0
60
+ fi
61
+ fi
62
+
63
+ xml_json_ok '{"format":"unknown","confidence":"low","signature":"none"}'
64
+ }
65
+
66
+ # ============================================================================
67
+ # XML to JSON Conversion
68
+ # ============================================================================
69
+
70
+ # xml-to-json: Convert XML to JSON format
71
+ # Usage: xml-to-json <xml_file> [--pretty]
72
+ # Returns: {"ok":true,"result":{"json":"...","format":"object"}}
73
+ xml-to-json() {
74
+ local xml_file="${1:-}"
75
+ local pretty=false
76
+
77
+ # Parse optional arguments
78
+ shift || true
79
+ while [[ $# -gt 0 ]]; do
80
+ case "$1" in
81
+ --pretty) pretty=true; shift ;;
82
+ *) shift ;;
83
+ esac
84
+ done
85
+
86
+ [[ -z "$xml_file" ]] && { xml_json_err "MISSING_ARG" "Missing XML file argument"; return 1; }
87
+ [[ -f "$xml_file" ]] || { xml_json_err "FILE_NOT_FOUND" "XML file not found: $xml_file"; return 1; }
88
+
89
+ # Check well-formedness first
90
+ local well_formed_result
91
+ well_formed_result=$(xml-well-formed "$xml_file" 2>/dev/null)
92
+ if ! echo "$well_formed_result" | jq -e '.result.well_formed' >/dev/null 2>&1; then
93
+ xml_json_err "PARSE_ERROR" "XML is not well-formed"
94
+ return 1
95
+ fi
96
+
97
+ # Try xml2json if available (npm package)
98
+ if [[ "$XML2JSON_AVAILABLE" == "true" ]]; then
99
+ local json_output
100
+ if json_output=$(xml2json "$xml_file" 2>/dev/null); then
101
+ if [[ "$pretty" == "true" ]]; then
102
+ json_output=$(echo "$json_output" | jq '.')
103
+ fi
104
+ local escaped_json
105
+ escaped_json=$(echo "$json_output" | jq -Rs '.')
106
+ xml_json_ok "$(jq -n --argjson json "$escaped_json" '{format: "object", json: $json}')"
107
+ return 0
108
+ fi
109
+ fi
110
+
111
+ # Fallback: Use xsltproc with built-in XSLT
112
+ if [[ "$XSLTPROC_AVAILABLE" == "true" ]]; then
113
+ local xslt_script
114
+ xslt_script=$(cat << 'XSLT'
115
+ <?xml version="1.0"?>
116
+ <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
117
+ <xsl:output method="text"/>
118
+ <xsl:template match="/">
119
+ <xsl:text>{"root":</xsl:text>
120
+ <xsl:apply-templates select="*"/>
121
+ <xsl:text>}</xsl:text>
122
+ </xsl:template>
123
+ <xsl:template match="*">
124
+ <xsl:text>{"</xsl:text>
125
+ <xsl:value-of select="name()"/>
126
+ <xsl:text>":</xsl:text>
127
+ <xsl:choose>
128
+ <xsl:when test="count(*) > 0">
129
+ <xsl:text>[</xsl:text>
130
+ <xsl:apply-templates select="*"/>
131
+ <xsl:text>]</xsl:text>
132
+ </xsl:when>
133
+ <xsl:otherwise>
134
+ <xsl:text>"</xsl:text>
135
+ <xsl:value-of select="."/>
136
+ <xsl:text>"</xsl:text>
137
+ </xsl:otherwise>
138
+ </xsl:choose>
139
+ <xsl:text>}</xsl:text>
140
+ <xsl:if test="position() != last()">,</xsl:if>
141
+ </xsl:template>
142
+ </xsl:stylesheet>
143
+ XSLT
144
+ )
145
+ local json_result
146
+ json_result=$(echo "$xslt_script" | xsltproc - "$xml_file" 2>/dev/null) || {
147
+ xml_json_err "CONVERSION_ERROR" "XSLT conversion failed"
148
+ return 1
149
+ }
150
+ local xslt_escaped_json
151
+ xslt_escaped_json=$(echo "$json_result" | jq -Rs '.')
152
+ xml_json_ok "$(jq -n --argjson json "$xslt_escaped_json" '{format: "object", json: $json}')"
153
+ return 0
154
+ fi
155
+
156
+ # Last resort: Use xmlstarlet if available
157
+ if [[ "$XMLSTARLET_AVAILABLE" == "true" ]]; then
158
+ local json_result
159
+ json_result=$(xmlstarlet sel -t -m "/" -o '{"root":{' -m "*" -v "name()" -o ':"' -v "." -o '"' -b -o '}}' "$xml_file" 2>/dev/null) || {
160
+ xml_json_err "CONVERSION_ERROR" "xmlstarlet conversion failed"
161
+ return 1
162
+ }
163
+ local xmlstar_escaped_json
164
+ xmlstar_escaped_json=$(echo "$json_result" | jq -Rs '.')
165
+ xml_json_ok "$(jq -n --argjson json "$xmlstar_escaped_json" '{format: "object", json: $json}')"
166
+ return 0
167
+ fi
168
+
169
+ xml_json_err "TOOL_NOT_AVAILABLE" "No XML to JSON conversion tool available. Install xml2json, xsltproc, or xmlstarlet."
170
+ return 1
171
+ }
172
+
173
+ # ============================================================================
174
+ # JSON to XML Conversion
175
+ # ============================================================================
176
+
177
+ # json-to-xml: Convert JSON to XML
178
+ # Usage: json-to-xml <json_file> [root_element]
179
+ # Returns: {"ok":true,"result":{"xml":"<root>...</root>"}}
180
+ json-to-xml() {
181
+ local json_file="${1:-}"
182
+ local root_element="${2:-root}"
183
+
184
+ [[ -z "$json_file" ]] && { xml_json_err "MISSING_ARG" "Missing JSON file argument"; return 1; }
185
+ [[ -f "$json_file" ]] || { xml_json_err "FILE_NOT_FOUND" "JSON file not found: $json_file"; return 1; }
186
+
187
+ # Validate JSON first
188
+ if ! jq empty "$json_file" 2>/dev/null; then
189
+ xml_json_err "PARSE_ERROR" "Invalid JSON file: $json_file"
190
+ return 1
191
+ fi
192
+
193
+ # Build XML using jq to generate structure
194
+ local xml_output
195
+ xml_output=$(jq -r --arg root "$root_element" '
196
+ def to_xml:
197
+ if type == "object" then
198
+ to_entries | map(
199
+ "<\(.key)>\(.value | to_xml)</\(.key)>"
200
+ ) | join("")
201
+ elif type == "array" then
202
+ map("<item>\(. | to_xml)</item>") | join("")
203
+ elif type == "string" then
204
+ .
205
+ elif type == "number" then
206
+ tostring
207
+ elif type == "boolean" then
208
+ tostring
209
+ elif type == "null" then
210
+ ""
211
+ else
212
+ tostring
213
+ end;
214
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<\($root)>\n" + (to_xml) + "\n</\($root)>"
215
+ ' "$json_file" 2>/dev/null) || {
216
+ xml_json_err "CONVERSION_ERROR" "JSON to XML conversion failed"
217
+ return 1
218
+ }
219
+
220
+ # Escape the XML for JSON output
221
+ local escaped_xml
222
+ escaped_xml=$(echo "$xml_output" | jq -Rs '.')
223
+ xml_json_ok "$(jq -n --argjson xml "$escaped_xml" '{xml: $xml}')"
224
+ }
225
+
226
+ # ============================================================================
227
+ # XML Document Merging
228
+ # ============================================================================
229
+
230
+ # xml-merge: XInclude document merging
231
+ # Usage: xml-merge <output_file> <main_xml_file>
232
+ # Returns: {"ok":true,"result":{"merged":true,"output":"<path>","sources_resolved":N}}
233
+ xml-merge() {
234
+ local output_file="${1:-}"
235
+ local main_xml="${2:-}"
236
+
237
+ [[ -z "$output_file" ]] && { xml_json_err "MISSING_ARG" "Missing output file argument"; return 1; }
238
+ [[ -z "$main_xml" ]] && { xml_json_err "MISSING_ARG" "Missing main XML file argument"; return 1; }
239
+ [[ -f "$main_xml" ]] || { xml_json_err "FILE_NOT_FOUND" "Main XML file not found: $main_xml"; return 1; }
240
+
241
+ # Check well-formedness of main file
242
+ local well_formed_result
243
+ well_formed_result=$(xml-well-formed "$main_xml" 2>/dev/null)
244
+ if ! echo "$well_formed_result" | jq -e '.result.well_formed' >/dev/null 2>&1; then
245
+ xml_json_err "PARSE_ERROR" "Main XML file is not well-formed"
246
+ return 1
247
+ fi
248
+
249
+ # Use xmllint for XInclude processing with security flags
250
+ if [[ "$XMLLINT_AVAILABLE" == "true" ]]; then
251
+ local merged
252
+ merged=$(xmllint --nonet --noent --xinclude "$main_xml" 2>/dev/null) || {
253
+ xml_json_err "MERGE_ERROR" "XInclude merge failed"
254
+ return 1
255
+ }
256
+
257
+ # Write output
258
+ echo "$merged" > "$output_file"
259
+
260
+ # Count resolved includes (approximate)
261
+ local resolved_count
262
+ resolved_count=$(echo "$merged" | grep -c '<xi:include' 2>/dev/null || echo "0")
263
+
264
+ local escaped_output
265
+ escaped_output=$(echo "$output_file" | jq -Rs '.[:-1]')
266
+ xml_json_ok "$(jq -n --argjson output "$escaped_output" --argjson sources_resolved "$resolved_count" '{merged: true, output: $output, sources_resolved: $sources_resolved}')"
267
+ return 0
268
+ fi
269
+
270
+ # Without xmllint, we cannot safely process XInclude
271
+ xml_json_err "TOOL_NOT_AVAILABLE" "xmllint required for XInclude merging. Install libxml2 utilities."
272
+ return 1
273
+ }
274
+
275
+ # Export functions
276
+ export -f xml-convert-detect-format xml-to-json json-to-xml xml-merge
277
+ export XML2JSON_AVAILABLE
@@ -89,10 +89,8 @@ xml-validate() {
89
89
  xml_json_ok '{"valid":true,"errors":[]}'
90
90
  return 0
91
91
  } || {
92
- # Escape errors for JSON
93
- local escaped_errors
94
- escaped_errors=$(echo "$errors" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\t/\\t/g' | tr '\n' ' ')
95
- xml_json_ok "{\"valid\":false,\"errors\":[\"$escaped_errors\"]}"
92
+ # Escape errors for JSON using jq
93
+ xml_json_ok "$(jq -n --arg errors "$errors" '{valid: false, errors: [$errors]}')"
96
94
  return 0
97
95
  }
98
96
  }
@@ -144,12 +142,10 @@ xml-format() {
144
142
 
145
143
  if [[ -n "$output_file" ]]; then
146
144
  echo "$formatted" > "$output_file"
147
- xml_json_ok "{\"formatted\":true,\"path\":\"$output_file\"}"
145
+ xml_json_ok "$(jq -n --arg path "$output_file" '{formatted: true, path: $path}')"
148
146
  else
149
- # Escape for JSON
150
- local escaped
151
- escaped=$(echo "$formatted" | sed 's/\\/\\\\/g; s/"/\\"/g' | tr '\n' ' ')
152
- xml_json_ok "{\"formatted\":true,\"output\":\"$escaped\"}"
147
+ # Escape for JSON using jq
148
+ xml_json_ok "$(jq -n --arg output "$formatted" '{formatted: true, output: $output}')"
153
149
  fi
154
150
  }
155
151
 
@@ -0,0 +1,201 @@
1
+ #!/bin/bash
2
+ # XML Query Utilities
3
+ # XPath queries with xmlstarlet and xmllint fallback
4
+ #
5
+ # Usage: source .aether/utils/xml-query.sh
6
+ # xml-query <xml_file> <xpath_expression>
7
+ # xml-query-attr <xml_file> <xpath_expression>
8
+ # xml-query-text <xml_file> <element_name>
9
+ # xml-query-count <xml_file> <xpath_expression>
10
+
11
+ set -euo pipefail
12
+
13
+ # Source xml-core.sh for JSON helpers and tool detection
14
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
15
+ source "$SCRIPT_DIR/xml-core.sh"
16
+
17
+ # ============================================================================
18
+ # XPath Query Functions
19
+ # ============================================================================
20
+
21
+ # xml-query: Execute XPath query against XML file
22
+ # Usage: xml-query <xml_file> <xpath_expression>
23
+ # Returns: {"ok":true,"result":{"matches":["value1","value2",...]}}
24
+ xml-query() {
25
+ local xml_file="${1:-}"
26
+ local xpath="${2:-}"
27
+
28
+ [[ -z "$xml_file" ]] && { xml_json_err "MISSING_ARG" "Missing XML file argument"; return 1; }
29
+ [[ -z "$xpath" ]] && { xml_json_err "MISSING_ARG" "Missing XPath expression"; return 1; }
30
+ [[ -f "$xml_file" ]] || { xml_json_err "FILE_NOT_FOUND" "XML file not found: $xml_file"; return 1; }
31
+
32
+ local results=""
33
+
34
+ # Prefer xmlstarlet for full XPath support
35
+ if [[ "$XMLSTARLET_AVAILABLE" == "true" ]]; then
36
+ results=$(xmlstarlet sel -t -v "$xpath" "$xml_file" 2>/dev/null | tr '\n' '|')
37
+ # Remove trailing pipe
38
+ results="${results%|}"
39
+ elif [[ "$XMLLINT_AVAILABLE" == "true" ]]; then
40
+ # xmllint has limited XPath but works for basic queries
41
+ # Note: xmllint --xpath returns the text content of matched nodes
42
+ results=$(xmllint --nonet --noent --xpath "$xpath" "$xml_file" 2>/dev/null | \
43
+ sed 's/<[^>]*>//g' | tr '\n' '|' | sed 's/|$//')
44
+ else
45
+ xml_json_err "TOOL_NOT_AVAILABLE" "No XPath-capable tool available (install xmlstarlet or libxml2)"
46
+ return 1
47
+ fi
48
+
49
+ # Build JSON array from pipe-separated results
50
+ if [[ -n "$results" ]]; then
51
+ local json_array="["
52
+ local first=true
53
+ IFS='|' read -ra matches <<< "$results"
54
+ for match in "${matches[@]}"; do
55
+ # Trim whitespace and escape for JSON
56
+ match=$(echo "$match" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
57
+ match=$(echo "$match" | sed 's/\\/\\\\/g; s/"/\\"/g')
58
+ if [[ "$first" == "true" ]]; then
59
+ first=false
60
+ json_array="$json_array\"$match\""
61
+ else
62
+ json_array="$json_array,\"$match\""
63
+ fi
64
+ done
65
+ json_array="$json_array]"
66
+ xml_json_ok "{\"matches\":$json_array}"
67
+ else
68
+ xml_json_ok '{"matches":[]}'
69
+ fi
70
+ }
71
+
72
+ # xml-query-attr: Extract attribute values using XPath
73
+ # Usage: xml-query-attr <xml_file> <element_xpath> <attribute_name>
74
+ # Returns: {"ok":true,"result":{"attribute":"name","values":["val1","val2"]}}
75
+ xml-query-attr() {
76
+ local xml_file="${1:-}"
77
+ local element_xpath="${2:-}"
78
+ local attr_name="${3:-}"
79
+
80
+ [[ -z "$xml_file" ]] && { xml_json_err "MISSING_ARG" "Missing XML file argument"; return 1; }
81
+ [[ -z "$element_xpath" ]] && { xml_json_err "MISSING_ARG" "Missing element XPath"; return 1; }
82
+ [[ -z "$attr_name" ]] && { xml_json_err "MISSING_ARG" "Missing attribute name"; return 1; }
83
+ [[ -f "$xml_file" ]] || { xml_json_err "FILE_NOT_FOUND" "XML file not found: $xml_file"; return 1; }
84
+
85
+ local full_xpath="${element_xpath}/@${attr_name}"
86
+ local results=""
87
+
88
+ if [[ "$XMLSTARLET_AVAILABLE" == "true" ]]; then
89
+ results=$(xmlstarlet sel -t -v "$full_xpath" "$xml_file" 2>/dev/null | tr '\n' '|')
90
+ results="${results%|}"
91
+ elif [[ "$XMLLINT_AVAILABLE" == "true" ]]; then
92
+ # xmllint can extract attributes with //@attrname syntax
93
+ results=$(xmllint --nonet --noent --xpath "$full_xpath" "$xml_file" 2>/dev/null | tr '\n' '|')
94
+ results="${results%|}"
95
+ else
96
+ xml_json_err "TOOL_NOT_AVAILABLE" "No XPath-capable tool available"
97
+ return 1
98
+ fi
99
+
100
+ # Build JSON array
101
+ if [[ -n "$results" ]]; then
102
+ local json_array="["
103
+ local first=true
104
+ IFS='|' read -ra values <<< "$results"
105
+ for val in "${values[@]}"; do
106
+ val=$(echo "$val" | sed 's/\\/\\\\/g; s/"/\\"/g')
107
+ if [[ "$first" == "true" ]]; then
108
+ first=false
109
+ json_array="$json_array\"$val\""
110
+ else
111
+ json_array="$json_array,\"$val\""
112
+ fi
113
+ done
114
+ json_array="$json_array]"
115
+ xml_json_ok "$(jq -n --arg attribute "$attr_name" --argjson values "$json_array" '{attribute: $attribute, values: $values}')"
116
+ else
117
+ xml_json_ok "$(jq -n --arg attribute "$attr_name" '{attribute: $attribute, values: []}')"
118
+ fi
119
+ }
120
+
121
+ # xml-query-text: Extract text content of elements
122
+ # Usage: xml-query-text <xml_file> <element_name>
123
+ # Returns: {"ok":true,"result":{"element":"name","text":["text1","text2"]}}
124
+ xml-query-text() {
125
+ local xml_file="${1:-}"
126
+ local element_name="${2:-}"
127
+
128
+ [[ -z "$xml_file" ]] && { xml_json_err "MISSING_ARG" "Missing XML file argument"; return 1; }
129
+ [[ -z "$element_name" ]] && { xml_json_err "MISSING_ARG" "Missing element name"; return 1; }
130
+ [[ -f "$xml_file" ]] || { xml_json_err "FILE_NOT_FOUND" "XML file not found: $xml_file"; return 1; }
131
+
132
+ local xpath="//$element_name"
133
+ local results=""
134
+
135
+ if [[ "$XMLSTARLET_AVAILABLE" == "true" ]]; then
136
+ # Use -m to match nodes and extract text
137
+ results=$(xmlstarlet sel -t -m "$xpath" -v "." -n "$xml_file" 2>/dev/null | tr '\n' '|')
138
+ results="${results%|}"
139
+ elif [[ "$XMLLINT_AVAILABLE" == "true" ]]; then
140
+ # xmllint --xpath returns text content directly for simple paths
141
+ results=$(xmllint --nonet --noent --xpath "$xpath" "$xml_file" 2>/dev/null | \
142
+ sed 's/<[^>]*>//g' | tr '\n' '|' | sed 's/|$//')
143
+ else
144
+ xml_json_err "TOOL_NOT_AVAILABLE" "No XPath-capable tool available"
145
+ return 1
146
+ fi
147
+
148
+ if [[ -n "$results" ]]; then
149
+ local json_array="["
150
+ local first=true
151
+ IFS='|' read -ra texts <<< "$results"
152
+ for text in "${texts[@]}"; do
153
+ text=$(echo "$text" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
154
+ text=$(echo "$text" | sed 's/\\/\\\\/g; s/"/\\"/g')
155
+ if [[ "$first" == "true" ]]; then
156
+ first=false
157
+ json_array="$json_array\"$text\""
158
+ else
159
+ json_array="$json_array,\"$text\""
160
+ fi
161
+ done
162
+ json_array="$json_array]"
163
+ xml_json_ok "$(jq -n --arg element "$element_name" --argjson text "$json_array" '{element: $element, text: $text}')"
164
+ else
165
+ xml_json_ok "$(jq -n --arg element "$element_name" '{element: $element, text: []}')"
166
+ fi
167
+ }
168
+
169
+ # xml-query-count: Count nodes matching XPath expression
170
+ # Usage: xml-query-count <xml_file> <xpath_expression>
171
+ # Returns: {"ok":true,"result":{"count":5}}
172
+ xml-query-count() {
173
+ local xml_file="${1:-}"
174
+ local xpath="${2:-}"
175
+
176
+ [[ -z "$xml_file" ]] && { xml_json_err "MISSING_ARG" "Missing XML file argument"; return 1; }
177
+ [[ -z "$xpath" ]] && { xml_json_err "MISSING_ARG" "Missing XPath expression"; return 1; }
178
+ [[ -f "$xml_file" ]] || { xml_json_err "FILE_NOT_FOUND" "XML file not found: $xml_file"; return 1; }
179
+
180
+ local count=0
181
+
182
+ if [[ "$XMLSTARLET_AVAILABLE" == "true" ]]; then
183
+ # Use count() XPath function
184
+ local count_result
185
+ count_result=$(xmlstarlet sel -t -v "count($xpath)" "$xml_file" 2>/dev/null)
186
+ count="${count_result:-0}"
187
+ elif [[ "$XMLLINT_AVAILABLE" == "true" ]]; then
188
+ # Count matching lines (approximate for simple cases)
189
+ local matches
190
+ matches=$(xmllint --nonet --noent --xpath "$xpath" "$xml_file" 2>/dev/null | grep -c '<' || true)
191
+ count="${matches:-0}"
192
+ else
193
+ xml_json_err "TOOL_NOT_AVAILABLE" "No XPath-capable tool available"
194
+ return 1
195
+ fi
196
+
197
+ xml_json_ok "{\"count\":$count}"
198
+ }
199
+
200
+ # Export functions
201
+ export -f xml-query xml-query-attr xml-query-text xml-query-count
@@ -0,0 +1,110 @@
1
+ #!/bin/bash
2
+ # XML Utilities Loader
3
+ # Sources all XML modules for backward compatibility
4
+ #
5
+ # IMPORTANT: This file is now a loader only. New code should source
6
+ # individual modules directly from .aether/utils/ or .aether/exchange/
7
+ #
8
+ # Usage: source .aether/utils/xml-utils.sh
9
+ #
10
+ # Modules loaded:
11
+ # - xml-core.sh : Core operations (validate, format, escape)
12
+ # - xml-query.sh : XPath queries
13
+ # - xml-convert.sh : JSON/XML conversion
14
+ # - xml-compose.sh : XInclude composition
15
+ # - pheromone-xml.sh : Pheromone exchange
16
+ # - wisdom-xml.sh : Queen wisdom exchange
17
+ # - registry-xml.sh : Colony registry exchange
18
+ #
19
+ # Deprecated functions (maintained for compatibility):
20
+ # - pheromone-to-xml() -> Use xml-pheromone-export()
21
+ # - pheromone-from-xml() -> Use xml-pheromone-import()
22
+ # - queen-wisdom-to-xml() -> Use xml-wisdom-export()
23
+ # - queen-wisdom-from-xml() -> Use xml-wisdom-import()
24
+
25
+ set -euo pipefail
26
+
27
+ # Determine script directory for relative sourcing
28
+ # Handle case when sourced interactively (BASH_SOURCE[0] may be empty)
29
+ if [[ -n "${BASH_SOURCE[0]:-}" ]]; then
30
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
31
+ else
32
+ # Fallback: derive from the sourced script's location
33
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
34
+ fi
35
+ EXCHANGE_DIR="$(cd "$SCRIPT_DIR/../exchange" && pwd)"
36
+
37
+ # ============================================================================
38
+ # Load Core Modules
39
+ # ============================================================================
40
+
41
+ # Core utilities (required by other modules)
42
+ source "$SCRIPT_DIR/xml-core.sh"
43
+
44
+ # Query functions
45
+ source "$SCRIPT_DIR/xml-query.sh"
46
+
47
+ # Conversion functions
48
+ source "$SCRIPT_DIR/xml-convert.sh"
49
+
50
+ # Composition functions
51
+ source "$SCRIPT_DIR/xml-compose.sh"
52
+
53
+ # ============================================================================
54
+ # Load Exchange Modules
55
+ # ============================================================================
56
+
57
+ # Pheromone exchange (export/import)
58
+ source "$EXCHANGE_DIR/pheromone-xml.sh"
59
+
60
+ # Queen wisdom exchange
61
+ source "$EXCHANGE_DIR/wisdom-xml.sh"
62
+
63
+ # Colony registry exchange
64
+ source "$EXCHANGE_DIR/registry-xml.sh"
65
+
66
+ # ============================================================================
67
+ # Backward Compatibility Aliases
68
+ # ============================================================================
69
+
70
+ # Map old function names to new ones for compatibility
71
+ pheromone-to-xml() { xml-pheromone-export "$@"; }
72
+ pheromone-from-xml() { xml-pheromone-import "$@"; }
73
+ queen-wisdom-to-xml() { xml-wisdom-export "$@"; }
74
+ queen-wisdom-from-xml() { xml-wisdom-import "$@"; }
75
+ registry-to-xml() { xml-registry-export "$@"; }
76
+ registry-from-xml() { xml-registry-import "$@"; }
77
+
78
+ # Export compatibility aliases
79
+ export -f pheromone-to-xml pheromone-from-xml
80
+ export -f queen-wisdom-to-xml queen-wisdom-from-xml
81
+ export -f registry-to-xml registry-from-xml
82
+
83
+ # ============================================================================
84
+ # Module Information
85
+ # ============================================================================
86
+
87
+ # xml-utils-info: Display module information
88
+ # Usage: xml-utils-info
89
+ xml-utils-info() {
90
+ xml_json_ok '{
91
+ "modules": [
92
+ "xml-core.sh",
93
+ "xml-query.sh",
94
+ "xml-convert.sh",
95
+ "xml-compose.sh",
96
+ "pheromone-xml.sh",
97
+ "wisdom-xml.sh",
98
+ "registry-xml.sh"
99
+ ],
100
+ "note": "This loader provides backward compatibility. New code should source individual modules.",
101
+ "tools": {
102
+ "xmllint": '"$XMLLINT_AVAILABLE"',
103
+ "xmlstarlet": '"$XMLSTARLET_AVAILABLE"',
104
+ "xsltproc": '"$XSLTPROC_AVAILABLE"'
105
+ }
106
+ }'
107
+ }
108
+
109
+ export -f xml-utils-info
110
+