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
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# XML Conversion Utilities
|
|
3
|
+
# Bidirectional JSON/XML conversion and document merging
|
|
4
|
+
#
|
|
5
|
+
# Usage: source .aether/utils/xml-convert.sh
|
|
6
|
+
# xml-to-json <xml_file> [--pretty]
|
|
7
|
+
# json-to-xml <json_file> [root_element]
|
|
8
|
+
# xml-merge <output_file> <main_xml_file>
|
|
9
|
+
# xml-convert-detect-format <file>
|
|
10
|
+
|
|
11
|
+
set -euo pipefail
|
|
12
|
+
|
|
13
|
+
# Source xml-core.sh for JSON helpers and tool detection
|
|
14
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
15
|
+
source "$SCRIPT_DIR/xml-core.sh"
|
|
16
|
+
|
|
17
|
+
# Additional tool detection for conversion
|
|
18
|
+
XML2JSON_AVAILABLE=false
|
|
19
|
+
if command -v xml2json >/dev/null 2>&1; then
|
|
20
|
+
XML2JSON_AVAILABLE=true
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
# ============================================================================
|
|
24
|
+
# Format Detection
|
|
25
|
+
# ============================================================================
|
|
26
|
+
|
|
27
|
+
# xml-convert-detect-format: Detect if file is XML or JSON
|
|
28
|
+
# Usage: xml-convert-detect-format <file>
|
|
29
|
+
# Returns: {"ok":true,"result":{"format":"xml|json|unknown","confidence":"high|medium|low"}}
|
|
30
|
+
xml-convert-detect-format() {
|
|
31
|
+
local file="${1:-}"
|
|
32
|
+
|
|
33
|
+
[[ -z "$file" ]] && { xml_json_err "MISSING_ARG" "Missing file argument"; return 1; }
|
|
34
|
+
[[ -f "$file" ]] || { xml_json_err "FILE_NOT_FOUND" "File not found: $file"; return 1; }
|
|
35
|
+
|
|
36
|
+
# Read first 1KB for analysis
|
|
37
|
+
local header
|
|
38
|
+
header=$(head -c 1024 "$file" 2>/dev/null || head -c 1024 < "$file")
|
|
39
|
+
|
|
40
|
+
# Check for XML signatures
|
|
41
|
+
if echo "$header" | grep -qE '^\s*<\?xml\s+version'; then
|
|
42
|
+
xml_json_ok '{"format":"xml","confidence":"high","signature":"xml_declaration"}'
|
|
43
|
+
return 0
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
if echo "$header" | grep -qE '^\s*<[a-zA-Z_][a-zA-Z0-9_]*[\s>]'; then
|
|
47
|
+
xml_json_ok '{"format":"xml","confidence":"medium","signature":"root_element"}'
|
|
48
|
+
return 0
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# Check for JSON signatures
|
|
52
|
+
if echo "$header" | grep -qE '^\s*(\{|\[)'; then
|
|
53
|
+
# Verify it's valid JSON
|
|
54
|
+
if jq empty "$file" 2>/dev/null; then
|
|
55
|
+
xml_json_ok '{"format":"json","confidence":"high","signature":"valid_json"}'
|
|
56
|
+
return 0
|
|
57
|
+
else
|
|
58
|
+
xml_json_ok '{"format":"json","confidence":"low","signature":"json_like","note":"Invalid JSON syntax"}'
|
|
59
|
+
return 0
|
|
60
|
+
fi
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
xml_json_ok '{"format":"unknown","confidence":"low","signature":"none"}'
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
# ============================================================================
|
|
67
|
+
# XML to JSON Conversion
|
|
68
|
+
# ============================================================================
|
|
69
|
+
|
|
70
|
+
# xml-to-json: Convert XML to JSON format
|
|
71
|
+
# Usage: xml-to-json <xml_file> [--pretty]
|
|
72
|
+
# Returns: {"ok":true,"result":{"json":"...","format":"object"}}
|
|
73
|
+
xml-to-json() {
|
|
74
|
+
local xml_file="${1:-}"
|
|
75
|
+
local pretty=false
|
|
76
|
+
|
|
77
|
+
# Parse optional arguments
|
|
78
|
+
shift || true
|
|
79
|
+
while [[ $# -gt 0 ]]; do
|
|
80
|
+
case "$1" in
|
|
81
|
+
--pretty) pretty=true; shift ;;
|
|
82
|
+
*) shift ;;
|
|
83
|
+
esac
|
|
84
|
+
done
|
|
85
|
+
|
|
86
|
+
[[ -z "$xml_file" ]] && { xml_json_err "MISSING_ARG" "Missing XML file argument"; return 1; }
|
|
87
|
+
[[ -f "$xml_file" ]] || { xml_json_err "FILE_NOT_FOUND" "XML file not found: $xml_file"; return 1; }
|
|
88
|
+
|
|
89
|
+
# Check well-formedness first
|
|
90
|
+
local well_formed_result
|
|
91
|
+
well_formed_result=$(xml-well-formed "$xml_file" 2>/dev/null)
|
|
92
|
+
if ! echo "$well_formed_result" | jq -e '.result.well_formed' >/dev/null 2>&1; then
|
|
93
|
+
xml_json_err "PARSE_ERROR" "XML is not well-formed"
|
|
94
|
+
return 1
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
# Try xml2json if available (npm package)
|
|
98
|
+
if [[ "$XML2JSON_AVAILABLE" == "true" ]]; then
|
|
99
|
+
local json_output
|
|
100
|
+
if json_output=$(xml2json "$xml_file" 2>/dev/null); then
|
|
101
|
+
if [[ "$pretty" == "true" ]]; then
|
|
102
|
+
json_output=$(echo "$json_output" | jq '.')
|
|
103
|
+
fi
|
|
104
|
+
local escaped_json
|
|
105
|
+
escaped_json=$(echo "$json_output" | jq -Rs '.')
|
|
106
|
+
xml_json_ok "{\"format\":\"object\",\"json\":$escaped_json}"
|
|
107
|
+
return 0
|
|
108
|
+
fi
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
# Fallback: Use xsltproc with built-in XSLT
|
|
112
|
+
if [[ "$XSLTPROC_AVAILABLE" == "true" ]]; then
|
|
113
|
+
local xslt_script
|
|
114
|
+
xslt_script=$(cat << 'XSLT'
|
|
115
|
+
<?xml version="1.0"?>
|
|
116
|
+
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
117
|
+
<xsl:output method="text"/>
|
|
118
|
+
<xsl:template match="/">
|
|
119
|
+
<xsl:text>{"root":</xsl:text>
|
|
120
|
+
<xsl:apply-templates select="*"/>
|
|
121
|
+
<xsl:text>}</xsl:text>
|
|
122
|
+
</xsl:template>
|
|
123
|
+
<xsl:template match="*">
|
|
124
|
+
<xsl:text>{"</xsl:text>
|
|
125
|
+
<xsl:value-of select="name()"/>
|
|
126
|
+
<xsl:text>":</xsl:text>
|
|
127
|
+
<xsl:choose>
|
|
128
|
+
<xsl:when test="count(*) > 0">
|
|
129
|
+
<xsl:text>[</xsl:text>
|
|
130
|
+
<xsl:apply-templates select="*"/>
|
|
131
|
+
<xsl:text>]</xsl:text>
|
|
132
|
+
</xsl:when>
|
|
133
|
+
<xsl:otherwise>
|
|
134
|
+
<xsl:text>"</xsl:text>
|
|
135
|
+
<xsl:value-of select="."/>
|
|
136
|
+
<xsl:text>"</xsl:text>
|
|
137
|
+
</xsl:otherwise>
|
|
138
|
+
</xsl:choose>
|
|
139
|
+
<xsl:text>}</xsl:text>
|
|
140
|
+
<xsl:if test="position() != last()">,</xsl:if>
|
|
141
|
+
</xsl:template>
|
|
142
|
+
</xsl:stylesheet>
|
|
143
|
+
XSLT
|
|
144
|
+
)
|
|
145
|
+
local json_result
|
|
146
|
+
json_result=$(echo "$xslt_script" | xsltproc - "$xml_file" 2>/dev/null) || {
|
|
147
|
+
xml_json_err "CONVERSION_ERROR" "XSLT conversion failed"
|
|
148
|
+
return 1
|
|
149
|
+
}
|
|
150
|
+
xml_json_ok "{\"format\":\"object\",\"json\":$(echo "$json_result" | jq -Rs '.')}"
|
|
151
|
+
return 0
|
|
152
|
+
fi
|
|
153
|
+
|
|
154
|
+
# Last resort: Use xmlstarlet if available
|
|
155
|
+
if [[ "$XMLSTARLET_AVAILABLE" == "true" ]]; then
|
|
156
|
+
local json_result
|
|
157
|
+
json_result=$(xmlstarlet sel -t -m "/" -o '{"root":{' -m "*" -v "name()" -o ':"' -v "." -o '"' -b -o '}}' "$xml_file" 2>/dev/null) || {
|
|
158
|
+
xml_json_err "CONVERSION_ERROR" "xmlstarlet conversion failed"
|
|
159
|
+
return 1
|
|
160
|
+
}
|
|
161
|
+
xml_json_ok "{\"format\":\"object\",\"json\":$(echo "$json_result" | jq -Rs '.')}"
|
|
162
|
+
return 0
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
xml_json_err "TOOL_NOT_AVAILABLE" "No XML to JSON conversion tool available. Install xml2json, xsltproc, or xmlstarlet."
|
|
166
|
+
return 1
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
# ============================================================================
|
|
170
|
+
# JSON to XML Conversion
|
|
171
|
+
# ============================================================================
|
|
172
|
+
|
|
173
|
+
# json-to-xml: Convert JSON to XML
|
|
174
|
+
# Usage: json-to-xml <json_file> [root_element]
|
|
175
|
+
# Returns: {"ok":true,"result":{"xml":"<root>...</root>"}}
|
|
176
|
+
json-to-xml() {
|
|
177
|
+
local json_file="${1:-}"
|
|
178
|
+
local root_element="${2:-root}"
|
|
179
|
+
|
|
180
|
+
[[ -z "$json_file" ]] && { xml_json_err "MISSING_ARG" "Missing JSON file argument"; return 1; }
|
|
181
|
+
[[ -f "$json_file" ]] || { xml_json_err "FILE_NOT_FOUND" "JSON file not found: $json_file"; return 1; }
|
|
182
|
+
|
|
183
|
+
# Validate JSON first
|
|
184
|
+
if ! jq empty "$json_file" 2>/dev/null; then
|
|
185
|
+
xml_json_err "PARSE_ERROR" "Invalid JSON file: $json_file"
|
|
186
|
+
return 1
|
|
187
|
+
fi
|
|
188
|
+
|
|
189
|
+
# Build XML using jq to generate structure
|
|
190
|
+
local xml_output
|
|
191
|
+
xml_output=$(jq -r --arg root "$root_element" '
|
|
192
|
+
def to_xml:
|
|
193
|
+
if type == "object" then
|
|
194
|
+
to_entries | map(
|
|
195
|
+
"<\(.key)>\(.value | to_xml)</\(.key)>"
|
|
196
|
+
) | join("")
|
|
197
|
+
elif type == "array" then
|
|
198
|
+
map("<item>\(. | to_xml)</item>") | join("")
|
|
199
|
+
elif type == "string" then
|
|
200
|
+
.
|
|
201
|
+
elif type == "number" then
|
|
202
|
+
tostring
|
|
203
|
+
elif type == "boolean" then
|
|
204
|
+
tostring
|
|
205
|
+
elif type == "null" then
|
|
206
|
+
""
|
|
207
|
+
else
|
|
208
|
+
tostring
|
|
209
|
+
end;
|
|
210
|
+
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<\($root)>\n" + (to_xml) + "\n</\($root)>"
|
|
211
|
+
' "$json_file" 2>/dev/null) || {
|
|
212
|
+
xml_json_err "CONVERSION_ERROR" "JSON to XML conversion failed"
|
|
213
|
+
return 1
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
# Escape the XML for JSON output
|
|
217
|
+
local escaped_xml
|
|
218
|
+
escaped_xml=$(echo "$xml_output" | jq -Rs '.')
|
|
219
|
+
xml_json_ok "{\"xml\":$escaped_xml}"
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
# ============================================================================
|
|
223
|
+
# XML Document Merging
|
|
224
|
+
# ============================================================================
|
|
225
|
+
|
|
226
|
+
# xml-merge: XInclude document merging
|
|
227
|
+
# Usage: xml-merge <output_file> <main_xml_file>
|
|
228
|
+
# Returns: {"ok":true,"result":{"merged":true,"output":"<path>","sources_resolved":N}}
|
|
229
|
+
xml-merge() {
|
|
230
|
+
local output_file="${1:-}"
|
|
231
|
+
local main_xml="${2:-}"
|
|
232
|
+
|
|
233
|
+
[[ -z "$output_file" ]] && { xml_json_err "MISSING_ARG" "Missing output file argument"; return 1; }
|
|
234
|
+
[[ -z "$main_xml" ]] && { xml_json_err "MISSING_ARG" "Missing main XML file argument"; return 1; }
|
|
235
|
+
[[ -f "$main_xml" ]] || { xml_json_err "FILE_NOT_FOUND" "Main XML file not found: $main_xml"; return 1; }
|
|
236
|
+
|
|
237
|
+
# Check well-formedness of main file
|
|
238
|
+
local well_formed_result
|
|
239
|
+
well_formed_result=$(xml-well-formed "$main_xml" 2>/dev/null)
|
|
240
|
+
if ! echo "$well_formed_result" | jq -e '.result.well_formed' >/dev/null 2>&1; then
|
|
241
|
+
xml_json_err "PARSE_ERROR" "Main XML file is not well-formed"
|
|
242
|
+
return 1
|
|
243
|
+
fi
|
|
244
|
+
|
|
245
|
+
# Use xmllint for XInclude processing with security flags
|
|
246
|
+
if [[ "$XMLLINT_AVAILABLE" == "true" ]]; then
|
|
247
|
+
local merged
|
|
248
|
+
merged=$(xmllint --nonet --noent --xinclude "$main_xml" 2>/dev/null) || {
|
|
249
|
+
xml_json_err "MERGE_ERROR" "XInclude merge failed"
|
|
250
|
+
return 1
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
# Write output
|
|
254
|
+
echo "$merged" > "$output_file"
|
|
255
|
+
|
|
256
|
+
# Count resolved includes (approximate)
|
|
257
|
+
local resolved_count
|
|
258
|
+
resolved_count=$(echo "$merged" | grep -c '<xi:include' 2>/dev/null || echo "0")
|
|
259
|
+
|
|
260
|
+
local escaped_output
|
|
261
|
+
escaped_output=$(echo "$output_file" | jq -Rs '.[:-1]')
|
|
262
|
+
xml_json_ok "{\"merged\":true,\"output\":$escaped_output,\"sources_resolved\":$resolved_count}"
|
|
263
|
+
return 0
|
|
264
|
+
fi
|
|
265
|
+
|
|
266
|
+
# Without xmllint, we cannot safely process XInclude
|
|
267
|
+
xml_json_err "TOOL_NOT_AVAILABLE" "xmllint required for XInclude merging. Install libxml2 utilities."
|
|
268
|
+
return 1
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
# Export functions
|
|
272
|
+
export -f xml-convert-detect-format xml-to-json json-to-xml xml-merge
|
|
273
|
+
export XML2JSON_AVAILABLE
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# XML Query Utilities
|
|
3
|
+
# XPath queries with xmlstarlet and xmllint fallback
|
|
4
|
+
#
|
|
5
|
+
# Usage: source .aether/utils/xml-query.sh
|
|
6
|
+
# xml-query <xml_file> <xpath_expression>
|
|
7
|
+
# xml-query-attr <xml_file> <xpath_expression>
|
|
8
|
+
# xml-query-text <xml_file> <element_name>
|
|
9
|
+
# xml-query-count <xml_file> <xpath_expression>
|
|
10
|
+
|
|
11
|
+
set -euo pipefail
|
|
12
|
+
|
|
13
|
+
# Source xml-core.sh for JSON helpers and tool detection
|
|
14
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
15
|
+
source "$SCRIPT_DIR/xml-core.sh"
|
|
16
|
+
|
|
17
|
+
# ============================================================================
|
|
18
|
+
# XPath Query Functions
|
|
19
|
+
# ============================================================================
|
|
20
|
+
|
|
21
|
+
# xml-query: Execute XPath query against XML file
|
|
22
|
+
# Usage: xml-query <xml_file> <xpath_expression>
|
|
23
|
+
# Returns: {"ok":true,"result":{"matches":["value1","value2",...]}}
|
|
24
|
+
xml-query() {
|
|
25
|
+
local xml_file="${1:-}"
|
|
26
|
+
local xpath="${2:-}"
|
|
27
|
+
|
|
28
|
+
[[ -z "$xml_file" ]] && { xml_json_err "MISSING_ARG" "Missing XML file argument"; return 1; }
|
|
29
|
+
[[ -z "$xpath" ]] && { xml_json_err "MISSING_ARG" "Missing XPath expression"; return 1; }
|
|
30
|
+
[[ -f "$xml_file" ]] || { xml_json_err "FILE_NOT_FOUND" "XML file not found: $xml_file"; return 1; }
|
|
31
|
+
|
|
32
|
+
local results=""
|
|
33
|
+
|
|
34
|
+
# Prefer xmlstarlet for full XPath support
|
|
35
|
+
if [[ "$XMLSTARLET_AVAILABLE" == "true" ]]; then
|
|
36
|
+
results=$(xmlstarlet sel -t -v "$xpath" "$xml_file" 2>/dev/null | tr '\n' '|')
|
|
37
|
+
# Remove trailing pipe
|
|
38
|
+
results="${results%|}"
|
|
39
|
+
elif [[ "$XMLLINT_AVAILABLE" == "true" ]]; then
|
|
40
|
+
# xmllint has limited XPath but works for basic queries
|
|
41
|
+
# Note: xmllint --xpath returns the text content of matched nodes
|
|
42
|
+
results=$(xmllint --nonet --noent --xpath "$xpath" "$xml_file" 2>/dev/null | \
|
|
43
|
+
sed 's/<[^>]*>//g' | tr '\n' '|' | sed 's/|$//')
|
|
44
|
+
else
|
|
45
|
+
xml_json_err "TOOL_NOT_AVAILABLE" "No XPath-capable tool available (install xmlstarlet or libxml2)"
|
|
46
|
+
return 1
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Build JSON array from pipe-separated results
|
|
50
|
+
if [[ -n "$results" ]]; then
|
|
51
|
+
local json_array="["
|
|
52
|
+
local first=true
|
|
53
|
+
IFS='|' read -ra matches <<< "$results"
|
|
54
|
+
for match in "${matches[@]}"; do
|
|
55
|
+
# Trim whitespace and escape for JSON
|
|
56
|
+
match=$(echo "$match" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
|
57
|
+
match=$(echo "$match" | sed 's/\\/\\\\/g; s/"/\\"/g')
|
|
58
|
+
if [[ "$first" == "true" ]]; then
|
|
59
|
+
first=false
|
|
60
|
+
json_array="$json_array\"$match\""
|
|
61
|
+
else
|
|
62
|
+
json_array="$json_array,\"$match\""
|
|
63
|
+
fi
|
|
64
|
+
done
|
|
65
|
+
json_array="$json_array]"
|
|
66
|
+
xml_json_ok "{\"matches\":$json_array}"
|
|
67
|
+
else
|
|
68
|
+
xml_json_ok '{"matches":[]}'
|
|
69
|
+
fi
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
# xml-query-attr: Extract attribute values using XPath
|
|
73
|
+
# Usage: xml-query-attr <xml_file> <element_xpath> <attribute_name>
|
|
74
|
+
# Returns: {"ok":true,"result":{"attribute":"name","values":["val1","val2"]}}
|
|
75
|
+
xml-query-attr() {
|
|
76
|
+
local xml_file="${1:-}"
|
|
77
|
+
local element_xpath="${2:-}"
|
|
78
|
+
local attr_name="${3:-}"
|
|
79
|
+
|
|
80
|
+
[[ -z "$xml_file" ]] && { xml_json_err "MISSING_ARG" "Missing XML file argument"; return 1; }
|
|
81
|
+
[[ -z "$element_xpath" ]] && { xml_json_err "MISSING_ARG" "Missing element XPath"; return 1; }
|
|
82
|
+
[[ -z "$attr_name" ]] && { xml_json_err "MISSING_ARG" "Missing attribute name"; return 1; }
|
|
83
|
+
[[ -f "$xml_file" ]] || { xml_json_err "FILE_NOT_FOUND" "XML file not found: $xml_file"; return 1; }
|
|
84
|
+
|
|
85
|
+
local full_xpath="${element_xpath}/@${attr_name}"
|
|
86
|
+
local results=""
|
|
87
|
+
|
|
88
|
+
if [[ "$XMLSTARLET_AVAILABLE" == "true" ]]; then
|
|
89
|
+
results=$(xmlstarlet sel -t -v "$full_xpath" "$xml_file" 2>/dev/null | tr '\n' '|')
|
|
90
|
+
results="${results%|}"
|
|
91
|
+
elif [[ "$XMLLINT_AVAILABLE" == "true" ]]; then
|
|
92
|
+
# xmllint can extract attributes with //@attrname syntax
|
|
93
|
+
results=$(xmllint --nonet --noent --xpath "$full_xpath" "$xml_file" 2>/dev/null | tr '\n' '|')
|
|
94
|
+
results="${results%|}"
|
|
95
|
+
else
|
|
96
|
+
xml_json_err "TOOL_NOT_AVAILABLE" "No XPath-capable tool available"
|
|
97
|
+
return 1
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
# Build JSON array
|
|
101
|
+
if [[ -n "$results" ]]; then
|
|
102
|
+
local json_array="["
|
|
103
|
+
local first=true
|
|
104
|
+
IFS='|' read -ra values <<< "$results"
|
|
105
|
+
for val in "${values[@]}"; do
|
|
106
|
+
val=$(echo "$val" | sed 's/\\/\\\\/g; s/"/\\"/g')
|
|
107
|
+
if [[ "$first" == "true" ]]; then
|
|
108
|
+
first=false
|
|
109
|
+
json_array="$json_array\"$val\""
|
|
110
|
+
else
|
|
111
|
+
json_array="$json_array,\"$val\""
|
|
112
|
+
fi
|
|
113
|
+
done
|
|
114
|
+
json_array="$json_array]"
|
|
115
|
+
xml_json_ok "{\"attribute\":\"$attr_name\",\"values\":$json_array}"
|
|
116
|
+
else
|
|
117
|
+
xml_json_ok "{\"attribute\":\"$attr_name\",\"values\":[]}"
|
|
118
|
+
fi
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
# xml-query-text: Extract text content of elements
|
|
122
|
+
# Usage: xml-query-text <xml_file> <element_name>
|
|
123
|
+
# Returns: {"ok":true,"result":{"element":"name","text":["text1","text2"]}}
|
|
124
|
+
xml-query-text() {
|
|
125
|
+
local xml_file="${1:-}"
|
|
126
|
+
local element_name="${2:-}"
|
|
127
|
+
|
|
128
|
+
[[ -z "$xml_file" ]] && { xml_json_err "MISSING_ARG" "Missing XML file argument"; return 1; }
|
|
129
|
+
[[ -z "$element_name" ]] && { xml_json_err "MISSING_ARG" "Missing element name"; return 1; }
|
|
130
|
+
[[ -f "$xml_file" ]] || { xml_json_err "FILE_NOT_FOUND" "XML file not found: $xml_file"; return 1; }
|
|
131
|
+
|
|
132
|
+
local xpath="//$element_name"
|
|
133
|
+
local results=""
|
|
134
|
+
|
|
135
|
+
if [[ "$XMLSTARLET_AVAILABLE" == "true" ]]; then
|
|
136
|
+
# Use -m to match nodes and extract text
|
|
137
|
+
results=$(xmlstarlet sel -t -m "$xpath" -v "." -n "$xml_file" 2>/dev/null | tr '\n' '|')
|
|
138
|
+
results="${results%|}"
|
|
139
|
+
elif [[ "$XMLLINT_AVAILABLE" == "true" ]]; then
|
|
140
|
+
# xmllint --xpath returns text content directly for simple paths
|
|
141
|
+
results=$(xmllint --nonet --noent --xpath "$xpath" "$xml_file" 2>/dev/null | \
|
|
142
|
+
sed 's/<[^>]*>//g' | tr '\n' '|' | sed 's/|$//')
|
|
143
|
+
else
|
|
144
|
+
xml_json_err "TOOL_NOT_AVAILABLE" "No XPath-capable tool available"
|
|
145
|
+
return 1
|
|
146
|
+
fi
|
|
147
|
+
|
|
148
|
+
if [[ -n "$results" ]]; then
|
|
149
|
+
local json_array="["
|
|
150
|
+
local first=true
|
|
151
|
+
IFS='|' read -ra texts <<< "$results"
|
|
152
|
+
for text in "${texts[@]}"; do
|
|
153
|
+
text=$(echo "$text" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
|
154
|
+
text=$(echo "$text" | sed 's/\\/\\\\/g; s/"/\\"/g')
|
|
155
|
+
if [[ "$first" == "true" ]]; then
|
|
156
|
+
first=false
|
|
157
|
+
json_array="$json_array\"$text\""
|
|
158
|
+
else
|
|
159
|
+
json_array="$json_array,\"$text\""
|
|
160
|
+
fi
|
|
161
|
+
done
|
|
162
|
+
json_array="$json_array]"
|
|
163
|
+
xml_json_ok "{\"element\":\"$element_name\",\"text\":$json_array}"
|
|
164
|
+
else
|
|
165
|
+
xml_json_ok "{\"element\":\"$element_name\",\"text\":[]}"
|
|
166
|
+
fi
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
# xml-query-count: Count nodes matching XPath expression
|
|
170
|
+
# Usage: xml-query-count <xml_file> <xpath_expression>
|
|
171
|
+
# Returns: {"ok":true,"result":{"count":5}}
|
|
172
|
+
xml-query-count() {
|
|
173
|
+
local xml_file="${1:-}"
|
|
174
|
+
local xpath="${2:-}"
|
|
175
|
+
|
|
176
|
+
[[ -z "$xml_file" ]] && { xml_json_err "MISSING_ARG" "Missing XML file argument"; return 1; }
|
|
177
|
+
[[ -z "$xpath" ]] && { xml_json_err "MISSING_ARG" "Missing XPath expression"; return 1; }
|
|
178
|
+
[[ -f "$xml_file" ]] || { xml_json_err "FILE_NOT_FOUND" "XML file not found: $xml_file"; return 1; }
|
|
179
|
+
|
|
180
|
+
local count=0
|
|
181
|
+
|
|
182
|
+
if [[ "$XMLSTARLET_AVAILABLE" == "true" ]]; then
|
|
183
|
+
# Use count() XPath function
|
|
184
|
+
local count_result
|
|
185
|
+
count_result=$(xmlstarlet sel -t -v "count($xpath)" "$xml_file" 2>/dev/null)
|
|
186
|
+
count="${count_result:-0}"
|
|
187
|
+
elif [[ "$XMLLINT_AVAILABLE" == "true" ]]; then
|
|
188
|
+
# Count matching lines (approximate for simple cases)
|
|
189
|
+
local matches
|
|
190
|
+
matches=$(xmllint --nonet --noent --xpath "$xpath" "$xml_file" 2>/dev/null | grep -c '<' || true)
|
|
191
|
+
count="${matches:-0}"
|
|
192
|
+
else
|
|
193
|
+
xml_json_err "TOOL_NOT_AVAILABLE" "No XPath-capable tool available"
|
|
194
|
+
return 1
|
|
195
|
+
fi
|
|
196
|
+
|
|
197
|
+
xml_json_ok "{\"count\":$count}"
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
# Export functions
|
|
201
|
+
export -f xml-query xml-query-attr xml-query-text xml-query-count
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# XML Utilities Loader
|
|
3
|
+
# Sources all XML modules for backward compatibility
|
|
4
|
+
#
|
|
5
|
+
# IMPORTANT: This file is now a loader only. New code should source
|
|
6
|
+
# individual modules directly from .aether/utils/ or .aether/exchange/
|
|
7
|
+
#
|
|
8
|
+
# Usage: source .aether/utils/xml-utils.sh
|
|
9
|
+
#
|
|
10
|
+
# Modules loaded:
|
|
11
|
+
# - xml-core.sh : Core operations (validate, format, escape)
|
|
12
|
+
# - xml-query.sh : XPath queries
|
|
13
|
+
# - xml-convert.sh : JSON/XML conversion
|
|
14
|
+
# - xml-compose.sh : XInclude composition
|
|
15
|
+
# - pheromone-xml.sh : Pheromone exchange
|
|
16
|
+
# - wisdom-xml.sh : Queen wisdom exchange
|
|
17
|
+
# - registry-xml.sh : Colony registry exchange
|
|
18
|
+
#
|
|
19
|
+
# Deprecated functions (maintained for compatibility):
|
|
20
|
+
# - pheromone-to-xml() -> Use xml-pheromone-export()
|
|
21
|
+
# - pheromone-from-xml() -> Use xml-pheromone-import()
|
|
22
|
+
# - queen-wisdom-to-xml() -> Use xml-wisdom-export()
|
|
23
|
+
# - queen-wisdom-from-xml() -> Use xml-wisdom-import()
|
|
24
|
+
|
|
25
|
+
set -euo pipefail
|
|
26
|
+
|
|
27
|
+
# Determine script directory for relative sourcing
|
|
28
|
+
# Handle case when sourced interactively (BASH_SOURCE[0] may be empty)
|
|
29
|
+
if [[ -n "${BASH_SOURCE[0]:-}" ]]; then
|
|
30
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
31
|
+
else
|
|
32
|
+
# Fallback: derive from the sourced script's location
|
|
33
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
|
|
34
|
+
fi
|
|
35
|
+
EXCHANGE_DIR="$(cd "$SCRIPT_DIR/../exchange" && pwd)"
|
|
36
|
+
|
|
37
|
+
# ============================================================================
|
|
38
|
+
# Load Core Modules
|
|
39
|
+
# ============================================================================
|
|
40
|
+
|
|
41
|
+
# Core utilities (required by other modules)
|
|
42
|
+
source "$SCRIPT_DIR/xml-core.sh"
|
|
43
|
+
|
|
44
|
+
# Query functions
|
|
45
|
+
source "$SCRIPT_DIR/xml-query.sh"
|
|
46
|
+
|
|
47
|
+
# Conversion functions
|
|
48
|
+
source "$SCRIPT_DIR/xml-convert.sh"
|
|
49
|
+
|
|
50
|
+
# Composition functions
|
|
51
|
+
source "$SCRIPT_DIR/xml-compose.sh"
|
|
52
|
+
|
|
53
|
+
# ============================================================================
|
|
54
|
+
# Load Exchange Modules
|
|
55
|
+
# ============================================================================
|
|
56
|
+
|
|
57
|
+
# Pheromone exchange (export/import)
|
|
58
|
+
source "$EXCHANGE_DIR/pheromone-xml.sh"
|
|
59
|
+
|
|
60
|
+
# Queen wisdom exchange
|
|
61
|
+
source "$EXCHANGE_DIR/wisdom-xml.sh"
|
|
62
|
+
|
|
63
|
+
# Colony registry exchange
|
|
64
|
+
source "$EXCHANGE_DIR/registry-xml.sh"
|
|
65
|
+
|
|
66
|
+
# ============================================================================
|
|
67
|
+
# Backward Compatibility Aliases
|
|
68
|
+
# ============================================================================
|
|
69
|
+
|
|
70
|
+
# Map old function names to new ones for compatibility
|
|
71
|
+
pheromone-to-xml() { xml-pheromone-export "$@"; }
|
|
72
|
+
pheromone-from-xml() { xml-pheromone-import "$@"; }
|
|
73
|
+
queen-wisdom-to-xml() { xml-wisdom-export "$@"; }
|
|
74
|
+
queen-wisdom-from-xml() { xml-wisdom-import "$@"; }
|
|
75
|
+
registry-to-xml() { xml-registry-export "$@"; }
|
|
76
|
+
registry-from-xml() { xml-registry-import "$@"; }
|
|
77
|
+
|
|
78
|
+
# Export compatibility aliases
|
|
79
|
+
export -f pheromone-to-xml pheromone-from-xml
|
|
80
|
+
export -f queen-wisdom-to-xml queen-wisdom-from-xml
|
|
81
|
+
export -f registry-to-xml registry-from-xml
|
|
82
|
+
|
|
83
|
+
# ============================================================================
|
|
84
|
+
# Module Information
|
|
85
|
+
# ============================================================================
|
|
86
|
+
|
|
87
|
+
# xml-utils-info: Display module information
|
|
88
|
+
# Usage: xml-utils-info
|
|
89
|
+
xml-utils-info() {
|
|
90
|
+
xml_json_ok '{
|
|
91
|
+
"modules": [
|
|
92
|
+
"xml-core.sh",
|
|
93
|
+
"xml-query.sh",
|
|
94
|
+
"xml-convert.sh",
|
|
95
|
+
"xml-compose.sh",
|
|
96
|
+
"pheromone-xml.sh",
|
|
97
|
+
"wisdom-xml.sh",
|
|
98
|
+
"registry-xml.sh"
|
|
99
|
+
],
|
|
100
|
+
"note": "This loader provides backward compatibility. New code should source individual modules.",
|
|
101
|
+
"tools": {
|
|
102
|
+
"xmllint": '"$XMLLINT_AVAILABLE"',
|
|
103
|
+
"xmlstarlet": '"$XMLSTARLET_AVAILABLE"',
|
|
104
|
+
"xsltproc": '"$XSLTPROC_AVAILABLE"'
|
|
105
|
+
}
|
|
106
|
+
}'
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export -f xml-utils-info
|
|
110
|
+
|
|
@@ -136,7 +136,7 @@ Before reporting ANY task as complete:
|
|
|
136
136
|
- Run relevant tests yourself
|
|
137
137
|
- Confirm success criteria with evidence
|
|
138
138
|
|
|
139
|
-
See `.aether/verification.md` for full discipline reference.
|
|
139
|
+
See `.aether/docs/disciplines/verification.md` for full discipline reference.
|
|
140
140
|
|
|
141
141
|
### Verification Loop Discipline
|
|
142
142
|
|
|
@@ -163,7 +163,7 @@ Diff: [X files changed]
|
|
|
163
163
|
Overall: [READY/NOT READY]
|
|
164
164
|
```
|
|
165
165
|
|
|
166
|
-
See `.aether/verification-loop.md` for full discipline reference.
|
|
166
|
+
See `.aether/docs/disciplines/verification-loop.md` for full discipline reference.
|
|
167
167
|
|
|
168
168
|
### Debugging Discipline
|
|
169
169
|
|
|
@@ -187,7 +187,7 @@ When you encounter ANY bug, test failure, or unexpected behavior:
|
|
|
187
187
|
- "Just try changing X"
|
|
188
188
|
- "I don't fully understand but this might work"
|
|
189
189
|
|
|
190
|
-
See `.aether/debugging.md` for full discipline reference.
|
|
190
|
+
See `.aether/docs/disciplines/debugging.md` for full discipline reference.
|
|
191
191
|
|
|
192
192
|
### TDD Discipline
|
|
193
193
|
|
|
@@ -210,7 +210,7 @@ When implementing ANY new code:
|
|
|
210
210
|
|
|
211
211
|
**Coverage target:** 80%+ for new code.
|
|
212
212
|
|
|
213
|
-
See `.aether/tdd.md` for full discipline reference.
|
|
213
|
+
See `.aether/docs/disciplines/tdd.md` for full discipline reference.
|
|
214
214
|
|
|
215
215
|
### Learning Discipline
|
|
216
216
|
|
|
@@ -228,7 +228,7 @@ The colony learns from every phase. Observe patterns for future improvement.
|
|
|
228
228
|
|
|
229
229
|
**Report patterns observed** in your output for colony learning.
|
|
230
230
|
|
|
231
|
-
See `.aether/learning.md` for full discipline reference.
|
|
231
|
+
See `.aether/docs/disciplines/learning.md` for full discipline reference.
|
|
232
232
|
|
|
233
233
|
### Coding Standards Discipline
|
|
234
234
|
|
|
@@ -252,7 +252,7 @@ Quick checklist before completing code:
|
|
|
252
252
|
- **Error handling** - Try/catch with meaningful messages
|
|
253
253
|
- **Async** - Parallelize with Promise.all where possible
|
|
254
254
|
|
|
255
|
-
See `.aether/coding-standards.md` for full discipline reference.
|
|
255
|
+
See `.aether/docs/disciplines/coding-standards.md` for full discipline reference.
|
|
256
256
|
|
|
257
257
|
### Activity Log
|
|
258
258
|
|
|
@@ -387,14 +387,9 @@ All spawns are logged to `.aether/data/spawn-tree.txt` and visible in `/ant:watc
|
|
|
387
387
|
|
|
388
388
|
### Visual Identity
|
|
389
389
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
| Watcher | 👁️🐜 |
|
|
394
|
-
| Scout | 🔍🐜 |
|
|
395
|
-
| Colonizer | 🗺️🐜 |
|
|
396
|
-
| Architect | 🏛️🐜 |
|
|
397
|
-
| Route-Setter | 📋🐜 |
|
|
390
|
+
Workers display as `{caste_emoji} {worker_name}` (e.g., `🔨🐜 Hammer-42`).
|
|
391
|
+
|
|
392
|
+
For complete caste emoji reference, see `.aether/docs/caste-system.md`.
|
|
398
393
|
|
|
399
394
|
Use your emoji in output headers: `{emoji} {Role} Ant -- {status}`
|
|
400
395
|
|
|
@@ -448,7 +443,7 @@ All passing: ✓
|
|
|
448
443
|
|
|
449
444
|
**When Encountering Errors:**
|
|
450
445
|
|
|
451
|
-
Follow systematic debugging (see `.aether/debugging.md`):
|
|
446
|
+
Follow systematic debugging (see `.aether/docs/disciplines/debugging.md`):
|
|
452
447
|
|
|
453
448
|
1. **STOP** - Do not attempt quick fixes
|
|
454
449
|
2. **Read error completely** - Stack trace, line numbers, error codes
|
|
@@ -562,7 +557,7 @@ Findings:
|
|
|
562
557
|
|
|
563
558
|
**When Tests Fail:**
|
|
564
559
|
|
|
565
|
-
Follow systematic debugging (see `.aether/debugging.md`):
|
|
560
|
+
Follow systematic debugging (see `.aether/docs/disciplines/debugging.md`):
|
|
566
561
|
|
|
567
562
|
1. **Read the failure completely** - Full error, stack trace
|
|
568
563
|
2. **Reproduce** - Run the specific failing test
|
|
@@ -626,7 +621,9 @@ Recommendation: {specific fix or investigation needed}
|
|
|
626
621
|
|
|
627
622
|
---
|
|
628
623
|
|
|
629
|
-
## Architect
|
|
624
|
+
## Architect (Merged into Keeper)
|
|
625
|
+
|
|
626
|
+
> **Note:** As of Phase 25, Architect capabilities are absorbed by the Keeper agent as "Architecture Mode". Workers named with Architect patterns still resolve to the 🏛️🐜 caste emoji. See `.opencode/agents/aether-keeper.md` for the merged definition.
|
|
630
627
|
|
|
631
628
|
🏛️ **Purpose:** Synthesize knowledge, extract patterns, and coordinate documentation. The colony's wisdom -- when the colony learns, you organize and preserve that knowledge.
|
|
632
629
|
|