aether-colony 3.1.4 → 3.1.15
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/.claude/commands/ant/archaeology.md +12 -0
- package/.claude/commands/ant/build.md +382 -319
- package/.claude/commands/ant/chaos.md +23 -1
- package/.claude/commands/ant/colonize.md +147 -87
- package/.claude/commands/ant/continue.md +213 -23
- package/.claude/commands/ant/council.md +22 -0
- package/.claude/commands/ant/dream.md +18 -0
- package/.claude/commands/ant/entomb.md +178 -6
- package/.claude/commands/ant/init.md +87 -13
- package/.claude/commands/ant/lay-eggs.md +45 -5
- package/.claude/commands/ant/oracle.md +82 -9
- package/.claude/commands/ant/organize.md +2 -2
- package/.claude/commands/ant/pause-colony.md +86 -28
- package/.claude/commands/ant/phase.md +26 -0
- package/.claude/commands/ant/plan.md +204 -111
- package/.claude/commands/ant/resume-colony.md +23 -1
- package/.claude/commands/ant/resume.md +159 -0
- package/.claude/commands/ant/seal.md +177 -3
- package/.claude/commands/ant/swarm.md +78 -97
- package/.claude/commands/ant/verify-castes.md +7 -7
- package/.claude/commands/ant/watch.md +17 -0
- package/.opencode/agents/aether-ambassador.md +97 -0
- package/.opencode/agents/aether-archaeologist.md +91 -0
- package/.opencode/agents/aether-architect.md +66 -0
- package/.opencode/agents/aether-auditor.md +111 -0
- package/.opencode/agents/aether-builder.md +28 -10
- package/.opencode/agents/aether-chaos.md +98 -0
- package/.opencode/agents/aether-chronicler.md +80 -0
- package/.opencode/agents/aether-gatekeeper.md +107 -0
- package/.opencode/agents/aether-guardian.md +107 -0
- package/.opencode/agents/aether-includer.md +108 -0
- package/.opencode/agents/aether-keeper.md +106 -0
- package/.opencode/agents/aether-measurer.md +119 -0
- package/.opencode/agents/aether-probe.md +91 -0
- package/.opencode/agents/aether-queen.md +72 -19
- package/.opencode/agents/aether-route-setter.md +85 -0
- package/.opencode/agents/aether-sage.md +98 -0
- package/.opencode/agents/aether-scout.md +33 -15
- package/.opencode/agents/aether-surveyor-disciplines.md +334 -0
- package/.opencode/agents/aether-surveyor-nest.md +272 -0
- package/.opencode/agents/aether-surveyor-pathogens.md +209 -0
- package/.opencode/agents/aether-surveyor-provisions.md +277 -0
- package/.opencode/agents/aether-tracker.md +91 -0
- package/.opencode/agents/aether-watcher.md +30 -12
- package/.opencode/agents/aether-weaver.md +87 -0
- package/.opencode/agents/workers.md +1034 -0
- package/.opencode/commands/ant/archaeology.md +44 -26
- package/.opencode/commands/ant/build.md +327 -295
- package/.opencode/commands/ant/chaos.md +32 -4
- package/.opencode/commands/ant/colonize.md +119 -93
- package/.opencode/commands/ant/continue.md +98 -10
- package/.opencode/commands/ant/council.md +28 -0
- package/.opencode/commands/ant/dream.md +24 -0
- package/.opencode/commands/ant/entomb.md +73 -1
- package/.opencode/commands/ant/feedback.md +8 -2
- package/.opencode/commands/ant/flag.md +9 -3
- package/.opencode/commands/ant/flags.md +8 -2
- package/.opencode/commands/ant/focus.md +8 -2
- package/.opencode/commands/ant/help.md +12 -0
- package/.opencode/commands/ant/init.md +49 -4
- package/.opencode/commands/ant/lay-eggs.md +30 -2
- package/.opencode/commands/ant/oracle.md +39 -7
- package/.opencode/commands/ant/organize.md +9 -3
- package/.opencode/commands/ant/pause-colony.md +54 -1
- package/.opencode/commands/ant/phase.md +36 -4
- package/.opencode/commands/ant/plan.md +225 -117
- package/.opencode/commands/ant/redirect.md +8 -2
- package/.opencode/commands/ant/resume-colony.md +51 -26
- package/.opencode/commands/ant/seal.md +76 -0
- package/.opencode/commands/ant/status.md +50 -20
- package/.opencode/commands/ant/swarm.md +108 -104
- package/.opencode/commands/ant/tunnels.md +107 -2
- package/CHANGELOG.md +21 -0
- package/README.md +199 -86
- package/bin/cli.js +142 -25
- package/bin/generate-commands.sh +100 -16
- package/bin/lib/caste-colors.js +5 -5
- package/bin/lib/errors.js +16 -0
- package/bin/lib/file-lock.js +279 -44
- package/bin/lib/state-sync.js +206 -23
- package/bin/lib/update-transaction.js +206 -24
- package/bin/sync-to-runtime.sh +129 -0
- package/package.json +2 -2
- package/runtime/CONTEXT.md +160 -0
- package/runtime/aether-utils.sh +1421 -55
- package/runtime/docs/AETHER-2.0-IMPLEMENTATION-PLAN.md +1343 -0
- package/runtime/docs/AETHER-PHEROMONE-SYSTEM-MASTER-SPEC.md +2642 -0
- package/runtime/docs/PHEROMONE-INJECTION.md +240 -0
- package/runtime/docs/PHEROMONE-INTEGRATION.md +192 -0
- package/runtime/docs/PHEROMONE-SYSTEM-DESIGN.md +426 -0
- package/runtime/docs/README.md +94 -0
- package/runtime/docs/VISUAL-OUTPUT-SPEC.md +219 -0
- package/runtime/docs/biological-reference.md +272 -0
- package/runtime/docs/codebase-review.md +399 -0
- package/runtime/docs/command-sync.md +164 -0
- package/runtime/docs/implementation-learnings.md +89 -0
- package/runtime/docs/known-issues.md +217 -0
- package/runtime/docs/namespace.md +148 -0
- package/runtime/docs/planning-discipline.md +159 -0
- package/runtime/lib/queen-utils.sh +729 -0
- package/runtime/model-profiles.yaml +100 -0
- package/runtime/recover.sh +136 -0
- package/runtime/templates/QUEEN.md.template +79 -0
- package/runtime/utils/atomic-write.sh +5 -5
- package/runtime/utils/chamber-utils.sh +6 -3
- package/runtime/utils/error-handler.sh +200 -0
- package/runtime/utils/queen-to-md.xsl +395 -0
- package/runtime/utils/spawn-tree.sh +428 -0
- package/runtime/utils/spawn-with-model.sh +56 -0
- package/runtime/utils/state-loader.sh +215 -0
- package/runtime/utils/swarm-display.sh +5 -5
- package/runtime/utils/watch-spawn-tree.sh +90 -22
- package/runtime/utils/xml-compose.sh +247 -0
- package/runtime/utils/xml-core.sh +186 -0
- package/runtime/utils/xml-utils.sh +2161 -0
- package/runtime/verification-loop.md +1 -1
- package/runtime/workers-new-castes.md +516 -0
- package/runtime/workers.md +20 -8
- package/.aether/visualizations/anthill-stages/brood-stable.txt +0 -26
- package/.aether/visualizations/anthill-stages/crowned-anthill.txt +0 -30
- package/.aether/visualizations/anthill-stages/first-mound.txt +0 -18
- package/.aether/visualizations/anthill-stages/open-chambers.txt +0 -24
- package/.aether/visualizations/anthill-stages/sealed-chambers.txt +0 -28
- package/.aether/visualizations/anthill-stages/ventilated-nest.txt +0 -27
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
version: '1.0'
|
|
2
|
+
description: Default model assignments for Aether colony workers
|
|
3
|
+
profile: default
|
|
4
|
+
worker_models:
|
|
5
|
+
prime: glm-5
|
|
6
|
+
archaeologist: glm-5
|
|
7
|
+
architect: glm-5
|
|
8
|
+
oracle: minimax-2.5
|
|
9
|
+
route_setter: kimi-k2.5
|
|
10
|
+
builder: kimi-k2.5
|
|
11
|
+
watcher: kimi-k2.5
|
|
12
|
+
scout: kimi-k2.5
|
|
13
|
+
chaos: kimi-k2.5
|
|
14
|
+
colonizer: kimi-k2.5
|
|
15
|
+
model_metadata:
|
|
16
|
+
glm-5:
|
|
17
|
+
description: '744B MoE model (40B active), long-horizon agentic engineering'
|
|
18
|
+
provider: z_ai
|
|
19
|
+
capabilities:
|
|
20
|
+
- planning
|
|
21
|
+
- coordination
|
|
22
|
+
- long_context
|
|
23
|
+
- complex_reasoning
|
|
24
|
+
- agentic_workflows
|
|
25
|
+
context_window: 200000
|
|
26
|
+
speed: medium
|
|
27
|
+
cost_tier: high
|
|
28
|
+
best_for:
|
|
29
|
+
- 'Long-horizon task execution (tested: 1 year business simulation)'
|
|
30
|
+
- Strategic coordination and planning
|
|
31
|
+
- Historical pattern analysis across large contexts
|
|
32
|
+
- Multi-step autonomous workflows
|
|
33
|
+
minimax-2.5:
|
|
34
|
+
description: Frontier model for architectural planning and agentic tool use
|
|
35
|
+
provider: minimax
|
|
36
|
+
capabilities:
|
|
37
|
+
- system_design
|
|
38
|
+
- architecture
|
|
39
|
+
- browse
|
|
40
|
+
- search
|
|
41
|
+
- task_decomposition
|
|
42
|
+
context_window: 200000
|
|
43
|
+
speed: fast
|
|
44
|
+
cost_tier: medium
|
|
45
|
+
best_for:
|
|
46
|
+
- Architectural-level planning and system design
|
|
47
|
+
- Research with browse/search (76.3% BrowseComp)
|
|
48
|
+
- Efficient task decomposition (20% fewer search rounds)
|
|
49
|
+
- Full-stack development (80.2% SWE-Bench Verified)
|
|
50
|
+
kimi-k2.5:
|
|
51
|
+
description: '1T MoE model (32B active), multimodal agent with swarm capabilities'
|
|
52
|
+
provider: kimi
|
|
53
|
+
capabilities:
|
|
54
|
+
- coding
|
|
55
|
+
- multimodal
|
|
56
|
+
- agent_swarm
|
|
57
|
+
- visual_coding
|
|
58
|
+
- validation
|
|
59
|
+
context_window: 256000
|
|
60
|
+
speed: fast
|
|
61
|
+
cost_tier: low
|
|
62
|
+
best_for:
|
|
63
|
+
- Code generation and refactoring (76.8% SWE-Bench)
|
|
64
|
+
- Visual coding (screenshots to code)
|
|
65
|
+
- Parallel exploration (up to 100 sub-agents)
|
|
66
|
+
- Validation and testing workflows
|
|
67
|
+
task_routing:
|
|
68
|
+
default_model: kimi-k2.5
|
|
69
|
+
complexity_indicators:
|
|
70
|
+
complex:
|
|
71
|
+
keywords:
|
|
72
|
+
- design
|
|
73
|
+
- architecture
|
|
74
|
+
- plan
|
|
75
|
+
- coordinate
|
|
76
|
+
- synthesize
|
|
77
|
+
- strategize
|
|
78
|
+
- optimize
|
|
79
|
+
model: glm-5
|
|
80
|
+
simple:
|
|
81
|
+
keywords:
|
|
82
|
+
- implement
|
|
83
|
+
- code
|
|
84
|
+
- refactor
|
|
85
|
+
- write
|
|
86
|
+
- create
|
|
87
|
+
model: kimi-k2.5
|
|
88
|
+
validate:
|
|
89
|
+
keywords:
|
|
90
|
+
- test
|
|
91
|
+
- validate
|
|
92
|
+
- verify
|
|
93
|
+
- check
|
|
94
|
+
- review
|
|
95
|
+
- audit
|
|
96
|
+
model: minimax-2.5
|
|
97
|
+
proxy:
|
|
98
|
+
endpoint: 'http://localhost:4000'
|
|
99
|
+
auth_token: ${LITELLM_AUTH_TOKEN:-sk-litellm-local}
|
|
100
|
+
health_check: 'http://localhost:4000/health'
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Aether v3.1 Recovery Script
|
|
3
|
+
# Run this after reading RECOVERY-PLAN.md
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
echo "╔══════════════════════════════════════════════════════════════╗"
|
|
8
|
+
echo "║ AETHER v3.1 RECOVERY - RUNNING SYNC ║"
|
|
9
|
+
echo "╚══════════════════════════════════════════════════════════════╝"
|
|
10
|
+
echo ""
|
|
11
|
+
|
|
12
|
+
# Colors
|
|
13
|
+
RED='\033[0;31m'
|
|
14
|
+
GREEN='\033[0;32m'
|
|
15
|
+
YELLOW='\033[1;33m'
|
|
16
|
+
NC='\033[0m' # No Color
|
|
17
|
+
|
|
18
|
+
# Step 1: Check if we're in the right place
|
|
19
|
+
if [ ! -f "package.json" ] || [ ! -d ".aether" ] || [ ! -d "runtime" ]; then
|
|
20
|
+
echo -e "${RED}ERROR: Must run from Aether repo root${NC}"
|
|
21
|
+
exit 1
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# Step 2: Commit any staged changes
|
|
25
|
+
echo "Step 1: Checking git status..."
|
|
26
|
+
if ! git diff --cached --quiet; then
|
|
27
|
+
echo "Found staged changes. Committing..."
|
|
28
|
+
git commit -m "recovery: staged changes before sync"
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# Step 3: Sync runtime/ from .aether/
|
|
32
|
+
echo ""
|
|
33
|
+
echo "Step 2: Syncing runtime/ from .aether/..."
|
|
34
|
+
echo "------------------------------------------"
|
|
35
|
+
|
|
36
|
+
# Core files
|
|
37
|
+
echo " → workers.md"
|
|
38
|
+
cp .aether/workers.md runtime/workers.md
|
|
39
|
+
|
|
40
|
+
echo " → aether-utils.sh"
|
|
41
|
+
cp .aether/aether-utils.sh runtime/aether-utils.sh
|
|
42
|
+
|
|
43
|
+
echo " → verification-loop.md"
|
|
44
|
+
cp .aether/verification-loop.md runtime/verification-loop.md 2>/dev/null || echo " (skipped - not in .aether)"
|
|
45
|
+
|
|
46
|
+
# Utils - sync all files
|
|
47
|
+
echo ""
|
|
48
|
+
echo " → utilities/"
|
|
49
|
+
for file in .aether/utils/*.sh; do
|
|
50
|
+
if [ -f "$file" ]; then
|
|
51
|
+
filename=$(basename "$file")
|
|
52
|
+
echo " copying $filename"
|
|
53
|
+
cp "$file" "runtime/utils/$filename"
|
|
54
|
+
fi
|
|
55
|
+
done
|
|
56
|
+
|
|
57
|
+
# Docs - ensure runtime/docs/ exists and has files
|
|
58
|
+
if [ -d ".aether/docs" ]; then
|
|
59
|
+
echo ""
|
|
60
|
+
echo " → docs/"
|
|
61
|
+
mkdir -p runtime/docs
|
|
62
|
+
for file in .aether/docs/*.md .aether/docs/*.json 2>/dev/null; do
|
|
63
|
+
if [ -f "$file" ]; then
|
|
64
|
+
filename=$(basename "$file")
|
|
65
|
+
echo " copying $filename"
|
|
66
|
+
cp "$file" "runtime/docs/$filename"
|
|
67
|
+
fi
|
|
68
|
+
done
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
# Step 4: Verify the sync
|
|
72
|
+
echo ""
|
|
73
|
+
echo "Step 3: Verifying sync..."
|
|
74
|
+
echo "------------------------------------------"
|
|
75
|
+
|
|
76
|
+
# Check emoji section
|
|
77
|
+
if grep -q "Caste Emoji Mapping:" runtime/workers.md; then
|
|
78
|
+
echo -e "${GREEN} ✓ workers.md has emoji section${NC}"
|
|
79
|
+
else
|
|
80
|
+
echo -e "${RED} ✗ workers.md MISSING emoji section${NC}"
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
# Check get_caste_emoji
|
|
84
|
+
if grep -q "get_caste_emoji()" runtime/aether-utils.sh; then
|
|
85
|
+
echo -e "${GREEN} ✓ aether-utils.sh has get_caste_emoji${NC}"
|
|
86
|
+
else
|
|
87
|
+
echo -e "${RED} ✗ aether-utils.sh MISSING get_caste_emoji${NC}"
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
# Count utils files
|
|
91
|
+
RUNTIME_UTILS=$(ls runtime/utils/*.sh 2>/dev/null | wc -l)
|
|
92
|
+
AETHER_UTILS=$(ls .aether/utils/*.sh 2>/dev/null | wc -l)
|
|
93
|
+
echo " → runtime/utils: $RUNTIME_UTILS files"
|
|
94
|
+
echo " → .aether/utils: $AETHER_UTILS files"
|
|
95
|
+
|
|
96
|
+
if [ "$RUNTIME_UTILS" -eq "$AETHER_UTILS" ]; then
|
|
97
|
+
echo -e "${GREEN} ✓ Utils counts match${NC}"
|
|
98
|
+
else
|
|
99
|
+
echo -e "${YELLOW} ⚠ Utils counts differ (may be okay if some are .aether-specific)${NC}"
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
# Step 5: Stage the changes
|
|
103
|
+
echo ""
|
|
104
|
+
echo "Step 4: Staging changes..."
|
|
105
|
+
git add runtime/
|
|
106
|
+
|
|
107
|
+
# Show status
|
|
108
|
+
echo ""
|
|
109
|
+
echo "Git status after sync:"
|
|
110
|
+
git status --short runtime/
|
|
111
|
+
|
|
112
|
+
# Step 6: Instructions
|
|
113
|
+
echo ""
|
|
114
|
+
echo "╔══════════════════════════════════════════════════════════════╗"
|
|
115
|
+
echo "║ RECOVERY SYNC COMPLETE ║"
|
|
116
|
+
echo "╚══════════════════════════════════════════════════════════════╝"
|
|
117
|
+
echo ""
|
|
118
|
+
echo "Next steps:"
|
|
119
|
+
echo ""
|
|
120
|
+
echo " 1. Review the changes:"
|
|
121
|
+
echo " git diff --cached runtime/"
|
|
122
|
+
echo ""
|
|
123
|
+
echo " 2. Commit the sync:"
|
|
124
|
+
echo " git commit -m 'sync: runtime/ updated from working .aether/'"
|
|
125
|
+
echo ""
|
|
126
|
+
echo " 3. Reinstall to update hub:"
|
|
127
|
+
echo " npm install -g ."
|
|
128
|
+
echo ""
|
|
129
|
+
echo " 4. Verify hub updated:"
|
|
130
|
+
echo " grep 'Caste Emoji Mapping:' ~/.aether/system/workers.md"
|
|
131
|
+
echo ""
|
|
132
|
+
echo " 5. Test in this repo:"
|
|
133
|
+
echo " /ant:init 'Test recovery'"
|
|
134
|
+
echo ""
|
|
135
|
+
echo "Remember: .aether/ is the SOURCE OF TRUTH. runtime/ is auto-populated by bin/sync-to-runtime.sh"
|
|
136
|
+
echo ""
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# QUEEN.md — Colony Wisdom
|
|
2
|
+
|
|
3
|
+
> Last evolved: {TIMESTAMP}
|
|
4
|
+
> Colonies contributed: 0
|
|
5
|
+
> Wisdom version: 1.0.0
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 📜 Philosophies
|
|
10
|
+
|
|
11
|
+
Core beliefs that guide all colony work. These are validated through repeated successful application across multiple colonies.
|
|
12
|
+
|
|
13
|
+
*No philosophies recorded yet. Philosophies are promoted from PHILOSOPHY pheromones after 5+ validations.*
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 🧭 Patterns
|
|
18
|
+
|
|
19
|
+
Validated approaches that consistently work. These represent discovered best practices that have proven themselves in the field.
|
|
20
|
+
|
|
21
|
+
*No patterns recorded yet. Patterns are promoted from PATTERN pheromones after 3+ validations.*
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## ⚠️ Redirects
|
|
26
|
+
|
|
27
|
+
Anti-patterns to avoid. These represent approaches that have caused problems and should be redirected away from.
|
|
28
|
+
|
|
29
|
+
*No redirects recorded yet. Redirects are promoted from REDIRECT pheromones after 2+ triggers.*
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 🔧 Stack Wisdom
|
|
34
|
+
|
|
35
|
+
Technology-specific insights and constraints detected through codebase analysis.
|
|
36
|
+
|
|
37
|
+
*No stack wisdom recorded yet. Stack wisdom is auto-populated by `/ant:colonize`.*
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 🏛️ Decrees
|
|
42
|
+
|
|
43
|
+
User-mandated rules that override other guidance. These represent explicit directives from the Queen.
|
|
44
|
+
|
|
45
|
+
*No decrees recorded yet. Decrees are added via `/ant:decree "<rule>"`.*
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 📊 Evolution Log
|
|
50
|
+
|
|
51
|
+
Track how wisdom has evolved over time.
|
|
52
|
+
|
|
53
|
+
| Date | Colony | Change | Details |
|
|
54
|
+
|------|--------|--------|---------|
|
|
55
|
+
| {TIMESTAMP} | system | initialized | QUEEN.md created from template |
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
<!-- METADATA
|
|
60
|
+
{
|
|
61
|
+
"version": "1.0.0",
|
|
62
|
+
"last_evolved": "{TIMESTAMP}",
|
|
63
|
+
"colonies_contributed": [],
|
|
64
|
+
"promotion_thresholds": {
|
|
65
|
+
"philosophy": 5,
|
|
66
|
+
"pattern": 3,
|
|
67
|
+
"redirect": 2,
|
|
68
|
+
"stack": 1,
|
|
69
|
+
"decree": 0
|
|
70
|
+
},
|
|
71
|
+
"stats": {
|
|
72
|
+
"total_philosophies": 0,
|
|
73
|
+
"total_patterns": 0,
|
|
74
|
+
"total_redirects": 0,
|
|
75
|
+
"total_stack_entries": 0,
|
|
76
|
+
"total_decrees": 0
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
-->
|
|
@@ -62,6 +62,11 @@ atomic_write() {
|
|
|
62
62
|
return 1
|
|
63
63
|
fi
|
|
64
64
|
|
|
65
|
+
# Create backup if target exists (do this BEFORE validation to avoid race condition)
|
|
66
|
+
if [ -f "$target_file" ]; then
|
|
67
|
+
create_backup "$target_file"
|
|
68
|
+
fi
|
|
69
|
+
|
|
65
70
|
# Validate JSON if it's a JSON file
|
|
66
71
|
if [[ "$target_file" == *.json ]]; then
|
|
67
72
|
if ! python3 -c "import json; json.load(open('$temp_file'))" 2>/dev/null; then
|
|
@@ -71,11 +76,6 @@ atomic_write() {
|
|
|
71
76
|
fi
|
|
72
77
|
fi
|
|
73
78
|
|
|
74
|
-
# Create backup if target exists
|
|
75
|
-
if [ -f "$target_file" ]; then
|
|
76
|
-
create_backup "$target_file"
|
|
77
|
-
fi
|
|
78
|
-
|
|
79
79
|
# Atomic rename (overwrites target if exists)
|
|
80
80
|
if ! mv "$temp_file" "$target_file"; then
|
|
81
81
|
echo "Failed to rename temp file to target: $target_file"
|
|
@@ -15,9 +15,12 @@ set -euo pipefail
|
|
|
15
15
|
LOCK_ACQUIRED=${LOCK_ACQUIRED:-false}
|
|
16
16
|
CURRENT_LOCK=${CURRENT_LOCK:-""}
|
|
17
17
|
|
|
18
|
-
# Get script directory for sourcing
|
|
19
|
-
|
|
20
|
-
AETHER_ROOT="$(cd "$
|
|
18
|
+
# Get script directory for sourcing (preserve parent SCRIPT_DIR if set)
|
|
19
|
+
__chamber_utils_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
20
|
+
AETHER_ROOT="$(cd "$__chamber_utils_dir/../.." && pwd 2>/dev/null || echo "$__chamber_utils_dir/../..")"
|
|
21
|
+
|
|
22
|
+
# Use parent SCRIPT_DIR if available, otherwise use local
|
|
23
|
+
SCRIPT_DIR="${SCRIPT_DIR:-$__chamber_utils_dir}"
|
|
21
24
|
|
|
22
25
|
# Source atomic-write for safe file operations
|
|
23
26
|
[[ -f "$SCRIPT_DIR/atomic-write.sh" ]] && source "$SCRIPT_DIR/atomic-write.sh"
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Aether Colony Error Handler Module
|
|
3
|
+
# Structured JSON error handling for bash utilities
|
|
4
|
+
#
|
|
5
|
+
# Usage: source "$SCRIPT_DIR/utils/error-handler.sh"
|
|
6
|
+
#
|
|
7
|
+
# Provides consistent error format between Node.js CLI and bash utilities
|
|
8
|
+
|
|
9
|
+
# --- Error Code Constants (matching Node.js error codes) ---
|
|
10
|
+
E_UNKNOWN="E_UNKNOWN"
|
|
11
|
+
E_HUB_NOT_FOUND="E_HUB_NOT_FOUND"
|
|
12
|
+
E_REPO_NOT_INITIALIZED="E_REPO_NOT_INITIALIZED"
|
|
13
|
+
E_FILE_NOT_FOUND="E_FILE_NOT_FOUND"
|
|
14
|
+
E_JSON_INVALID="E_JSON_INVALID"
|
|
15
|
+
E_LOCK_FAILED="E_LOCK_FAILED"
|
|
16
|
+
E_GIT_ERROR="E_GIT_ERROR"
|
|
17
|
+
E_VALIDATION_FAILED="E_VALIDATION_FAILED"
|
|
18
|
+
E_FEATURE_UNAVAILABLE="E_FEATURE_UNAVAILABLE"
|
|
19
|
+
E_BASH_ERROR="E_BASH_ERROR"
|
|
20
|
+
|
|
21
|
+
# --- Recovery Suggestion Functions (internal, prefixed with _) ---
|
|
22
|
+
_recovery_hub_not_found() { echo '"Run: aether install"'; }
|
|
23
|
+
_recovery_repo_not_init() { echo '"Run /ant:init in this repo first"'; }
|
|
24
|
+
_recovery_file_not_found() { echo '"Check file path and permissions"'; }
|
|
25
|
+
_recovery_json_invalid() { echo '"Validate JSON syntax"'; }
|
|
26
|
+
_recovery_lock_failed() { echo '"Wait for other operations to complete"'; }
|
|
27
|
+
_recovery_git_error() { echo '"Check git status and resolve conflicts"'; }
|
|
28
|
+
_recovery_default() { echo 'null'; }
|
|
29
|
+
|
|
30
|
+
# Get recovery suggestion based on error code
|
|
31
|
+
_get_recovery() {
|
|
32
|
+
local code="$1"
|
|
33
|
+
case "$code" in
|
|
34
|
+
"$E_HUB_NOT_FOUND") _recovery_hub_not_found ;;
|
|
35
|
+
"$E_REPO_NOT_INITIALIZED") _recovery_repo_not_init ;;
|
|
36
|
+
"$E_FILE_NOT_FOUND") _recovery_file_not_found ;;
|
|
37
|
+
"$E_JSON_INVALID") _recovery_json_invalid ;;
|
|
38
|
+
"$E_LOCK_FAILED") _recovery_lock_failed ;;
|
|
39
|
+
"$E_GIT_ERROR") _recovery_git_error ;;
|
|
40
|
+
*) _recovery_default ;;
|
|
41
|
+
esac
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
# --- Enhanced json_err function ---
|
|
45
|
+
# Signature: json_err [code] [message] [details] [recovery]
|
|
46
|
+
# All parameters optional with sensible defaults
|
|
47
|
+
json_err() {
|
|
48
|
+
local code="${1:-$E_UNKNOWN}"
|
|
49
|
+
local message="${2:-An unknown error occurred}"
|
|
50
|
+
local details="${3:-null}"
|
|
51
|
+
local recovery="${4:-}"
|
|
52
|
+
local timestamp
|
|
53
|
+
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
54
|
+
|
|
55
|
+
# Get recovery suggestion if not provided
|
|
56
|
+
if [[ -z "$recovery" ]]; then
|
|
57
|
+
recovery=$(_get_recovery "$code")
|
|
58
|
+
else
|
|
59
|
+
# Escape and quote the recovery string
|
|
60
|
+
recovery=$(echo "$recovery" | sed 's/"/\\"/g' | tr '\n' ' ')
|
|
61
|
+
recovery="\"$recovery\""
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
# Escape message for JSON
|
|
65
|
+
local escaped_message
|
|
66
|
+
escaped_message=$(echo "$message" | sed 's/"/\\"/g' | tr '\n' ' ')
|
|
67
|
+
|
|
68
|
+
# Build details JSON
|
|
69
|
+
local details_json
|
|
70
|
+
if [[ "$details" == "null" || -z "$details" ]]; then
|
|
71
|
+
details_json="null"
|
|
72
|
+
else
|
|
73
|
+
details_json="$details"
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
# Output structured JSON to stderr
|
|
77
|
+
printf '{"ok":false,"error":{"code":"%s","message":"%s","details":%s,"recovery":%s,"timestamp":"%s"}}\n' \
|
|
78
|
+
"$code" "$escaped_message" "$details_json" "$recovery" "$timestamp" >&2
|
|
79
|
+
|
|
80
|
+
# Log to activity.log (best effort)
|
|
81
|
+
if [[ -n "${DATA_DIR:-}" ]]; then
|
|
82
|
+
echo "[$timestamp] ERROR $code: $escaped_message" >> "$DATA_DIR/activity.log" 2>/dev/null || true
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
exit 1
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
# --- json_warn function for non-fatal warnings ---
|
|
89
|
+
# Signature: json_warn [code] [message]
|
|
90
|
+
json_warn() {
|
|
91
|
+
local code="${1:-W_UNKNOWN}"
|
|
92
|
+
local message="${2:-Warning}"
|
|
93
|
+
local timestamp
|
|
94
|
+
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
95
|
+
|
|
96
|
+
# Escape message for JSON
|
|
97
|
+
local escaped_message
|
|
98
|
+
escaped_message=$(echo "$message" | sed 's/"/\\"/g' | tr '\n' ' ')
|
|
99
|
+
|
|
100
|
+
# Output warning JSON to stdout (not stderr - this is non-fatal)
|
|
101
|
+
printf '{"ok":true,"warning":{"code":"%s","message":"%s","timestamp":"%s"}}\n' \
|
|
102
|
+
"$code" "$escaped_message" "$timestamp"
|
|
103
|
+
|
|
104
|
+
# Log to activity.log (best effort)
|
|
105
|
+
if [[ -n "${DATA_DIR:-}" ]]; then
|
|
106
|
+
echo "[$timestamp] WARN $code: $escaped_message" >> "$DATA_DIR/activity.log" 2>/dev/null || true
|
|
107
|
+
fi
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
# --- error_handler function for trap ERR ---
|
|
111
|
+
# Captures: line number, command, exit code
|
|
112
|
+
# Usage: trap 'error_handler ${LINENO} "$BASH_COMMAND" $?' ERR
|
|
113
|
+
error_handler() {
|
|
114
|
+
local line_num="${1:-unknown}"
|
|
115
|
+
local command="${2:-unknown}"
|
|
116
|
+
local exit_code="${3:-1}"
|
|
117
|
+
local timestamp
|
|
118
|
+
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
119
|
+
|
|
120
|
+
# Escape command for JSON
|
|
121
|
+
local escaped_command
|
|
122
|
+
escaped_command=$(echo "$command" | sed 's/"/\\"/g' | tr '\n' ' ')
|
|
123
|
+
|
|
124
|
+
# Build details JSON
|
|
125
|
+
local details
|
|
126
|
+
details="{\"line\":$line_num,\"command\":\"$escaped_command\",\"exit_code\":$exit_code}"
|
|
127
|
+
|
|
128
|
+
# Output structured JSON to stderr
|
|
129
|
+
printf '{"ok":false,"error":{"code":"%s","message":"Bash command failed","details":%s,"recovery":%s,"timestamp":"%s"}}\n' \
|
|
130
|
+
"$E_BASH_ERROR" "$details" "$(_recovery_default)" "$timestamp" >&2
|
|
131
|
+
|
|
132
|
+
# Log to activity.log (best effort)
|
|
133
|
+
if [[ -n "${DATA_DIR:-}" ]]; then
|
|
134
|
+
echo "[$timestamp] ERROR $E_BASH_ERROR: Command failed at line $line_num (exit $exit_code)" >> "$DATA_DIR/activity.log" 2>/dev/null || true
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
exit 1
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
# --- Feature flag functions for graceful degradation ---
|
|
141
|
+
# Using simple variables for bash 3.2+ compatibility (no associative arrays)
|
|
142
|
+
|
|
143
|
+
# Track disabled features as colon-separated list: "feature1:reason1|feature2:reason2"
|
|
144
|
+
_FEATURES_DISABLED=""
|
|
145
|
+
|
|
146
|
+
# Enable a feature (remove from disabled list if present)
|
|
147
|
+
feature_enable() {
|
|
148
|
+
local name="$1"
|
|
149
|
+
# Remove from disabled list if present
|
|
150
|
+
_FEATURES_DISABLED=$(echo "$_FEATURES_DISABLED" | sed "s/:$name:[^|]*//g" | sed 's/^|//;s/|$//')
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
# Disable a feature with reason
|
|
154
|
+
feature_disable() {
|
|
155
|
+
local name="$1"
|
|
156
|
+
local reason="${2:-disabled}"
|
|
157
|
+
# Remove existing entry if present, then add new
|
|
158
|
+
_FEATURES_DISABLED=$(echo "$_FEATURES_DISABLED" | sed "s/:$name:[^|]*//g")
|
|
159
|
+
if [[ -z "$_FEATURES_DISABLED" ]]; then
|
|
160
|
+
_FEATURES_DISABLED=":$name:$reason"
|
|
161
|
+
else
|
|
162
|
+
_FEATURES_DISABLED="${_FEATURES_DISABLED}|:$name:$reason"
|
|
163
|
+
fi
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
# Check if feature is enabled (returns 0 if enabled, 1 if disabled)
|
|
167
|
+
feature_enabled() {
|
|
168
|
+
local name="$1"
|
|
169
|
+
if echo "$_FEATURES_DISABLED" | grep -q ":$name:"; then
|
|
170
|
+
return 1
|
|
171
|
+
fi
|
|
172
|
+
return 0
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
# Get reason for feature being disabled
|
|
176
|
+
_feature_reason() {
|
|
177
|
+
local name="$1"
|
|
178
|
+
echo "$_FEATURES_DISABLED" | grep -o ":$name:[^|]*" | sed "s/:$name://" || echo "unknown"
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
# Log degradation warning
|
|
182
|
+
feature_log_degradation() {
|
|
183
|
+
local name="$1"
|
|
184
|
+
local reason="${2:-}"
|
|
185
|
+
if [[ -z "$reason" ]]; then
|
|
186
|
+
reason=$(_feature_reason "$name")
|
|
187
|
+
fi
|
|
188
|
+
json_warn "W_DEGRADED" "Feature '$name' is disabled: $reason"
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
# --- Export all functions and variables ---
|
|
192
|
+
export -f json_err json_warn error_handler
|
|
193
|
+
export -f feature_enable feature_disable feature_enabled feature_log_degradation
|
|
194
|
+
export -f _get_recovery _recovery_hub_not_found _recovery_repo_not_init
|
|
195
|
+
export -f _recovery_file_not_found _recovery_json_invalid _recovery_lock_failed
|
|
196
|
+
export -f _recovery_git_error _recovery_default _feature_reason
|
|
197
|
+
export E_UNKNOWN E_HUB_NOT_FOUND E_REPO_NOT_INITIALIZED E_FILE_NOT_FOUND
|
|
198
|
+
export E_JSON_INVALID E_LOCK_FAILED E_GIT_ERROR E_VALIDATION_FAILED
|
|
199
|
+
export E_FEATURE_UNAVAILABLE E_BASH_ERROR
|
|
200
|
+
export _FEATURES_DISABLED
|