aether-colony 3.1.17 → 5.0.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 (183) hide show
  1. package/{runtime → .aether}/CONTEXT.md +1 -1
  2. package/{runtime → .aether}/aether-utils.sh +1772 -98
  3. package/.aether/docs/QUEEN-SYSTEM.md +211 -0
  4. package/.aether/docs/QUEEN.md +84 -0
  5. package/.aether/docs/README.md +68 -0
  6. package/.aether/docs/caste-system.md +48 -0
  7. package/{runtime → .aether/docs/disciplines}/DISCIPLINES.md +8 -8
  8. package/.aether/docs/error-codes.md +268 -0
  9. package/{runtime → .aether}/docs/known-issues.md +42 -26
  10. package/.aether/docs/queen-commands.md +97 -0
  11. package/.aether/exchange/colony-registry.xml +11 -0
  12. package/{runtime → .aether}/exchange/pheromone-xml.sh +2 -1
  13. package/.aether/exchange/pheromones.xml +87 -0
  14. package/.aether/exchange/queen-wisdom.xml +14 -0
  15. package/{runtime → .aether}/exchange/registry-xml.sh +7 -3
  16. package/{runtime → .aether}/exchange/wisdom-xml.sh +11 -4
  17. package/.aether/rules/aether-colony.md +134 -0
  18. package/.aether/schemas/example-prompt-builder.xml +234 -0
  19. package/.aether/templates/colony-state-reset.jq.template +22 -0
  20. package/.aether/templates/colony-state.template.json +35 -0
  21. package/.aether/templates/constraints.template.json +9 -0
  22. package/.aether/templates/crowned-anthill.template.md +36 -0
  23. package/.aether/templates/handoff-build-error.template.md +30 -0
  24. package/.aether/templates/handoff-build-success.template.md +39 -0
  25. package/.aether/templates/handoff.template.md +40 -0
  26. package/{runtime → .aether}/utils/atomic-write.sh +5 -5
  27. package/{runtime → .aether}/utils/chamber-compare.sh +23 -10
  28. package/{runtime → .aether}/utils/chamber-utils.sh +32 -20
  29. package/{runtime → .aether}/utils/error-handler.sh +13 -1
  30. package/{runtime → .aether}/utils/file-lock.sh +49 -13
  31. package/.aether/utils/semantic-cli.sh +413 -0
  32. package/{runtime → .aether}/utils/xml-compose.sh +7 -1
  33. package/.aether/utils/xml-convert.sh +273 -0
  34. package/.aether/utils/xml-query.sh +201 -0
  35. package/.aether/utils/xml-utils.sh +110 -0
  36. package/{runtime → .aether}/workers.md +14 -17
  37. package/.claude/agents/ant/aether-ambassador.md +264 -0
  38. package/.claude/agents/ant/aether-archaeologist.md +322 -0
  39. package/.claude/agents/ant/aether-auditor.md +266 -0
  40. package/.claude/agents/ant/aether-builder.md +187 -0
  41. package/.claude/agents/ant/aether-chaos.md +268 -0
  42. package/.claude/agents/ant/aether-chronicler.md +304 -0
  43. package/.claude/agents/ant/aether-gatekeeper.md +325 -0
  44. package/.claude/agents/ant/aether-includer.md +373 -0
  45. package/.claude/agents/ant/aether-keeper.md +271 -0
  46. package/.claude/agents/ant/aether-measurer.md +317 -0
  47. package/.claude/agents/ant/aether-probe.md +210 -0
  48. package/.claude/agents/ant/aether-queen.md +325 -0
  49. package/.claude/agents/ant/aether-route-setter.md +173 -0
  50. package/.claude/agents/ant/aether-sage.md +353 -0
  51. package/.claude/agents/ant/aether-scout.md +142 -0
  52. package/.claude/agents/ant/aether-surveyor-disciplines.md +416 -0
  53. package/.claude/agents/ant/aether-surveyor-nest.md +354 -0
  54. package/.claude/agents/ant/aether-surveyor-pathogens.md +288 -0
  55. package/.claude/agents/ant/aether-surveyor-provisions.md +359 -0
  56. package/.claude/agents/ant/aether-tracker.md +265 -0
  57. package/.claude/agents/ant/aether-watcher.md +244 -0
  58. package/.claude/agents/ant/aether-weaver.md +247 -0
  59. package/.claude/commands/ant/archaeology.md +16 -7
  60. package/.claude/commands/ant/build.md +415 -284
  61. package/.claude/commands/ant/chaos.md +19 -10
  62. package/.claude/commands/ant/colonize.md +58 -24
  63. package/.claude/commands/ant/continue.md +155 -145
  64. package/.claude/commands/ant/council.md +15 -5
  65. package/.claude/commands/ant/dream.md +16 -7
  66. package/.claude/commands/ant/entomb.md +274 -157
  67. package/.claude/commands/ant/feedback.md +33 -29
  68. package/.claude/commands/ant/flag.md +18 -10
  69. package/.claude/commands/ant/flags.md +14 -6
  70. package/.claude/commands/ant/focus.md +29 -21
  71. package/.claude/commands/ant/help.md +11 -1
  72. package/.claude/commands/ant/history.md +10 -0
  73. package/.claude/commands/ant/init.md +91 -65
  74. package/.claude/commands/ant/interpret.md +15 -4
  75. package/.claude/commands/ant/lay-eggs.md +55 -7
  76. package/.claude/commands/ant/maturity.md +11 -1
  77. package/.claude/commands/ant/migrate-state.md +14 -2
  78. package/.claude/commands/ant/oracle.md +23 -15
  79. package/.claude/commands/ant/organize.md +29 -20
  80. package/.claude/commands/ant/pause-colony.md +17 -7
  81. package/.claude/commands/ant/phase.md +17 -8
  82. package/.claude/commands/ant/plan.md +20 -9
  83. package/.claude/commands/ant/redirect.md +29 -32
  84. package/.claude/commands/ant/resume-colony.md +19 -9
  85. package/.claude/commands/ant/resume.md +272 -96
  86. package/.claude/commands/ant/seal.md +201 -191
  87. package/.claude/commands/ant/status.md +71 -32
  88. package/.claude/commands/ant/swarm.md +26 -44
  89. package/.claude/commands/ant/tunnels.md +279 -105
  90. package/.claude/commands/ant/update.md +81 -20
  91. package/.claude/commands/ant/verify-castes.md +14 -4
  92. package/.claude/commands/ant/watch.md +13 -12
  93. package/.opencode/agents/aether-ambassador.md +63 -20
  94. package/.opencode/agents/aether-archaeologist.md +29 -12
  95. package/.opencode/agents/aether-auditor.md +51 -18
  96. package/.opencode/agents/aether-builder.md +69 -19
  97. package/.opencode/agents/aether-chaos.md +29 -12
  98. package/.opencode/agents/aether-chronicler.md +60 -18
  99. package/.opencode/agents/aether-gatekeeper.md +27 -18
  100. package/.opencode/agents/aether-includer.md +27 -18
  101. package/.opencode/agents/aether-keeper.md +89 -18
  102. package/.opencode/agents/aether-measurer.md +27 -18
  103. package/.opencode/agents/aether-probe.md +60 -18
  104. package/.opencode/agents/aether-queen.md +172 -24
  105. package/.opencode/agents/aether-route-setter.md +57 -12
  106. package/.opencode/agents/aether-sage.md +26 -18
  107. package/.opencode/agents/aether-scout.md +27 -19
  108. package/.opencode/agents/aether-surveyor-disciplines.md +53 -1
  109. package/.opencode/agents/aether-surveyor-nest.md +53 -1
  110. package/.opencode/agents/aether-surveyor-pathogens.md +51 -1
  111. package/.opencode/agents/aether-surveyor-provisions.md +53 -1
  112. package/.opencode/agents/aether-tracker.md +64 -18
  113. package/.opencode/agents/aether-watcher.md +66 -19
  114. package/.opencode/agents/aether-weaver.md +61 -18
  115. package/.opencode/commands/ant/build.md +406 -192
  116. package/.opencode/commands/ant/continue.md +66 -76
  117. package/.opencode/commands/ant/entomb.md +106 -45
  118. package/.opencode/commands/ant/init.md +46 -48
  119. package/.opencode/commands/ant/organize.md +5 -5
  120. package/.opencode/commands/ant/resume.md +334 -0
  121. package/.opencode/commands/ant/seal.md +33 -24
  122. package/.opencode/commands/ant/status.md +11 -0
  123. package/.opencode/commands/ant/tunnels.md +149 -0
  124. package/.opencode/commands/ant/update.md +59 -16
  125. package/CHANGELOG.md +79 -0
  126. package/README.md +135 -353
  127. package/bin/cli.js +243 -122
  128. package/bin/generate-commands.sh +2 -2
  129. package/bin/lib/init.js +13 -3
  130. package/bin/lib/update-transaction.js +119 -117
  131. package/bin/sync-to-runtime.sh +5 -137
  132. package/bin/validate-package.sh +84 -0
  133. package/package.json +9 -6
  134. package/.opencode/agents/aether-architect.md +0 -66
  135. package/.opencode/agents/aether-guardian.md +0 -107
  136. package/.opencode/agents/workers.md +0 -1034
  137. package/runtime/QUEEN_ANT_ARCHITECTURE.md +0 -402
  138. package/runtime/data/signatures.json +0 -41
  139. package/runtime/docs/AETHER-2.0-IMPLEMENTATION-PLAN.md +0 -1343
  140. package/runtime/docs/AETHER-PHEROMONE-SYSTEM-MASTER-SPEC.md +0 -2642
  141. package/runtime/docs/PHEROMONE-INJECTION.md +0 -240
  142. package/runtime/docs/PHEROMONE-INTEGRATION.md +0 -192
  143. package/runtime/docs/PHEROMONE-SYSTEM-DESIGN.md +0 -426
  144. package/runtime/docs/README.md +0 -94
  145. package/runtime/docs/VISUAL-OUTPUT-SPEC.md +0 -219
  146. package/runtime/docs/biological-reference.md +0 -272
  147. package/runtime/docs/codebase-review.md +0 -399
  148. package/runtime/docs/command-sync.md +0 -164
  149. package/runtime/docs/constraints.md +0 -116
  150. package/runtime/docs/implementation-learnings.md +0 -89
  151. package/runtime/docs/namespace.md +0 -148
  152. package/runtime/docs/pathogen-schema-example.json +0 -36
  153. package/runtime/docs/pathogen-schema.md +0 -111
  154. package/runtime/docs/planning-discipline.md +0 -159
  155. package/runtime/docs/progressive-disclosure.md +0 -184
  156. package/runtime/lib/queen-utils.sh +0 -729
  157. package/runtime/planning.md +0 -159
  158. package/runtime/recover.sh +0 -136
  159. package/runtime/utils/xml-utils.sh +0 -2196
  160. package/runtime/workers-new-castes.md +0 -516
  161. /package/{runtime → .aether/docs/disciplines}/coding-standards.md +0 -0
  162. /package/{runtime → .aether/docs/disciplines}/debugging.md +0 -0
  163. /package/{runtime → .aether/docs/disciplines}/learning.md +0 -0
  164. /package/{runtime → .aether/docs/disciplines}/tdd.md +0 -0
  165. /package/{runtime → .aether/docs/disciplines}/verification-loop.md +0 -0
  166. /package/{runtime → .aether/docs/disciplines}/verification.md +0 -0
  167. /package/{runtime → .aether}/docs/pheromones.md +0 -0
  168. /package/{runtime → .aether}/model-profiles.yaml +0 -0
  169. /package/{runtime → .aether}/schemas/aether-types.xsd +0 -0
  170. /package/{runtime → .aether}/schemas/colony-registry.xsd +0 -0
  171. /package/{runtime → .aether}/schemas/pheromone.xsd +0 -0
  172. /package/{runtime → .aether}/schemas/prompt.xsd +0 -0
  173. /package/{runtime → .aether}/schemas/queen-wisdom.xsd +0 -0
  174. /package/{runtime → .aether}/schemas/worker-priming.xsd +0 -0
  175. /package/{runtime → .aether}/templates/QUEEN.md.template +0 -0
  176. /package/{runtime → .aether}/utils/colorize-log.sh +0 -0
  177. /package/{runtime → .aether}/utils/queen-to-md.xsl +0 -0
  178. /package/{runtime → .aether}/utils/spawn-tree.sh +0 -0
  179. /package/{runtime → .aether}/utils/spawn-with-model.sh +0 -0
  180. /package/{runtime → .aether}/utils/state-loader.sh +0 -0
  181. /package/{runtime → .aether}/utils/swarm-display.sh +0 -0
  182. /package/{runtime → .aether}/utils/watch-spawn-tree.sh +0 -0
  183. /package/{runtime → .aether}/utils/xml-core.sh +0 -0
@@ -161,62 +161,21 @@ class UpdateTransaction {
161
161
  // Hub paths (from cli.js)
162
162
  this.HOME = process.env.HOME || process.env.USERPROFILE;
163
163
  this.HUB_DIR = path.join(this.HOME, '.aether');
164
- this.HUB_COMMANDS_CLAUDE = path.join(this.HUB_DIR, 'commands', 'claude');
165
- this.HUB_COMMANDS_OPENCODE = path.join(this.HUB_DIR, 'commands', 'opencode');
166
- this.HUB_AGENTS = path.join(this.HUB_DIR, 'agents');
164
+ this.HUB_SYSTEM_DIR = path.join(this.HUB_DIR, 'system');
165
+ this.HUB_COMMANDS_CLAUDE = path.join(this.HUB_SYSTEM_DIR, 'commands', 'claude');
166
+ this.HUB_COMMANDS_OPENCODE = path.join(this.HUB_SYSTEM_DIR, 'commands', 'opencode');
167
+ this.HUB_AGENTS = path.join(this.HUB_SYSTEM_DIR, 'agents');
168
+ this.HUB_AGENTS_CLAUDE = path.join(this.HUB_SYSTEM_DIR, 'agents-claude');
169
+ this.HUB_RULES = path.join(this.HUB_SYSTEM_DIR, 'rules');
167
170
  this.HUB_VERSION = path.join(this.HUB_DIR, 'version.json');
168
171
  this.HUB_REGISTRY = path.join(this.HUB_DIR, 'registry.json');
169
172
 
170
- // Directories to exclude from sync (user data, local state)
171
- this.EXCLUDE_DIRS = ['data', 'dreams', 'checkpoints', 'locks', 'temp'];
173
+ // Directories to exclude from sync (user data, local state, and separately-synced dirs)
174
+ // v4.0: archive and chambers added these are private and must not sync to target repos
175
+ this.EXCLUDE_DIRS = ['data', 'dreams', 'checkpoints', 'locks', 'temp', 'agents', 'commands', 'rules', 'archive', 'chambers'];
172
176
 
173
177
  // Target directories for git safety checks
174
- this.targetDirs = ['.aether', '.claude/commands/ant', '.opencode/commands/ant', '.opencode/agents'];
175
-
176
- // System files allowlist (from cli.js)
177
- this.SYSTEM_FILES = [
178
- 'aether-utils.sh',
179
- 'coding-standards.md',
180
- 'debugging.md',
181
- 'DISCIPLINES.md',
182
- 'learning.md',
183
- 'planning.md',
184
- 'QUEEN_ANT_ARCHITECTURE.md',
185
- 'tdd.md',
186
- 'verification-loop.md',
187
- 'verification.md',
188
- 'workers.md',
189
- 'workers-new-castes.md',
190
- 'docs/biological-reference.md',
191
- 'docs/command-sync.md',
192
- 'docs/constraints.md',
193
- 'docs/namespace.md',
194
- 'docs/pathogen-schema-example.json',
195
- 'docs/pathogen-schema.md',
196
- 'docs/PHEROMONE-INJECTION.md',
197
- 'docs/PHEROMONE-INTEGRATION.md',
198
- 'docs/PHEROMONE-SYSTEM-DESIGN.md',
199
- 'docs/pheromones.md',
200
- 'docs/progressive-disclosure.md',
201
- 'docs/README.md',
202
- 'docs/VISUAL-OUTPUT-SPEC.md',
203
- 'docs/known-issues.md',
204
- 'docs/implementation-learnings.md',
205
- 'docs/codebase-review.md',
206
- 'docs/planning-discipline.md',
207
- 'utils/atomic-write.sh',
208
- 'utils/chamber-compare.sh',
209
- 'utils/chamber-utils.sh',
210
- 'utils/colorize-log.sh',
211
- 'utils/error-handler.sh',
212
- 'utils/file-lock.sh',
213
- 'utils/spawn-tree.sh',
214
- 'utils/spawn-with-model.sh',
215
- 'utils/state-loader.sh',
216
- 'utils/swarm-display.sh',
217
- 'utils/watch-spawn-tree.sh',
218
- 'templates/QUEEN.md.template',
219
- ];
178
+ this.targetDirs = ['.aether', '.claude/commands/ant', '.claude/agents/ant', '.claude/rules', '.opencode/commands/ant', '.opencode/agents'];
220
179
  }
221
180
 
222
181
  /**
@@ -686,66 +645,6 @@ class UpdateTransaction {
686
645
  }
687
646
  }
688
647
 
689
- /**
690
- * Sync system files from hub
691
- * @param {string} srcDir - Source directory
692
- * @param {string} destDir - Destination directory
693
- * @param {object} opts - Options
694
- * @returns {object} Sync result: { copied, removed, skipped }
695
- * @private
696
- */
697
- syncSystemFilesWithCleanup(srcDir, destDir, opts) {
698
- opts = opts || {};
699
- const dryRun = opts.dryRun || false;
700
-
701
- let copied = 0;
702
- let skipped = 0;
703
-
704
- for (const file of this.SYSTEM_FILES) {
705
- const srcPath = path.join(srcDir, file);
706
- const destPath = path.join(destDir, file);
707
- if (fs.existsSync(srcPath)) {
708
- if (!dryRun) {
709
- // Compute hashes to determine if copy is needed
710
- const srcHash = this.hashFileSync(srcPath);
711
- const destHash = fs.existsSync(destPath) ? this.hashFileSync(destPath) : null;
712
-
713
- if (srcHash === destHash) {
714
- // Files are identical, skip copying
715
- skipped++;
716
- continue;
717
- }
718
-
719
- fs.mkdirSync(path.dirname(destPath), { recursive: true });
720
- fs.copyFileSync(srcPath, destPath);
721
- if (file.endsWith('.sh')) {
722
- fs.chmodSync(destPath, 0o755);
723
- }
724
- }
725
- copied++;
726
- }
727
- }
728
-
729
- // Remove allowlisted files that no longer exist in src
730
- const removed = [];
731
- for (const file of this.SYSTEM_FILES) {
732
- const srcPath = path.join(srcDir, file);
733
- const destPath = path.join(destDir, file);
734
- if (!fs.existsSync(srcPath) && fs.existsSync(destPath)) {
735
- removed.push(file);
736
- if (!dryRun) {
737
- fs.unlinkSync(destPath);
738
- }
739
- }
740
- }
741
-
742
- if (!dryRun && removed.length > 0) {
743
- this.cleanEmptyDirs(destDir);
744
- }
745
-
746
- return { copied, removed, skipped };
747
- }
748
-
749
648
  /**
750
649
  * Check if a path should be excluded from sync
751
650
  * @param {string} relPath - Relative path
@@ -867,6 +766,60 @@ class UpdateTransaction {
867
766
  return { copied, removed, skipped };
868
767
  }
869
768
 
769
+ /**
770
+ * Remove known stale directories and files left behind by pre-3.0.0 versions.
771
+ * These paths were incorrectly distributed in earlier releases and must be
772
+ * explicitly removed — EXCLUDE_DIRS prevents NEW pollution but does not clean
773
+ * items that already exist on disk.
774
+ *
775
+ * Idempotent: safe to call when items do not exist.
776
+ *
777
+ * @param {string} repoPath - Absolute path to the target repository root
778
+ * @returns {{ cleaned: string[], failed: Array<{label: string, error: string}> }}
779
+ */
780
+ cleanupStaleAetherDirs(repoPath) {
781
+ const staleItems = [
782
+ {
783
+ path: path.join(repoPath, '.aether', 'agents'),
784
+ label: '.aether/agents/ (stale duplicate)',
785
+ type: 'dir',
786
+ },
787
+ {
788
+ path: path.join(repoPath, '.aether', 'commands'),
789
+ label: '.aether/commands/ (stale duplicate)',
790
+ type: 'dir',
791
+ },
792
+ {
793
+ path: path.join(repoPath, '.aether', 'planning.md'),
794
+ label: '.aether/planning.md (phantom file)',
795
+ type: 'file',
796
+ },
797
+ ];
798
+
799
+ const cleaned = [];
800
+ const failed = [];
801
+
802
+ for (const item of staleItems) {
803
+ if (!fs.existsSync(item.path)) {
804
+ // Already clean — idempotent skip
805
+ continue;
806
+ }
807
+
808
+ try {
809
+ if (item.type === 'dir') {
810
+ fs.rmSync(item.path, { recursive: true, force: true });
811
+ } else {
812
+ fs.unlinkSync(item.path);
813
+ }
814
+ cleaned.push(item.label);
815
+ } catch (err) {
816
+ failed.push({ label: item.label, error: err.message });
817
+ }
818
+ }
819
+
820
+ return { cleaned, failed };
821
+ }
822
+
870
823
  /**
871
824
  * Sync files from hub to repo
872
825
  * @param {string} sourceVersion - Version to sync from
@@ -880,14 +833,16 @@ class UpdateTransaction {
880
833
  system: { copied: 0, removed: 0, skipped: 0 },
881
834
  commands: { copied: 0, removed: 0, skipped: 0 },
882
835
  agents: { copied: 0, removed: 0, skipped: 0 },
836
+ agents_claude: { copied: 0, removed: [], skipped: 0 },
837
+ rules: { copied: 0, removed: 0, skipped: 0 },
883
838
  errors: [],
884
839
  };
885
840
 
886
841
  const repoAether = path.join(this.repoPath, '.aether');
887
842
 
888
843
  // Sync .aether/ from hub to repo (excluding user data directories)
889
- if (fs.existsSync(this.HUB_DIR)) {
890
- results.system = this.syncAetherToRepo(this.HUB_DIR, repoAether, { dryRun });
844
+ if (fs.existsSync(this.HUB_SYSTEM_DIR)) {
845
+ results.system = this.syncAetherToRepo(this.HUB_SYSTEM_DIR, repoAether, { dryRun });
891
846
  }
892
847
 
893
848
  // Sync commands from hub
@@ -911,6 +866,18 @@ class UpdateTransaction {
911
866
  results.agents = this.syncDirWithCleanup(this.HUB_AGENTS, repoAgents, { dryRun });
912
867
  }
913
868
 
869
+ // Sync claude agents from hub to .claude/agents/ant/
870
+ const repoClaudeAgents = path.join(this.repoPath, '.claude', 'agents', 'ant');
871
+ if (fs.existsSync(this.HUB_AGENTS_CLAUDE)) {
872
+ results.agents_claude = this.syncDirWithCleanup(this.HUB_AGENTS_CLAUDE, repoClaudeAgents, { dryRun });
873
+ }
874
+
875
+ // Sync rules from hub to .claude/rules/
876
+ const repoRules = path.join(this.repoPath, '.claude', 'rules');
877
+ if (fs.existsSync(this.HUB_RULES)) {
878
+ results.rules = this.syncDirWithCleanup(this.HUB_RULES, repoRules, { dryRun });
879
+ }
880
+
914
881
  this.syncResult = results;
915
882
  return results;
916
883
  }
@@ -953,10 +920,12 @@ class UpdateTransaction {
953
920
  };
954
921
 
955
922
  const repoAether = path.join(this.repoPath, '.aether');
956
- verifyDir(this.HUB_DIR, repoAether);
923
+ verifyDir(this.HUB_SYSTEM_DIR, repoAether);
957
924
  verifyDir(this.HUB_COMMANDS_CLAUDE, path.join(this.repoPath, '.claude', 'commands', 'ant'));
958
925
  verifyDir(this.HUB_COMMANDS_OPENCODE, path.join(this.repoPath, '.opencode', 'commands', 'ant'));
959
926
  verifyDir(this.HUB_AGENTS, path.join(this.repoPath, '.opencode', 'agents'));
927
+ verifyDir(this.HUB_AGENTS_CLAUDE, path.join(this.repoPath, '.claude', 'agents', 'ant'));
928
+ verifyDir(this.HUB_RULES, path.join(this.repoPath, '.claude', 'rules'));
960
929
 
961
930
  return {
962
931
  valid: errors.length === 0,
@@ -1002,6 +971,8 @@ class UpdateTransaction {
1002
971
  checkDir(this.HUB_COMMANDS_CLAUDE, 'commands/claude');
1003
972
  checkDir(this.HUB_COMMANDS_OPENCODE, 'commands/opencode');
1004
973
  checkDir(this.HUB_AGENTS, 'agents');
974
+ checkDir(this.HUB_AGENTS_CLAUDE, 'agents-claude');
975
+ checkDir(this.HUB_RULES, 'rules');
1005
976
  checkDir(this.HUB_VERSION, 'version');
1006
977
 
1007
978
  // Check if source files exist
@@ -1098,10 +1069,11 @@ class UpdateTransaction {
1098
1069
  };
1099
1070
 
1100
1071
  const repoAether = path.join(this.repoPath, '.aether');
1101
- checkDir(this.HUB_DIR, repoAether);
1072
+ checkDir(this.HUB_SYSTEM_DIR, repoAether);
1102
1073
  checkDir(this.HUB_COMMANDS_CLAUDE, path.join(this.repoPath, '.claude', 'commands', 'ant'));
1103
1074
  checkDir(this.HUB_COMMANDS_OPENCODE, path.join(this.repoPath, '.opencode', 'commands', 'ant'));
1104
1075
  checkDir(this.HUB_AGENTS, path.join(this.repoPath, '.opencode', 'agents'));
1076
+ checkDir(this.HUB_RULES, path.join(this.repoPath, '.claude', 'rules'));
1105
1077
 
1106
1078
  return {
1107
1079
  isPartial: missing.length > 0 || corrupted.length > 0,
@@ -1260,6 +1232,14 @@ class UpdateTransaction {
1260
1232
  * @returns {Promise<boolean>} True if rollback succeeded
1261
1233
  */
1262
1234
  async rollback() {
1235
+ // Clear pending sentinel on rollback — we've cleanly returned to prior state
1236
+ const pendingPath = path.join(this.repoPath, '.aether', '.update-pending');
1237
+ try {
1238
+ if (fs.existsSync(pendingPath)) {
1239
+ fs.unlinkSync(pendingPath);
1240
+ }
1241
+ } catch { /* ignore — rollback cleanup is best-effort */ }
1242
+
1263
1243
  this.state = TransactionStates.ROLLING_BACK;
1264
1244
  this.log(' Rolling back to checkpoint...');
1265
1245
 
@@ -1342,6 +1322,13 @@ class UpdateTransaction {
1342
1322
  async execute(sourceVersion, options = {}) {
1343
1323
  const dryRun = options.dryRun || false;
1344
1324
 
1325
+ // Write pending sentinel BEFORE any work — marks update as in-flight
1326
+ const pendingPath = path.join(this.repoPath, '.aether', '.update-pending');
1327
+ this.writeJsonSync(pendingPath, {
1328
+ target_version: sourceVersion,
1329
+ started_at: new Date().toISOString(),
1330
+ });
1331
+
1345
1332
  try {
1346
1333
  // Phase 0: Validate repo state (before any modifications)
1347
1334
  // Check for dirty repo and provide clear recovery instructions
@@ -1368,6 +1355,9 @@ class UpdateTransaction {
1368
1355
 
1369
1356
  await this.createCheckpoint();
1370
1357
 
1358
+ // Clean up known stale directories/files from previous versions
1359
+ this.cleanupResult = this.cleanupStaleAetherDirs(this.repoPath);
1360
+
1371
1361
  // Phase 2: Sync (with network error handling)
1372
1362
  this.state = TransactionStates.SYNCING;
1373
1363
  try {
@@ -1403,15 +1393,26 @@ class UpdateTransaction {
1403
1393
  this.state = TransactionStates.COMMITTING;
1404
1394
  this.updateVersion(sourceVersion);
1405
1395
  this.state = TransactionStates.COMMITTED;
1396
+
1397
+ // Delete pending sentinel — update is now complete
1398
+ try {
1399
+ if (fs.existsSync(pendingPath)) {
1400
+ fs.unlinkSync(pendingPath);
1401
+ }
1402
+ } catch (err) {
1403
+ this.log(` Warning: could not clear update sentinel: ${err.message}`);
1404
+ }
1406
1405
  }
1407
1406
 
1408
1407
  // Calculate totals
1409
1408
  const filesSynced = (this.syncResult?.system?.copied || 0) +
1410
1409
  (this.syncResult?.commands?.copied || 0) +
1411
- (this.syncResult?.agents?.copied || 0);
1410
+ (this.syncResult?.agents?.copied || 0) +
1411
+ (this.syncResult?.rules?.copied || 0);
1412
1412
  const filesRemoved = (this.syncResult?.system?.removed?.length || 0) +
1413
1413
  (this.syncResult?.commands?.removed?.length || 0) +
1414
- (this.syncResult?.agents?.removed?.length || 0);
1414
+ (this.syncResult?.agents?.removed?.length || 0) +
1415
+ (this.syncResult?.rules?.removed?.length || 0);
1415
1416
 
1416
1417
  return {
1417
1418
  success: true,
@@ -1420,6 +1421,7 @@ class UpdateTransaction {
1420
1421
  files_synced: filesSynced,
1421
1422
  files_removed: filesRemoved,
1422
1423
  sync_result: this.syncResult,
1424
+ cleanup_result: this.cleanupResult || { cleaned: [], failed: [] },
1423
1425
  };
1424
1426
 
1425
1427
  } catch (error) {
@@ -1,138 +1,6 @@
1
1
  #!/bin/bash
2
- # sync-to-runtime.sh — Copies allowlisted system files from .aether/ to runtime/
3
- #
4
- # Purpose: In the Aether repo, .aether/ is the source of truth for system files.
5
- # This script syncs those files INTO runtime/ (the npm staging directory)
6
- # so that `npm install -g .` packages the latest versions.
7
- #
8
- # Usage: bash bin/sync-to-runtime.sh [--reverse]
9
- # --reverse Copy FROM runtime/ TO .aether/ (one-time seed operation)
10
- #
11
- # This script is safe to run multiple times (idempotent).
12
- # It only copies allowlisted files — it never deletes extras in runtime/.
13
-
14
- set -e
15
-
16
- # Resolve repo root (one level up from bin/)
17
- REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
18
- AETHER_DIR="$REPO_ROOT/.aether"
19
- RUNTIME_DIR="$REPO_ROOT/runtime"
20
-
21
- # Allowlist: these are the system files that sync between .aether/ and runtime/
22
- # Must match the SYSTEM_FILES array in bin/lib/update-transaction.js
23
- SYSTEM_FILES=(
24
- "aether-utils.sh"
25
- "coding-standards.md"
26
- "debugging.md"
27
- "DISCIPLINES.md"
28
- "learning.md"
29
- "planning.md"
30
- "QUEEN_ANT_ARCHITECTURE.md"
31
- "tdd.md"
32
- "verification-loop.md"
33
- "verification.md"
34
- "workers.md"
35
- "workers-new-castes.md"
36
- "CONTEXT.md"
37
- "model-profiles.yaml"
38
- "recover.sh"
39
- "docs/biological-reference.md"
40
- "docs/command-sync.md"
41
- "docs/constraints.md"
42
- "docs/namespace.md"
43
- "docs/pathogen-schema-example.json"
44
- "docs/pathogen-schema.md"
45
- "docs/PHEROMONE-INJECTION.md"
46
- "docs/PHEROMONE-INTEGRATION.md"
47
- "docs/PHEROMONE-SYSTEM-DESIGN.md"
48
- "docs/pheromones.md"
49
- "docs/progressive-disclosure.md"
50
- "docs/README.md"
51
- "docs/VISUAL-OUTPUT-SPEC.md"
52
- "docs/known-issues.md"
53
- "docs/implementation-learnings.md"
54
- "docs/codebase-review.md"
55
- "docs/planning-discipline.md"
56
- "utils/atomic-write.sh"
57
- "utils/chamber-compare.sh"
58
- "utils/chamber-utils.sh"
59
- "utils/colorize-log.sh"
60
- "utils/error-handler.sh"
61
- "utils/file-lock.sh"
62
- "utils/spawn-tree.sh"
63
- "utils/spawn-with-model.sh"
64
- "utils/state-loader.sh"
65
- "utils/swarm-display.sh"
66
- "utils/watch-spawn-tree.sh"
67
- "utils/xml-utils.sh"
68
- "utils/xml-core.sh"
69
- "utils/xml-compose.sh"
70
- "utils/queen-to-md.xsl"
71
- "exchange/pheromone-xml.sh"
72
- "exchange/wisdom-xml.sh"
73
- "exchange/registry-xml.sh"
74
- "schemas/aether-types.xsd"
75
- "schemas/pheromone.xsd"
76
- "schemas/queen-wisdom.xsd"
77
- "schemas/colony-registry.xsd"
78
- "schemas/worker-priming.xsd"
79
- "schemas/prompt.xsd"
80
- "templates/QUEEN.md.template"
81
- )
82
-
83
- # Determine direction
84
- REVERSE=false
85
- if [ "${1:-}" = "--reverse" ]; then
86
- REVERSE=true
87
- fi
88
-
89
- if [ "$REVERSE" = true ]; then
90
- SRC_DIR="$RUNTIME_DIR"
91
- DST_DIR="$AETHER_DIR"
92
- LABEL="runtime/ -> .aether/ (seeding)"
93
- else
94
- SRC_DIR="$AETHER_DIR"
95
- DST_DIR="$RUNTIME_DIR"
96
- LABEL=".aether/ -> runtime/ (staging)"
97
- fi
98
-
99
- # Check source directory exists
100
- if [ ! -d "$SRC_DIR" ]; then
101
- # Silently exit if source doesn't exist (e.g. installed from npm, no .aether/)
102
- exit 0
103
- fi
104
-
105
- copied=0
106
- skipped=0
107
-
108
- for file in "${SYSTEM_FILES[@]}"; do
109
- src="$SRC_DIR/$file"
110
- dst="$DST_DIR/$file"
111
-
112
- # Skip if source file doesn't exist
113
- if [ ! -f "$src" ]; then
114
- continue
115
- fi
116
-
117
- # Create destination directory if needed
118
- dst_dir="$(dirname "$dst")"
119
- mkdir -p "$dst_dir"
120
-
121
- # Skip if files are identical (compare hashes)
122
- if [ -f "$dst" ]; then
123
- src_hash=$(shasum -a 256 "$src" 2>/dev/null | cut -d' ' -f1)
124
- dst_hash=$(shasum -a 256 "$dst" 2>/dev/null | cut -d' ' -f1)
125
- if [ "$src_hash" = "$dst_hash" ]; then
126
- skipped=$((skipped + 1))
127
- continue
128
- fi
129
- fi
130
-
131
- cp "$src" "$dst"
132
- copied=$((copied + 1))
133
- done
134
-
135
- # Only print output if not running in quiet mode (npm postinstall suppresses)
136
- if [ -t 1 ] || [ "${VERBOSE:-}" = "1" ]; then
137
- echo "Sync ($LABEL): $copied copied, $skipped unchanged"
138
- fi
2
+ # sync-to-runtime.sh — DEPRECATED (v4.0)
3
+ # runtime/ staging was eliminated in v4.0. .aether/ is packaged directly.
4
+ # This script exists only for CI backward compatibility.
5
+ echo "runtime/ sync skipped deprecated in v4.0 (direct .aether/ packaging)"
6
+ exit 0
@@ -0,0 +1,84 @@
1
+ #!/bin/bash
2
+ # validate-package.sh — Pre-packaging validation for aether-colony npm package
3
+ #
4
+ # Purpose: Replaces sync-to-runtime.sh (removed in v4.0). Instead of copying files
5
+ # to a staging directory, this script validates that .aether/ is ready for
6
+ # direct packaging: required files exist, private directories are excluded.
7
+ #
8
+ # Usage: bash bin/validate-package.sh [--dry-run]
9
+ # --dry-run Run npm pack --dry-run to show what would be published
10
+ #
11
+ # This script is safe to run multiple times (idempotent).
12
+
13
+ set -euo pipefail
14
+
15
+ # Resolve paths relative to script location
16
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
17
+ REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
18
+ AETHER_DIR="$(cd "$SCRIPT_DIR/../.aether" && pwd)"
19
+
20
+ # --dry-run mode: delegate to npm pack and exit
21
+ if [ "${1:-}" = "--dry-run" ]; then
22
+ cd "$REPO_ROOT"
23
+ npm pack --dry-run 2>&1
24
+ exit 0
25
+ fi
26
+
27
+ # Required files that must exist in .aether/ before packaging
28
+ REQUIRED_FILES=(
29
+ "aether-utils.sh"
30
+ "workers.md"
31
+ "CONTEXT.md"
32
+ "model-profiles.yaml"
33
+ "docs/README.md"
34
+ "utils/atomic-write.sh"
35
+ "utils/error-handler.sh"
36
+ "utils/file-lock.sh"
37
+ "templates/QUEEN.md.template"
38
+ "templates/colony-state.template.json"
39
+ "templates/constraints.template.json"
40
+ "templates/colony-state-reset.jq.template"
41
+ "templates/crowned-anthill.template.md"
42
+ "templates/handoff.template.md"
43
+ "templates/handoff-build-error.template.md"
44
+ "templates/handoff-build-success.template.md"
45
+ "rules/aether-colony.md"
46
+ )
47
+
48
+ # Verify required files exist
49
+ for file in "${REQUIRED_FILES[@]}"; do
50
+ if [ ! -f "$AETHER_DIR/$file" ]; then
51
+ echo "ERROR: Required file missing from .aether/: $file" >&2
52
+ echo " Run this from the Aether repo root after editing .aether/ files." >&2
53
+ exit 1
54
+ fi
55
+ done
56
+
57
+ # Private directories that must never be published
58
+ PRIVATE_DIRS=(
59
+ "data"
60
+ "dreams"
61
+ "oracle"
62
+ "checkpoints"
63
+ "locks"
64
+ "temp"
65
+ "archive"
66
+ "chambers"
67
+ )
68
+
69
+ # .aether/.npmignore is the effective ignore file for the .aether/ subdirectory.
70
+ # npm-packlist reads subdirectory .npmignore files when walking included directories.
71
+ AETHER_NPMIGNORE="$AETHER_DIR/.npmignore"
72
+
73
+ # Verify each private directory is excluded in .aether/.npmignore (hard block)
74
+ for dir in "${PRIVATE_DIRS[@]}"; do
75
+ if [ -d "$AETHER_DIR/$dir" ]; then
76
+ if ! grep -qF "$dir/" "$AETHER_NPMIGNORE" 2>/dev/null; then
77
+ echo "ERROR: Private directory .aether/$dir/ exists but is NOT excluded in .aether/.npmignore" >&2
78
+ echo " Add '$dir/' to .aether/.npmignore to prevent publishing private data." >&2
79
+ exit 1
80
+ fi
81
+ fi
82
+ done
83
+
84
+ echo "Package validation passed."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aether-colony",
3
- "version": "3.1.17",
3
+ "version": "5.0.0",
4
4
  "description": "Multi-agent system using ant colony intelligence for Claude Code and OpenCode — workers self-organize via pheromone signals",
5
5
  "bin": {
6
6
  "aether": "bin/cli.js"
@@ -8,23 +8,26 @@
8
8
  "files": [
9
9
  "bin/",
10
10
  ".claude/commands/ant/",
11
+ ".claude/agents/ant/",
11
12
  ".opencode/commands/ant/",
12
13
  ".opencode/agents/",
13
14
  ".opencode/opencode.json",
14
- "runtime/",
15
+ ".aether/",
15
16
  "README.md",
16
17
  "LICENSE",
17
18
  "DISCLAIMER.md",
18
19
  "CHANGELOG.md"
19
20
  ],
20
21
  "scripts": {
21
- "preinstall": "bash bin/sync-to-runtime.sh 2>/dev/null || true",
22
+ "preinstall": "bash bin/validate-package.sh 2>/dev/null || true",
22
23
  "postinstall": "node bin/cli.js install --quiet",
23
- "test": "npm run test:unit && npm run test:bash",
24
+ "prepublishOnly": "bash bin/validate-package.sh",
25
+ "test": "npm run test:unit",
26
+ "test:all": "npm run test:unit && npm run test:bash",
24
27
  "test:unit": "ava",
25
28
  "test:bash": "bash tests/bash/test-aether-utils.sh",
26
- "lint:shell": "shellcheck --severity=error .aether/aether-utils.sh runtime/aether-utils.sh bin/generate-commands.sh .aether/utils/file-lock.sh .aether/utils/atomic-write.sh .aether/utils/colorize-log.sh .aether/utils/watch-spawn-tree.sh runtime/utils/file-lock.sh runtime/utils/atomic-write.sh runtime/utils/colorize-log.sh runtime/utils/watch-spawn-tree.sh",
27
- "lint:json": "node -e \"const fs=require('fs'); const files=['.aether/data/constraints.json','.aether/data/COLONY_STATE.json']; files.forEach(f=>{JSON.parse(fs.readFileSync(f,'utf8'))}); console.log('JSON valid')\"",
29
+ "lint:shell": "shellcheck --severity=error .aether/aether-utils.sh bin/generate-commands.sh .aether/utils/file-lock.sh .aether/utils/atomic-write.sh .aether/utils/colorize-log.sh .aether/utils/watch-spawn-tree.sh",
30
+ "lint:json": "node -e \"const fs=require('fs'); const files=['.aether/data/constraints.json','.aether/data/COLONY_STATE.json']; files.filter(f=>fs.existsSync(f)).forEach(f=>{JSON.parse(fs.readFileSync(f,'utf8'))}); console.log('JSON valid')\"",
28
31
  "lint:sync": "bash bin/generate-commands.sh check",
29
32
  "lint": "npm run lint:shell && npm run lint:json && npm run lint:sync"
30
33
  },
@@ -1,66 +0,0 @@
1
- ---
2
- name: aether-architect
3
- description: "Architect ant - synthesizes knowledge and coordinates documentation"
4
- ---
5
-
6
- You are an **Architect Ant** in the Aether Colony. You are the colony's wisdom — when the colony learns, you organize and preserve that knowledge.
7
-
8
- ## Aether Integration
9
-
10
- This agent operates as a **specialist worker** within the Aether Colony system. You:
11
- - Report to the Queen/Prime worker who spawns you
12
- - Log activity using Aether utilities
13
- - Follow depth-based spawning rules
14
- - Output structured JSON reports
15
-
16
- ## Activity Logging
17
-
18
- Log progress as you work:
19
- ```bash
20
- bash .aether/aether-utils.sh activity-log "ACTION" "{your_name} (Architect)" "description"
21
- ```
22
-
23
- Actions: SYNTHESIZING, EXTRACTING, ORGANIZING, COMPLETED
24
-
25
- ## Your Role
26
-
27
- As Architect, you:
28
- 1. Analyze input — what knowledge needs organizing?
29
- 2. Extract patterns — success patterns, failure patterns, preferences
30
- 3. Synthesize into coherent structures
31
- 4. Document clear, actionable summaries with recommendations
32
-
33
- ## Synthesis Workflow
34
-
35
- 1. **Gather** - Collect all relevant information
36
- 2. **Analyze** - Identify patterns and themes
37
- 3. **Structure** - Organize into logical hierarchy
38
- 4. **Document** - Create clear, actionable output
39
-
40
- ## Model Context
41
-
42
- - **Model:** glm-5
43
- - **Strengths:** Long-context synthesis, pattern extraction, complex documentation
44
- - **Best for:** Synthesizing knowledge, coordinating docs, pattern recognition
45
-
46
- ## Output Format
47
-
48
- ```json
49
- {
50
- "ant_name": "{your name}",
51
- "caste": "architect",
52
- "target": "{what was synthesized}",
53
- "status": "completed",
54
- "patterns_extracted": [],
55
- "synthesis": {
56
- "summary": "{overall summary}",
57
- "key_findings": [],
58
- "recommendations": []
59
- },
60
- "documentation": {}
61
- }
62
- ```
63
-
64
- ## Reference
65
-
66
- Full worker specifications: `.aether/workers.md`