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.
- package/{runtime → .aether}/CONTEXT.md +1 -1
- package/{runtime → .aether}/aether-utils.sh +1772 -98
- package/.aether/docs/QUEEN-SYSTEM.md +211 -0
- package/.aether/docs/QUEEN.md +84 -0
- package/.aether/docs/README.md +68 -0
- package/.aether/docs/caste-system.md +48 -0
- package/{runtime → .aether/docs/disciplines}/DISCIPLINES.md +8 -8
- package/.aether/docs/error-codes.md +268 -0
- package/{runtime → .aether}/docs/known-issues.md +42 -26
- package/.aether/docs/queen-commands.md +97 -0
- package/.aether/exchange/colony-registry.xml +11 -0
- package/{runtime → .aether}/exchange/pheromone-xml.sh +2 -1
- package/.aether/exchange/pheromones.xml +87 -0
- package/.aether/exchange/queen-wisdom.xml +14 -0
- package/{runtime → .aether}/exchange/registry-xml.sh +7 -3
- package/{runtime → .aether}/exchange/wisdom-xml.sh +11 -4
- package/.aether/rules/aether-colony.md +134 -0
- package/.aether/schemas/example-prompt-builder.xml +234 -0
- package/.aether/templates/colony-state-reset.jq.template +22 -0
- package/.aether/templates/colony-state.template.json +35 -0
- package/.aether/templates/constraints.template.json +9 -0
- package/.aether/templates/crowned-anthill.template.md +36 -0
- package/.aether/templates/handoff-build-error.template.md +30 -0
- package/.aether/templates/handoff-build-success.template.md +39 -0
- package/.aether/templates/handoff.template.md +40 -0
- package/{runtime → .aether}/utils/atomic-write.sh +5 -5
- package/{runtime → .aether}/utils/chamber-compare.sh +23 -10
- package/{runtime → .aether}/utils/chamber-utils.sh +32 -20
- package/{runtime → .aether}/utils/error-handler.sh +13 -1
- package/{runtime → .aether}/utils/file-lock.sh +49 -13
- package/.aether/utils/semantic-cli.sh +413 -0
- package/{runtime → .aether}/utils/xml-compose.sh +7 -1
- package/.aether/utils/xml-convert.sh +273 -0
- package/.aether/utils/xml-query.sh +201 -0
- package/.aether/utils/xml-utils.sh +110 -0
- package/{runtime → .aether}/workers.md +14 -17
- package/.claude/agents/ant/aether-ambassador.md +264 -0
- package/.claude/agents/ant/aether-archaeologist.md +322 -0
- package/.claude/agents/ant/aether-auditor.md +266 -0
- package/.claude/agents/ant/aether-builder.md +187 -0
- package/.claude/agents/ant/aether-chaos.md +268 -0
- package/.claude/agents/ant/aether-chronicler.md +304 -0
- package/.claude/agents/ant/aether-gatekeeper.md +325 -0
- package/.claude/agents/ant/aether-includer.md +373 -0
- package/.claude/agents/ant/aether-keeper.md +271 -0
- package/.claude/agents/ant/aether-measurer.md +317 -0
- package/.claude/agents/ant/aether-probe.md +210 -0
- package/.claude/agents/ant/aether-queen.md +325 -0
- package/.claude/agents/ant/aether-route-setter.md +173 -0
- package/.claude/agents/ant/aether-sage.md +353 -0
- package/.claude/agents/ant/aether-scout.md +142 -0
- package/.claude/agents/ant/aether-surveyor-disciplines.md +416 -0
- package/.claude/agents/ant/aether-surveyor-nest.md +354 -0
- package/.claude/agents/ant/aether-surveyor-pathogens.md +288 -0
- package/.claude/agents/ant/aether-surveyor-provisions.md +359 -0
- package/.claude/agents/ant/aether-tracker.md +265 -0
- package/.claude/agents/ant/aether-watcher.md +244 -0
- package/.claude/agents/ant/aether-weaver.md +247 -0
- package/.claude/commands/ant/archaeology.md +16 -7
- package/.claude/commands/ant/build.md +415 -284
- package/.claude/commands/ant/chaos.md +19 -10
- package/.claude/commands/ant/colonize.md +58 -24
- package/.claude/commands/ant/continue.md +155 -145
- package/.claude/commands/ant/council.md +15 -5
- package/.claude/commands/ant/dream.md +16 -7
- package/.claude/commands/ant/entomb.md +274 -157
- package/.claude/commands/ant/feedback.md +33 -29
- package/.claude/commands/ant/flag.md +18 -10
- package/.claude/commands/ant/flags.md +14 -6
- package/.claude/commands/ant/focus.md +29 -21
- package/.claude/commands/ant/help.md +11 -1
- package/.claude/commands/ant/history.md +10 -0
- package/.claude/commands/ant/init.md +91 -65
- package/.claude/commands/ant/interpret.md +15 -4
- package/.claude/commands/ant/lay-eggs.md +55 -7
- package/.claude/commands/ant/maturity.md +11 -1
- package/.claude/commands/ant/migrate-state.md +14 -2
- package/.claude/commands/ant/oracle.md +23 -15
- package/.claude/commands/ant/organize.md +29 -20
- package/.claude/commands/ant/pause-colony.md +17 -7
- package/.claude/commands/ant/phase.md +17 -8
- package/.claude/commands/ant/plan.md +20 -9
- package/.claude/commands/ant/redirect.md +29 -32
- package/.claude/commands/ant/resume-colony.md +19 -9
- package/.claude/commands/ant/resume.md +272 -96
- package/.claude/commands/ant/seal.md +201 -191
- package/.claude/commands/ant/status.md +71 -32
- package/.claude/commands/ant/swarm.md +26 -44
- package/.claude/commands/ant/tunnels.md +279 -105
- package/.claude/commands/ant/update.md +81 -20
- package/.claude/commands/ant/verify-castes.md +14 -4
- package/.claude/commands/ant/watch.md +13 -12
- package/.opencode/agents/aether-ambassador.md +63 -20
- package/.opencode/agents/aether-archaeologist.md +29 -12
- package/.opencode/agents/aether-auditor.md +51 -18
- package/.opencode/agents/aether-builder.md +69 -19
- package/.opencode/agents/aether-chaos.md +29 -12
- package/.opencode/agents/aether-chronicler.md +60 -18
- package/.opencode/agents/aether-gatekeeper.md +27 -18
- package/.opencode/agents/aether-includer.md +27 -18
- package/.opencode/agents/aether-keeper.md +89 -18
- package/.opencode/agents/aether-measurer.md +27 -18
- package/.opencode/agents/aether-probe.md +60 -18
- package/.opencode/agents/aether-queen.md +172 -24
- package/.opencode/agents/aether-route-setter.md +57 -12
- package/.opencode/agents/aether-sage.md +26 -18
- package/.opencode/agents/aether-scout.md +27 -19
- package/.opencode/agents/aether-surveyor-disciplines.md +53 -1
- package/.opencode/agents/aether-surveyor-nest.md +53 -1
- package/.opencode/agents/aether-surveyor-pathogens.md +51 -1
- package/.opencode/agents/aether-surveyor-provisions.md +53 -1
- package/.opencode/agents/aether-tracker.md +64 -18
- package/.opencode/agents/aether-watcher.md +66 -19
- package/.opencode/agents/aether-weaver.md +61 -18
- package/.opencode/commands/ant/build.md +406 -192
- package/.opencode/commands/ant/continue.md +66 -76
- package/.opencode/commands/ant/entomb.md +106 -45
- package/.opencode/commands/ant/init.md +46 -48
- package/.opencode/commands/ant/organize.md +5 -5
- package/.opencode/commands/ant/resume.md +334 -0
- package/.opencode/commands/ant/seal.md +33 -24
- package/.opencode/commands/ant/status.md +11 -0
- package/.opencode/commands/ant/tunnels.md +149 -0
- package/.opencode/commands/ant/update.md +59 -16
- package/CHANGELOG.md +79 -0
- package/README.md +135 -353
- package/bin/cli.js +243 -122
- package/bin/generate-commands.sh +2 -2
- package/bin/lib/init.js +13 -3
- package/bin/lib/update-transaction.js +119 -117
- package/bin/sync-to-runtime.sh +5 -137
- package/bin/validate-package.sh +84 -0
- package/package.json +9 -6
- package/.opencode/agents/aether-architect.md +0 -66
- package/.opencode/agents/aether-guardian.md +0 -107
- package/.opencode/agents/workers.md +0 -1034
- package/runtime/QUEEN_ANT_ARCHITECTURE.md +0 -402
- package/runtime/data/signatures.json +0 -41
- package/runtime/docs/AETHER-2.0-IMPLEMENTATION-PLAN.md +0 -1343
- package/runtime/docs/AETHER-PHEROMONE-SYSTEM-MASTER-SPEC.md +0 -2642
- package/runtime/docs/PHEROMONE-INJECTION.md +0 -240
- package/runtime/docs/PHEROMONE-INTEGRATION.md +0 -192
- package/runtime/docs/PHEROMONE-SYSTEM-DESIGN.md +0 -426
- package/runtime/docs/README.md +0 -94
- package/runtime/docs/VISUAL-OUTPUT-SPEC.md +0 -219
- package/runtime/docs/biological-reference.md +0 -272
- package/runtime/docs/codebase-review.md +0 -399
- package/runtime/docs/command-sync.md +0 -164
- package/runtime/docs/constraints.md +0 -116
- package/runtime/docs/implementation-learnings.md +0 -89
- package/runtime/docs/namespace.md +0 -148
- package/runtime/docs/pathogen-schema-example.json +0 -36
- package/runtime/docs/pathogen-schema.md +0 -111
- package/runtime/docs/planning-discipline.md +0 -159
- package/runtime/docs/progressive-disclosure.md +0 -184
- package/runtime/lib/queen-utils.sh +0 -729
- package/runtime/planning.md +0 -159
- package/runtime/recover.sh +0 -136
- package/runtime/utils/xml-utils.sh +0 -2196
- package/runtime/workers-new-castes.md +0 -516
- /package/{runtime → .aether/docs/disciplines}/coding-standards.md +0 -0
- /package/{runtime → .aether/docs/disciplines}/debugging.md +0 -0
- /package/{runtime → .aether/docs/disciplines}/learning.md +0 -0
- /package/{runtime → .aether/docs/disciplines}/tdd.md +0 -0
- /package/{runtime → .aether/docs/disciplines}/verification-loop.md +0 -0
- /package/{runtime → .aether/docs/disciplines}/verification.md +0 -0
- /package/{runtime → .aether}/docs/pheromones.md +0 -0
- /package/{runtime → .aether}/model-profiles.yaml +0 -0
- /package/{runtime → .aether}/schemas/aether-types.xsd +0 -0
- /package/{runtime → .aether}/schemas/colony-registry.xsd +0 -0
- /package/{runtime → .aether}/schemas/pheromone.xsd +0 -0
- /package/{runtime → .aether}/schemas/prompt.xsd +0 -0
- /package/{runtime → .aether}/schemas/queen-wisdom.xsd +0 -0
- /package/{runtime → .aether}/schemas/worker-priming.xsd +0 -0
- /package/{runtime → .aether}/templates/QUEEN.md.template +0 -0
- /package/{runtime → .aether}/utils/colorize-log.sh +0 -0
- /package/{runtime → .aether}/utils/queen-to-md.xsl +0 -0
- /package/{runtime → .aether}/utils/spawn-tree.sh +0 -0
- /package/{runtime → .aether}/utils/spawn-with-model.sh +0 -0
- /package/{runtime → .aether}/utils/state-loader.sh +0 -0
- /package/{runtime → .aether}/utils/swarm-display.sh +0 -0
- /package/{runtime → .aether}/utils/watch-spawn-tree.sh +0 -0
- /package/{runtime → .aether}/utils/xml-core.sh +0 -0
package/bin/cli.js
CHANGED
|
@@ -67,12 +67,16 @@ if (!HOME) {
|
|
|
67
67
|
// Claude Code paths (global)
|
|
68
68
|
const COMMANDS_SRC = path.join(PACKAGE_DIR, 'commands', 'ant');
|
|
69
69
|
const COMMANDS_DEST = path.join(HOME, '.claude', 'commands', 'ant');
|
|
70
|
+
const AGENTS_DEST = path.join(HOME, '.claude', 'agents', 'ant');
|
|
70
71
|
|
|
71
72
|
// Hub paths
|
|
72
73
|
const HUB_DIR = path.join(HOME, '.aether');
|
|
73
|
-
const
|
|
74
|
-
const
|
|
75
|
-
const
|
|
74
|
+
const HUB_SYSTEM_DIR = path.join(HUB_DIR, 'system');
|
|
75
|
+
const HUB_COMMANDS_CLAUDE = path.join(HUB_SYSTEM_DIR, 'commands', 'claude');
|
|
76
|
+
const HUB_COMMANDS_OPENCODE = path.join(HUB_SYSTEM_DIR, 'commands', 'opencode');
|
|
77
|
+
const HUB_AGENTS = path.join(HUB_SYSTEM_DIR, 'agents');
|
|
78
|
+
const HUB_AGENTS_CLAUDE = path.join(HUB_SYSTEM_DIR, 'agents-claude');
|
|
79
|
+
const HUB_RULES = path.join(HUB_SYSTEM_DIR, 'rules');
|
|
76
80
|
const HUB_REGISTRY = path.join(HUB_DIR, 'registry.json');
|
|
77
81
|
const HUB_VERSION = path.join(HUB_DIR, 'version.json');
|
|
78
82
|
|
|
@@ -374,47 +378,6 @@ function removeDirSync(dir) {
|
|
|
374
378
|
return count;
|
|
375
379
|
}
|
|
376
380
|
|
|
377
|
-
// System files allowlist — only these are copied during updates (never colony data)
|
|
378
|
-
const SYSTEM_FILES = [
|
|
379
|
-
'aether-utils.sh',
|
|
380
|
-
'coding-standards.md',
|
|
381
|
-
'debugging.md',
|
|
382
|
-
'DISCIPLINES.md',
|
|
383
|
-
'learning.md',
|
|
384
|
-
'planning.md',
|
|
385
|
-
'QUEEN_ANT_ARCHITECTURE.md',
|
|
386
|
-
'tdd.md',
|
|
387
|
-
'verification-loop.md',
|
|
388
|
-
'verification.md',
|
|
389
|
-
'workers.md',
|
|
390
|
-
'docs/constraints.md',
|
|
391
|
-
'docs/pathogen-schema-example.json',
|
|
392
|
-
'docs/pathogen-schema.md',
|
|
393
|
-
'docs/pheromones.md',
|
|
394
|
-
'docs/progressive-disclosure.md',
|
|
395
|
-
'utils/atomic-write.sh',
|
|
396
|
-
'utils/colorize-log.sh',
|
|
397
|
-
'utils/file-lock.sh',
|
|
398
|
-
'utils/watch-spawn-tree.sh',
|
|
399
|
-
];
|
|
400
|
-
|
|
401
|
-
function copySystemFiles(srcDir, destDir) {
|
|
402
|
-
let count = 0;
|
|
403
|
-
for (const file of SYSTEM_FILES) {
|
|
404
|
-
const srcPath = path.join(srcDir, file);
|
|
405
|
-
const destPath = path.join(destDir, file);
|
|
406
|
-
if (fs.existsSync(srcPath)) {
|
|
407
|
-
fs.mkdirSync(path.dirname(destPath), { recursive: true });
|
|
408
|
-
fs.copyFileSync(srcPath, destPath);
|
|
409
|
-
if (file.endsWith('.sh')) {
|
|
410
|
-
fs.chmodSync(destPath, 0o755);
|
|
411
|
-
}
|
|
412
|
-
count++;
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
return count;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
381
|
function readJsonSafe(filePath) {
|
|
419
382
|
try {
|
|
420
383
|
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
@@ -585,65 +548,15 @@ function computeFileHash(filePath) {
|
|
|
585
548
|
}
|
|
586
549
|
}
|
|
587
550
|
|
|
588
|
-
function syncSystemFilesWithCleanup(srcDir, destDir, opts) {
|
|
589
|
-
opts = opts || {};
|
|
590
|
-
const dryRun = opts.dryRun || false;
|
|
591
|
-
|
|
592
|
-
let copied = 0;
|
|
593
|
-
let skipped = 0;
|
|
594
|
-
for (const file of SYSTEM_FILES) {
|
|
595
|
-
const srcPath = path.join(srcDir, file);
|
|
596
|
-
const destPath = path.join(destDir, file);
|
|
597
|
-
if (fs.existsSync(srcPath)) {
|
|
598
|
-
if (!dryRun) {
|
|
599
|
-
// Compute hashes to determine if copy is needed
|
|
600
|
-
const srcHash = computeFileHash(srcPath);
|
|
601
|
-
const destHash = fs.existsSync(destPath) ? computeFileHash(destPath) : null;
|
|
602
|
-
|
|
603
|
-
if (srcHash === destHash) {
|
|
604
|
-
// Files are identical, skip copying
|
|
605
|
-
skipped++;
|
|
606
|
-
continue;
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
fs.mkdirSync(path.dirname(destPath), { recursive: true });
|
|
610
|
-
fs.copyFileSync(srcPath, destPath);
|
|
611
|
-
if (file.endsWith('.sh')) {
|
|
612
|
-
fs.chmodSync(destPath, 0o755);
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
copied++;
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
// Remove allowlisted files that no longer exist in src
|
|
620
|
-
const removed = [];
|
|
621
|
-
for (const file of SYSTEM_FILES) {
|
|
622
|
-
const srcPath = path.join(srcDir, file);
|
|
623
|
-
const destPath = path.join(destDir, file);
|
|
624
|
-
if (!fs.existsSync(srcPath) && fs.existsSync(destPath)) {
|
|
625
|
-
removed.push(file);
|
|
626
|
-
if (!dryRun) {
|
|
627
|
-
fs.unlinkSync(destPath);
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
if (!dryRun && removed.length > 0) {
|
|
633
|
-
cleanEmptyDirs(destDir);
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
return { copied, removed, skipped };
|
|
637
|
-
}
|
|
638
|
-
|
|
639
551
|
// Checkpoint allowlist - only these files are captured in checkpoints
|
|
640
552
|
// NEVER include: data/, dreams/, oracle/, TO-DOs.md (user data)
|
|
553
|
+
// Note: runtime/ was removed in v4.0 — .aether/ is published directly
|
|
641
554
|
const CHECKPOINT_ALLOWLIST = [
|
|
642
555
|
'.aether/*.md', // All .md files directly in .aether/
|
|
643
556
|
'.claude/commands/ant/**', // All files in .claude/commands/ant/ recursively
|
|
557
|
+
'.claude/agents/ant/**', // All files in .claude/agents/ant/ recursively
|
|
644
558
|
'.opencode/commands/ant/**', // All files in .opencode/commands/ant/ recursively
|
|
645
559
|
'.opencode/agents/**', // All files in .opencode/agents/ recursively
|
|
646
|
-
'runtime/**', // All files in runtime/ recursively
|
|
647
560
|
'bin/cli.js', // Specific file: bin/cli.js
|
|
648
561
|
];
|
|
649
562
|
|
|
@@ -835,7 +748,8 @@ function gitStashFiles(repoPath, files) {
|
|
|
835
748
|
}
|
|
836
749
|
|
|
837
750
|
// Directories to exclude from hub sync (user data, local state)
|
|
838
|
-
|
|
751
|
+
// 'rules' is excluded here because it is synced via a dedicated step (rulesSrc below)
|
|
752
|
+
const HUB_EXCLUDE_DIRS = ['data', 'dreams', 'checkpoints', 'locks', 'temp', 'rules'];
|
|
839
753
|
|
|
840
754
|
/**
|
|
841
755
|
* Check if a path should be excluded from hub sync
|
|
@@ -955,6 +869,47 @@ function setupHub() {
|
|
|
955
869
|
try {
|
|
956
870
|
fs.mkdirSync(HUB_DIR, { recursive: true });
|
|
957
871
|
|
|
872
|
+
// MIGRATION: Check for old structure and migrate to system/
|
|
873
|
+
const oldStructureFiles = [
|
|
874
|
+
path.join(HUB_DIR, 'aether-utils.sh'),
|
|
875
|
+
path.join(HUB_DIR, 'workers.md'),
|
|
876
|
+
];
|
|
877
|
+
const hasOldStructure = oldStructureFiles.some(f => fs.existsSync(f));
|
|
878
|
+
const hasNewStructure = fs.existsSync(HUB_SYSTEM_DIR);
|
|
879
|
+
|
|
880
|
+
if (hasOldStructure && !hasNewStructure) {
|
|
881
|
+
log(' Migrating hub to new structure...');
|
|
882
|
+
fs.mkdirSync(HUB_SYSTEM_DIR, { recursive: true });
|
|
883
|
+
|
|
884
|
+
// Move system files to system/
|
|
885
|
+
const systemFiles = ['aether-utils.sh', 'workers.md', 'CONTEXT.md', 'model-profiles.yaml'];
|
|
886
|
+
const systemDirs = ['docs', 'utils', 'commands', 'agents', 'schemas', 'exchange', 'templates', 'lib'];
|
|
887
|
+
|
|
888
|
+
for (const file of systemFiles) {
|
|
889
|
+
const oldPath = path.join(HUB_DIR, file);
|
|
890
|
+
if (fs.existsSync(oldPath)) {
|
|
891
|
+
fs.renameSync(oldPath, path.join(HUB_SYSTEM_DIR, file));
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
for (const dir of systemDirs) {
|
|
896
|
+
const oldPath = path.join(HUB_DIR, dir);
|
|
897
|
+
if (fs.existsSync(oldPath)) {
|
|
898
|
+
fs.renameSync(oldPath, path.join(HUB_SYSTEM_DIR, dir));
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
log(' Migration complete: system files moved to ~/.aether/system/');
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
// Create system/ directory structure
|
|
906
|
+
fs.mkdirSync(HUB_SYSTEM_DIR, { recursive: true });
|
|
907
|
+
fs.mkdirSync(path.join(HUB_SYSTEM_DIR, 'commands', 'claude'), { recursive: true });
|
|
908
|
+
fs.mkdirSync(path.join(HUB_SYSTEM_DIR, 'commands', 'opencode'), { recursive: true });
|
|
909
|
+
fs.mkdirSync(path.join(HUB_SYSTEM_DIR, 'agents'), { recursive: true });
|
|
910
|
+
fs.mkdirSync(path.join(HUB_SYSTEM_DIR, 'agents-claude'), { recursive: true });
|
|
911
|
+
fs.mkdirSync(path.join(HUB_SYSTEM_DIR, 'rules'), { recursive: true });
|
|
912
|
+
|
|
958
913
|
// Read previous manifest for delta reporting
|
|
959
914
|
const prevManifestRaw = readJsonSafe(path.join(HUB_DIR, 'manifest.json'));
|
|
960
915
|
const prevManifest = prevManifestRaw && validateManifest(prevManifestRaw).valid ? prevManifestRaw : null;
|
|
@@ -962,21 +917,32 @@ function setupHub() {
|
|
|
962
917
|
log(` Warning: previous manifest is invalid, regenerating`);
|
|
963
918
|
}
|
|
964
919
|
|
|
965
|
-
// Sync
|
|
966
|
-
//
|
|
967
|
-
const
|
|
968
|
-
if (fs.existsSync(
|
|
969
|
-
const result = syncAetherToHub(
|
|
970
|
-
log(` Hub system: ${result.copied} files, ${result.skipped} unchanged -> ${
|
|
920
|
+
// Sync .aether/ -> ~/.aether/system/ (direct packaging, no staging)
|
|
921
|
+
// v4.0: .aether/ is published directly — runtime/ staging removed
|
|
922
|
+
const aetherSrc = path.join(PACKAGE_DIR, '.aether');
|
|
923
|
+
if (fs.existsSync(aetherSrc)) {
|
|
924
|
+
const result = syncAetherToHub(aetherSrc, HUB_SYSTEM_DIR);
|
|
925
|
+
log(` Hub system: ${result.copied} files, ${result.skipped} unchanged -> ${HUB_SYSTEM_DIR}`);
|
|
971
926
|
if (result.removed.length > 0) {
|
|
972
927
|
log(` Hub system: removed ${result.removed.length} stale files`);
|
|
973
928
|
for (const f of result.removed) log(` - ${f}`);
|
|
974
929
|
}
|
|
975
930
|
}
|
|
976
931
|
|
|
977
|
-
//
|
|
932
|
+
// Migration message for users upgrading from pre-4.0 (runtime/ era)
|
|
933
|
+
const prevManifestForMigration = readJsonSafe(path.join(HUB_DIR, 'manifest.json'));
|
|
934
|
+
if (prevManifestForMigration && prevManifestForMigration.version && prevManifestForMigration.version.startsWith('3.')) {
|
|
935
|
+
log('');
|
|
936
|
+
log(' Distribution pipeline simplified (v4.0 change):');
|
|
937
|
+
log(' - runtime/ staging directory has been removed');
|
|
938
|
+
log(' - .aether/ is now published directly (private dirs excluded)');
|
|
939
|
+
log(' - Your colony state and data are unaffected');
|
|
940
|
+
log(' - See CHANGELOG.md for details');
|
|
941
|
+
log('');
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
// Clean up legacy directories from very old hub structure (pre-system/)
|
|
978
945
|
const legacyDirs = [
|
|
979
|
-
path.join(HUB_DIR, 'system'),
|
|
980
946
|
path.join(HUB_DIR, '.aether'),
|
|
981
947
|
path.join(HUB_DIR, 'visualizations'),
|
|
982
948
|
];
|
|
@@ -991,7 +957,7 @@ function setupHub() {
|
|
|
991
957
|
}
|
|
992
958
|
}
|
|
993
959
|
|
|
994
|
-
// Sync .claude/commands/ant/ -> ~/.aether/commands/claude/
|
|
960
|
+
// Sync .claude/commands/ant/ -> ~/.aether/system/commands/claude/
|
|
995
961
|
const claudeCmdSrc = fs.existsSync(COMMANDS_SRC)
|
|
996
962
|
? COMMANDS_SRC
|
|
997
963
|
: path.join(PACKAGE_DIR, '.claude', 'commands', 'ant');
|
|
@@ -1004,7 +970,7 @@ function setupHub() {
|
|
|
1004
970
|
}
|
|
1005
971
|
}
|
|
1006
972
|
|
|
1007
|
-
// Sync .opencode/commands/ant/ -> ~/.aether/commands/opencode/
|
|
973
|
+
// Sync .opencode/commands/ant/ -> ~/.aether/system/commands/opencode/
|
|
1008
974
|
const opencodeCmdSrc = path.join(PACKAGE_DIR, '.opencode', 'commands', 'ant');
|
|
1009
975
|
if (fs.existsSync(opencodeCmdSrc)) {
|
|
1010
976
|
const result = syncDirWithCleanup(opencodeCmdSrc, HUB_COMMANDS_OPENCODE);
|
|
@@ -1015,7 +981,7 @@ function setupHub() {
|
|
|
1015
981
|
}
|
|
1016
982
|
}
|
|
1017
983
|
|
|
1018
|
-
// Sync .opencode/agents/ -> ~/.aether/agents/
|
|
984
|
+
// Sync .opencode/agents/ -> ~/.aether/system/agents/
|
|
1019
985
|
const agentsSrc = path.join(PACKAGE_DIR, '.opencode', 'agents');
|
|
1020
986
|
if (fs.existsSync(agentsSrc)) {
|
|
1021
987
|
const result = syncDirWithCleanup(agentsSrc, HUB_AGENTS);
|
|
@@ -1026,7 +992,30 @@ function setupHub() {
|
|
|
1026
992
|
}
|
|
1027
993
|
}
|
|
1028
994
|
|
|
1029
|
-
//
|
|
995
|
+
// Sync .claude/agents/ant/ -> ~/.aether/system/agents-claude/
|
|
996
|
+
const claudeAgentsSrc = path.join(PACKAGE_DIR, '.claude', 'agents', 'ant');
|
|
997
|
+
if (fs.existsSync(claudeAgentsSrc)) {
|
|
998
|
+
const result = syncDirWithCleanup(claudeAgentsSrc, HUB_AGENTS_CLAUDE);
|
|
999
|
+
log(` Hub agents (claude): ${result.copied} files, ${result.skipped} unchanged -> ${HUB_AGENTS_CLAUDE}`);
|
|
1000
|
+
if (result.removed.length > 0) {
|
|
1001
|
+
log(` Hub agents (claude): removed ${result.removed.length} stale files`);
|
|
1002
|
+
for (const f of result.removed) log(` - ${f}`);
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
// Sync rules/ from .aether/ -> ~/.aether/system/rules/
|
|
1007
|
+
// v4.0: source is .aether/rules/ directly (no runtime/ staging)
|
|
1008
|
+
const rulesSrc = path.join(PACKAGE_DIR, '.aether', 'rules');
|
|
1009
|
+
if (fs.existsSync(rulesSrc)) {
|
|
1010
|
+
const result = syncDirWithCleanup(rulesSrc, HUB_RULES);
|
|
1011
|
+
log(` Hub rules: ${result.copied} files -> ${HUB_RULES}`);
|
|
1012
|
+
if (result.removed.length > 0) {
|
|
1013
|
+
log(` Hub rules: removed ${result.removed.length} stale files`);
|
|
1014
|
+
for (const f of result.removed) log(` - ${f}`);
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
// Create/preserve registry.json (at root, not in system/)
|
|
1030
1019
|
if (!fs.existsSync(HUB_REGISTRY)) {
|
|
1031
1020
|
writeJsonSync(HUB_REGISTRY, { schema_version: 1, repos: [] });
|
|
1032
1021
|
log(` Registry: initialized ${HUB_REGISTRY}`);
|
|
@@ -1034,7 +1023,7 @@ function setupHub() {
|
|
|
1034
1023
|
log(` Registry: preserved existing ${HUB_REGISTRY}`);
|
|
1035
1024
|
}
|
|
1036
1025
|
|
|
1037
|
-
// Generate and write manifest
|
|
1026
|
+
// Generate and write manifest (at root, tracks everything)
|
|
1038
1027
|
const manifest = generateManifest(HUB_DIR);
|
|
1039
1028
|
const manifestPath = path.join(HUB_DIR, 'manifest.json');
|
|
1040
1029
|
writeJsonSync(manifestPath, manifest);
|
|
@@ -1053,7 +1042,7 @@ function setupHub() {
|
|
|
1053
1042
|
}
|
|
1054
1043
|
}
|
|
1055
1044
|
|
|
1056
|
-
// Write version.json
|
|
1045
|
+
// Write version.json (at root)
|
|
1057
1046
|
writeJsonSync(HUB_VERSION, { version: VERSION, updated_at: new Date().toISOString() });
|
|
1058
1047
|
log(` Hub version: ${VERSION}`);
|
|
1059
1048
|
} catch (err) {
|
|
@@ -1079,7 +1068,7 @@ async function updateRepo(repoPath, sourceVersion, opts) {
|
|
|
1079
1068
|
const currentVer = currentVersion ? currentVersion.version : 'unknown';
|
|
1080
1069
|
|
|
1081
1070
|
// Target directories for git safety checks
|
|
1082
|
-
const targetDirs = ['.aether', '.claude/commands/ant', '.opencode/commands/ant', '.opencode/agents'];
|
|
1071
|
+
const targetDirs = ['.aether', '.claude/commands/ant', '.claude/agents/ant', '.claude/rules', '.opencode/commands/ant', '.opencode/agents'];
|
|
1083
1072
|
|
|
1084
1073
|
// Git safety: check for dirty files in target directories (skip in dry-run mode)
|
|
1085
1074
|
let dirtyFiles = [];
|
|
@@ -1101,17 +1090,25 @@ async function updateRepo(repoPath, sourceVersion, opts) {
|
|
|
1101
1090
|
const systemCopied = result.sync_result?.system?.copied || 0;
|
|
1102
1091
|
const commandsCopied = (result.sync_result?.commands?.copied || 0);
|
|
1103
1092
|
const agentsCopied = result.sync_result?.agents?.copied || 0;
|
|
1093
|
+
const rulesCopied = result.sync_result?.rules?.copied || 0;
|
|
1094
|
+
const agentsClaudeCopied = result.sync_result?.agents_claude?.copied || 0;
|
|
1104
1095
|
|
|
1105
1096
|
const systemRemoved = result.sync_result?.system?.removed?.length || 0;
|
|
1106
1097
|
const commandsRemoved = result.sync_result?.commands?.removed?.length || 0;
|
|
1107
1098
|
const agentsRemoved = result.sync_result?.agents?.removed?.length || 0;
|
|
1099
|
+
const rulesRemoved = result.sync_result?.rules?.removed?.length || 0;
|
|
1100
|
+
const agentsClaudeRemoved = result.sync_result?.agents_claude?.removed?.length || 0;
|
|
1108
1101
|
|
|
1109
1102
|
const allRemovedFiles = [
|
|
1110
1103
|
...(result.sync_result?.system?.removed || []),
|
|
1111
1104
|
...(result.sync_result?.commands?.removed || []).map(f => `.claude/commands/ant/${f}`),
|
|
1112
1105
|
...(result.sync_result?.agents?.removed || []).map(f => `.opencode/agents/${f}`),
|
|
1106
|
+
...(result.sync_result?.rules?.removed || []).map(f => `.claude/rules/${f}`),
|
|
1107
|
+
...(result.sync_result?.agents_claude?.removed || []).map(f => `.claude/agents/ant/${f}`),
|
|
1113
1108
|
];
|
|
1114
1109
|
|
|
1110
|
+
const cleanupResult = result.cleanup_result || { cleaned: [], failed: [] };
|
|
1111
|
+
|
|
1115
1112
|
return {
|
|
1116
1113
|
status: result.status,
|
|
1117
1114
|
from: currentVer,
|
|
@@ -1119,10 +1116,13 @@ async function updateRepo(repoPath, sourceVersion, opts) {
|
|
|
1119
1116
|
system: systemCopied,
|
|
1120
1117
|
commands: commandsCopied,
|
|
1121
1118
|
agents: agentsCopied,
|
|
1122
|
-
|
|
1119
|
+
rules: rulesCopied,
|
|
1120
|
+
agentsClaude: agentsClaudeCopied,
|
|
1121
|
+
removed: systemRemoved + commandsRemoved + agentsRemoved + rulesRemoved + agentsClaudeRemoved,
|
|
1123
1122
|
removedFiles: allRemovedFiles,
|
|
1124
1123
|
stashCreated: !!transaction.checkpoint?.stashRef,
|
|
1125
1124
|
checkpoint_id: result.checkpoint_id,
|
|
1125
|
+
cleanup: cleanupResult,
|
|
1126
1126
|
};
|
|
1127
1127
|
} catch (error) {
|
|
1128
1128
|
// Handle UpdateError with recovery commands
|
|
@@ -1161,7 +1161,7 @@ program.on('option:quiet', () => {
|
|
|
1161
1161
|
// Install command
|
|
1162
1162
|
program
|
|
1163
1163
|
.command('install')
|
|
1164
|
-
.description('Install
|
|
1164
|
+
.description('Install commands and agents to ~/.claude/ and set up distribution hub')
|
|
1165
1165
|
.action(wrapCommand(async () => {
|
|
1166
1166
|
log(c.header(`aether-colony v${VERSION} — installing...`));
|
|
1167
1167
|
|
|
@@ -1188,6 +1188,17 @@ program
|
|
|
1188
1188
|
}
|
|
1189
1189
|
}
|
|
1190
1190
|
|
|
1191
|
+
// Sync agents to ~/.claude/agents/ant/ (with orphan cleanup)
|
|
1192
|
+
const repoAgents = path.join(PACKAGE_DIR, '.claude', 'agents', 'ant');
|
|
1193
|
+
if (fs.existsSync(repoAgents)) {
|
|
1194
|
+
const result = syncDirWithCleanup(repoAgents, AGENTS_DEST);
|
|
1195
|
+
log(` Agents (claude): ${result.copied} files -> ${AGENTS_DEST}`);
|
|
1196
|
+
if (result.removed.length > 0) {
|
|
1197
|
+
log(` Agents (claude): removed ${result.removed.length} stale files`);
|
|
1198
|
+
for (const f of result.removed) log(` - ${f}`);
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1191
1202
|
// Set up distribution hub at ~/.aether/
|
|
1192
1203
|
log('');
|
|
1193
1204
|
log(c.colony('Setting up distribution hub...'));
|
|
@@ -1288,19 +1299,31 @@ program
|
|
|
1288
1299
|
console.error(` Skipping. Use --force to stash and update.`);
|
|
1289
1300
|
dirty++;
|
|
1290
1301
|
} else if (result.status === 'dry-run') {
|
|
1291
|
-
log(` Would update: ${repo.path} (${result.from} -> ${result.to}) [${result.system} system, ${result.commands} commands, ${result.agents} agents]`);
|
|
1302
|
+
log(` Would update: ${repo.path} (${result.from} -> ${result.to}) [${result.system} system, ${result.commands} commands, ${result.agents} agents, ${result.agentsClaude} claude agents]`);
|
|
1292
1303
|
if (result.removed > 0) {
|
|
1293
1304
|
log(` Would remove ${result.removed} stale files:`);
|
|
1294
1305
|
for (const f of result.removedFiles) log(` - ${f}`);
|
|
1295
1306
|
}
|
|
1296
1307
|
updated++;
|
|
1297
1308
|
} else if (result.status === 'updated') {
|
|
1298
|
-
log(` ${c.success('Updated:')} ${repo.path} (${result.from} -> ${result.to}) [${result.system} system, ${result.commands} commands, ${result.agents} agents]`);
|
|
1309
|
+
log(` ${c.success('Updated:')} ${repo.path} (${result.from} -> ${result.to}) [${result.system} system, ${result.commands} commands, ${result.agents} agents, ${result.agentsClaude} claude agents]`);
|
|
1299
1310
|
if (result.removed > 0) {
|
|
1300
1311
|
log(` Removed ${result.removed} stale files:`);
|
|
1301
1312
|
for (const f of result.removedFiles) log(` - ${f}`);
|
|
1302
1313
|
totalRemoved += result.removed;
|
|
1303
1314
|
}
|
|
1315
|
+
// Distribution chain cleanup reporting
|
|
1316
|
+
if (result.cleanup && result.cleanup.cleaned.length > 0) {
|
|
1317
|
+
for (const label of result.cleanup.cleaned) {
|
|
1318
|
+
log(` ${c.success('\u2713')} Removed ${label}`);
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
for (const failure of (result.cleanup?.failed || [])) {
|
|
1322
|
+
log(` ${c.error('\u2717')} Failed to remove ${failure.label}: ${failure.error}`);
|
|
1323
|
+
}
|
|
1324
|
+
if (result.cleanup && result.cleanup.cleaned.length === 0 && result.cleanup.failed.length === 0) {
|
|
1325
|
+
log(` Distribution chain: ${c.success('\u2713')} clean`);
|
|
1326
|
+
}
|
|
1304
1327
|
if (result.stashCreated) {
|
|
1305
1328
|
log(` Stash created. Recover with: cd ${repo.path} && git stash pop`);
|
|
1306
1329
|
}
|
|
@@ -1324,7 +1347,7 @@ program
|
|
|
1324
1347
|
}
|
|
1325
1348
|
|
|
1326
1349
|
const label = dryRun ? 'would update' : 'updated';
|
|
1327
|
-
let summary = `\nSummary: ${updated} ${label}, ${upToDate} up
|
|
1350
|
+
let summary = `\nSummary: ${updated} ${label}, ${upToDate} up to date, ${pruned} pruned`;
|
|
1328
1351
|
if (dirty > 0) summary += `, ${dirty} dirty (skipped)`;
|
|
1329
1352
|
if (totalRemoved > 0) summary += `, ${totalRemoved} stale files removed`;
|
|
1330
1353
|
console.log(summary);
|
|
@@ -1343,11 +1366,19 @@ program
|
|
|
1343
1366
|
process.exit(getExitCode(error.code));
|
|
1344
1367
|
}
|
|
1345
1368
|
|
|
1369
|
+
const pendingPath = path.join(repoAether, '.update-pending');
|
|
1370
|
+
const hasPending = fs.existsSync(pendingPath);
|
|
1371
|
+
|
|
1372
|
+
if (hasPending) {
|
|
1373
|
+
console.log('Detected incomplete update, re-syncing...');
|
|
1374
|
+
try { fs.unlinkSync(pendingPath); } catch { /* ignore */ }
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1346
1377
|
const currentVersion = readJsonSafe(path.join(repoAether, 'version.json'));
|
|
1347
1378
|
const currentVer = currentVersion ? currentVersion.version : 'unknown';
|
|
1348
1379
|
|
|
1349
|
-
if (!forceFlag && !dryRun && currentVer === sourceVersion) {
|
|
1350
|
-
console.log(c.info(`Already up
|
|
1380
|
+
if (!hasPending && !forceFlag && !dryRun && currentVer === sourceVersion) {
|
|
1381
|
+
console.log(c.info(`Already up to date (v${sourceVersion}).`));
|
|
1351
1382
|
return;
|
|
1352
1383
|
}
|
|
1353
1384
|
|
|
@@ -1371,7 +1402,7 @@ program
|
|
|
1371
1402
|
|
|
1372
1403
|
if (result.status === 'dry-run') {
|
|
1373
1404
|
console.log(`Would update: ${result.from} -> ${result.to}`);
|
|
1374
|
-
console.log(` ${result.system} system files, ${result.commands} command files, ${result.agents} agent files`);
|
|
1405
|
+
console.log(` ${result.system} system files, ${result.commands} command files, ${result.agents} agent files, ${result.agentsClaude} claude agent files`);
|
|
1375
1406
|
if (result.removed > 0) {
|
|
1376
1407
|
console.log(` Would remove ${result.removed} stale files:`);
|
|
1377
1408
|
for (const f of result.removedFiles) console.log(` - ${f}`);
|
|
@@ -1381,11 +1412,23 @@ program
|
|
|
1381
1412
|
}
|
|
1382
1413
|
|
|
1383
1414
|
console.log(c.success(`Updated: ${result.from} -> ${result.to}`));
|
|
1384
|
-
console.log(` ${result.system} system files, ${result.commands} command files, ${result.agents} agent files, ${result.
|
|
1415
|
+
console.log(` ${result.system} system files, ${result.commands} command files, ${result.agents} agent files, ${result.agentsClaude} claude agent files`);
|
|
1385
1416
|
if (result.removed > 0) {
|
|
1386
1417
|
console.log(` Removed ${result.removed} stale files:`);
|
|
1387
1418
|
for (const f of result.removedFiles) console.log(` - ${f}`);
|
|
1388
1419
|
}
|
|
1420
|
+
// Distribution chain cleanup reporting
|
|
1421
|
+
if (result.cleanup && result.cleanup.cleaned.length > 0) {
|
|
1422
|
+
for (const label of result.cleanup.cleaned) {
|
|
1423
|
+
console.log(` ${c.success('\u2713')} Removed ${label}`);
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
for (const failure of (result.cleanup?.failed || [])) {
|
|
1427
|
+
console.log(` ${c.error('\u2717')} Failed to remove ${failure.label}: ${failure.error}`);
|
|
1428
|
+
}
|
|
1429
|
+
if (result.cleanup && result.cleanup.cleaned.length === 0 && result.cleanup.failed.length === 0) {
|
|
1430
|
+
console.log(` Distribution chain: ${c.success('\u2713')} clean`);
|
|
1431
|
+
}
|
|
1389
1432
|
if (result.stashCreated) {
|
|
1390
1433
|
console.log(' Git stash created. Recover with: git stash pop');
|
|
1391
1434
|
}
|
|
@@ -1969,6 +2012,85 @@ program
|
|
|
1969
2012
|
console.log(tree);
|
|
1970
2013
|
}));
|
|
1971
2014
|
|
|
2015
|
+
// Status command - Show colony status
|
|
2016
|
+
program
|
|
2017
|
+
.command('status')
|
|
2018
|
+
.description('Show colony status')
|
|
2019
|
+
.option('-j, --json', 'Output as JSON')
|
|
2020
|
+
.action(wrapCommand(async (options) => {
|
|
2021
|
+
const repoPath = process.cwd();
|
|
2022
|
+
const colonyStatePath = path.join(repoPath, '.aether', 'data', 'COLONY_STATE.json');
|
|
2023
|
+
|
|
2024
|
+
// Check if colony exists
|
|
2025
|
+
if (!fs.existsSync(colonyStatePath)) {
|
|
2026
|
+
console.log(c.warning('No colony found in current directory.'));
|
|
2027
|
+
console.log(c.dim('Run /ant:init to create a new colony, or cd to a project with an existing colony.'));
|
|
2028
|
+
return;
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
// Load colony state
|
|
2032
|
+
let state;
|
|
2033
|
+
try {
|
|
2034
|
+
state = JSON.parse(fs.readFileSync(colonyStatePath, 'utf8'));
|
|
2035
|
+
} catch (err) {
|
|
2036
|
+
console.log(c.error('Could not read colony state.'));
|
|
2037
|
+
console.log(c.dim(`Error: ${err.message}`));
|
|
2038
|
+
console.log(c.dim('The colony state file may be corrupted. Consider running /ant:init to reinitialize.'));
|
|
2039
|
+
return;
|
|
2040
|
+
}
|
|
2041
|
+
|
|
2042
|
+
// JSON output
|
|
2043
|
+
if (options.json) {
|
|
2044
|
+
console.log(JSON.stringify(state, null, 2));
|
|
2045
|
+
return;
|
|
2046
|
+
}
|
|
2047
|
+
|
|
2048
|
+
// Dashboard output
|
|
2049
|
+
console.log(c.header('Colony Status\n'));
|
|
2050
|
+
|
|
2051
|
+
// Goal
|
|
2052
|
+
if (state.goal) {
|
|
2053
|
+
console.log(`${c.queen('Goal:')} ${state.goal}`);
|
|
2054
|
+
}
|
|
2055
|
+
|
|
2056
|
+
// State
|
|
2057
|
+
if (state.state) {
|
|
2058
|
+
const stateDisplay = state.state === 'BUILDING' ? c.success(state.state) :
|
|
2059
|
+
state.state === 'PLANNING' ? c.warning(state.state) :
|
|
2060
|
+
state.state === 'COMPLETED' ? c.success(state.state) :
|
|
2061
|
+
state.state;
|
|
2062
|
+
console.log(`${c.colony('State:')} ${stateDisplay}`);
|
|
2063
|
+
}
|
|
2064
|
+
|
|
2065
|
+
// Phase
|
|
2066
|
+
if (state.current_phase !== undefined) {
|
|
2067
|
+
console.log(`${c.info('Phase:')} ${state.current_phase}`);
|
|
2068
|
+
}
|
|
2069
|
+
|
|
2070
|
+
// Version
|
|
2071
|
+
if (state.version) {
|
|
2072
|
+
console.log(`${c.dim('Version:')} ${state.version}`);
|
|
2073
|
+
}
|
|
2074
|
+
|
|
2075
|
+
// Last updated
|
|
2076
|
+
if (state.last_updated) {
|
|
2077
|
+
const lastUpdated = new Date(state.last_updated);
|
|
2078
|
+
const now = new Date();
|
|
2079
|
+
const hoursAgo = Math.round((now - lastUpdated) / (1000 * 60 * 60));
|
|
2080
|
+
const timeDisplay = hoursAgo < 1 ? 'just now' :
|
|
2081
|
+
hoursAgo < 24 ? `${hoursAgo} hours ago` :
|
|
2082
|
+
`${Math.round(hoursAgo / 24)} days ago`;
|
|
2083
|
+
console.log(`${c.dim('Last updated:')} ${timeDisplay}`);
|
|
2084
|
+
}
|
|
2085
|
+
|
|
2086
|
+
// Event count
|
|
2087
|
+
if (state.events && state.events.length > 0) {
|
|
2088
|
+
console.log(`${c.dim('Events:')} ${state.events.length}`);
|
|
2089
|
+
}
|
|
2090
|
+
|
|
2091
|
+
console.log('');
|
|
2092
|
+
}));
|
|
2093
|
+
|
|
1972
2094
|
// Nestmates command - List sibling colonies
|
|
1973
2095
|
program
|
|
1974
2096
|
.command('nestmates')
|
|
@@ -2242,7 +2364,6 @@ module.exports = {
|
|
|
2242
2364
|
saveCheckpointMetadata,
|
|
2243
2365
|
isUserData,
|
|
2244
2366
|
syncDirWithCleanup,
|
|
2245
|
-
syncSystemFilesWithCleanup,
|
|
2246
2367
|
listFilesRecursive,
|
|
2247
2368
|
cleanEmptyDirs
|
|
2248
2369
|
};
|
package/bin/generate-commands.sh
CHANGED
|
@@ -212,9 +212,9 @@ check_content() {
|
|
|
212
212
|
|
|
213
213
|
if [[ "$drift_count" -gt 0 ]]; then
|
|
214
214
|
echo ""
|
|
215
|
-
|
|
215
|
+
log_warn "Content drift detected in $drift_count file(s) (non-blocking):"
|
|
216
216
|
echo -e "$drift_files"
|
|
217
|
-
|
|
217
|
+
# Content drift is advisory — structural sync is what matters
|
|
218
218
|
fi
|
|
219
219
|
|
|
220
220
|
if [[ "$error_count" -gt 0 ]]; then
|
package/bin/lib/init.js
CHANGED
|
@@ -15,9 +15,10 @@ const path = require('path');
|
|
|
15
15
|
const HOME = process.env.HOME || process.env.USERPROFILE;
|
|
16
16
|
const HUB_DIR = HOME ? path.join(HOME, '.aether') : null;
|
|
17
17
|
const HUB_SYSTEM = HUB_DIR ? path.join(HUB_DIR, 'system') : null;
|
|
18
|
-
const HUB_COMMANDS_CLAUDE =
|
|
19
|
-
const HUB_COMMANDS_OPENCODE =
|
|
20
|
-
const HUB_AGENTS =
|
|
18
|
+
const HUB_COMMANDS_CLAUDE = HUB_SYSTEM ? path.join(HUB_SYSTEM, 'commands', 'claude') : null;
|
|
19
|
+
const HUB_COMMANDS_OPENCODE = HUB_SYSTEM ? path.join(HUB_SYSTEM, 'commands', 'opencode') : null;
|
|
20
|
+
const HUB_AGENTS = HUB_SYSTEM ? path.join(HUB_SYSTEM, 'agents') : null;
|
|
21
|
+
const HUB_AGENTS_CLAUDE = HUB_SYSTEM ? path.join(HUB_SYSTEM, 'agents-claude') : null;
|
|
21
22
|
const HUB_REGISTRY = HUB_DIR ? path.join(HUB_DIR, 'registry.json') : null;
|
|
22
23
|
const HUB_VERSION = HUB_DIR ? path.join(HUB_DIR, 'version.json') : null;
|
|
23
24
|
|
|
@@ -381,6 +382,15 @@ async function initializeRepo(repoPath, options = {}) {
|
|
|
381
382
|
}
|
|
382
383
|
}
|
|
383
384
|
|
|
385
|
+
// Sync claude agents
|
|
386
|
+
if (HUB_AGENTS_CLAUDE && fs.existsSync(HUB_AGENTS_CLAUDE)) {
|
|
387
|
+
const destClaudeAgents = path.join(repoPath, '.claude', 'agents', 'ant');
|
|
388
|
+
const claudeAgentsResult = syncFiles(HUB_AGENTS_CLAUDE, destClaudeAgents);
|
|
389
|
+
if (!quiet && claudeAgentsResult.copied > 0) {
|
|
390
|
+
console.log(` Agents (claude): ${claudeAgentsResult.copied} copied, ${claudeAgentsResult.skipped} skipped`);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
384
394
|
// Create directory structure (in case some weren't created by sync)
|
|
385
395
|
const dirs = [
|
|
386
396
|
path.join(repoPath, '.aether', 'data'),
|