aether-colony 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.aether/CONTEXT.md +160 -0
- package/.aether/QUEEN.md +84 -0
- package/.aether/aether-utils.sh +7749 -0
- package/.aether/docs/QUEEN-SYSTEM.md +211 -0
- package/.aether/docs/README.md +68 -0
- package/.aether/docs/caste-system.md +48 -0
- package/.aether/docs/disciplines/DISCIPLINES.md +93 -0
- package/.aether/docs/disciplines/coding-standards.md +197 -0
- package/.aether/docs/disciplines/debugging.md +207 -0
- package/.aether/docs/disciplines/learning.md +254 -0
- package/.aether/docs/disciplines/tdd.md +257 -0
- package/.aether/docs/disciplines/verification-loop.md +167 -0
- package/.aether/docs/disciplines/verification.md +116 -0
- package/.aether/docs/error-codes.md +268 -0
- package/.aether/docs/known-issues.md +233 -0
- package/.aether/docs/pheromones.md +205 -0
- package/.aether/docs/queen-commands.md +97 -0
- package/.aether/exchange/colony-registry.xml +11 -0
- package/.aether/exchange/pheromone-xml.sh +575 -0
- package/.aether/exchange/pheromones.xml +87 -0
- package/.aether/exchange/queen-wisdom.xml +14 -0
- package/.aether/exchange/registry-xml.sh +273 -0
- package/.aether/exchange/wisdom-xml.sh +319 -0
- package/.aether/midden/approach-changes.md +5 -0
- package/.aether/midden/build-failures.md +5 -0
- package/.aether/midden/test-failures.md +5 -0
- package/.aether/model-profiles.yaml +100 -0
- package/.aether/rules/aether-colony.md +134 -0
- package/.aether/schemas/aether-types.xsd +255 -0
- package/.aether/schemas/colony-registry.xsd +309 -0
- package/.aether/schemas/example-prompt-builder.xml +234 -0
- package/.aether/schemas/pheromone.xsd +163 -0
- package/.aether/schemas/prompt.xsd +416 -0
- package/.aether/schemas/queen-wisdom.xsd +325 -0
- package/.aether/schemas/worker-priming.xsd +276 -0
- package/.aether/templates/QUEEN.md.template +79 -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/.aether/templates/learning-observations.template.json +6 -0
- package/.aether/templates/midden.template.json +7 -0
- package/.aether/templates/pheromones.template.json +6 -0
- package/.aether/templates/session.template.json +9 -0
- package/.aether/utils/atomic-write.sh +219 -0
- package/.aether/utils/chamber-compare.sh +193 -0
- package/.aether/utils/chamber-utils.sh +297 -0
- package/.aether/utils/colorize-log.sh +132 -0
- package/.aether/utils/error-handler.sh +212 -0
- package/.aether/utils/file-lock.sh +158 -0
- package/.aether/utils/queen-to-md.xsl +395 -0
- package/.aether/utils/semantic-cli.sh +413 -0
- package/.aether/utils/spawn-tree.sh +428 -0
- package/.aether/utils/spawn-with-model.sh +56 -0
- package/.aether/utils/state-loader.sh +215 -0
- package/.aether/utils/swarm-display.sh +268 -0
- package/.aether/utils/watch-spawn-tree.sh +253 -0
- package/.aether/utils/xml-compose.sh +253 -0
- package/.aether/utils/xml-convert.sh +273 -0
- package/.aether/utils/xml-core.sh +186 -0
- package/.aether/utils/xml-query.sh +201 -0
- package/.aether/utils/xml-utils.sh +110 -0
- package/.aether/workers.md +765 -0
- 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 +341 -0
- package/.claude/commands/ant/build.md +1160 -0
- package/.claude/commands/ant/chaos.md +349 -0
- package/.claude/commands/ant/colonize.md +270 -0
- package/.claude/commands/ant/continue.md +1070 -0
- package/.claude/commands/ant/council.md +309 -0
- package/.claude/commands/ant/dream.md +265 -0
- package/.claude/commands/ant/entomb.md +487 -0
- package/.claude/commands/ant/feedback.md +78 -0
- package/.claude/commands/ant/flag.md +139 -0
- package/.claude/commands/ant/flags.md +155 -0
- package/.claude/commands/ant/focus.md +58 -0
- package/.claude/commands/ant/help.md +122 -0
- package/.claude/commands/ant/history.md +137 -0
- package/.claude/commands/ant/init.md +409 -0
- package/.claude/commands/ant/interpret.md +267 -0
- package/.claude/commands/ant/lay-eggs.md +201 -0
- package/.claude/commands/ant/maturity.md +102 -0
- package/.claude/commands/ant/memory-details.md +77 -0
- package/.claude/commands/ant/migrate-state.md +165 -0
- package/.claude/commands/ant/oracle.md +387 -0
- package/.claude/commands/ant/organize.md +227 -0
- package/.claude/commands/ant/pause-colony.md +247 -0
- package/.claude/commands/ant/phase.md +126 -0
- package/.claude/commands/ant/plan.md +544 -0
- package/.claude/commands/ant/redirect.md +58 -0
- package/.claude/commands/ant/resume-colony.md +182 -0
- package/.claude/commands/ant/resume.md +363 -0
- package/.claude/commands/ant/seal.md +306 -0
- package/.claude/commands/ant/status.md +272 -0
- package/.claude/commands/ant/swarm.md +361 -0
- package/.claude/commands/ant/tunnels.md +425 -0
- package/.claude/commands/ant/update.md +209 -0
- package/.claude/commands/ant/verify-castes.md +95 -0
- package/.claude/commands/ant/watch.md +238 -0
- package/.opencode/agents/aether-ambassador.md +140 -0
- package/.opencode/agents/aether-archaeologist.md +108 -0
- package/.opencode/agents/aether-auditor.md +144 -0
- package/.opencode/agents/aether-builder.md +184 -0
- package/.opencode/agents/aether-chaos.md +115 -0
- package/.opencode/agents/aether-chronicler.md +122 -0
- package/.opencode/agents/aether-gatekeeper.md +116 -0
- package/.opencode/agents/aether-includer.md +117 -0
- package/.opencode/agents/aether-keeper.md +177 -0
- package/.opencode/agents/aether-measurer.md +128 -0
- package/.opencode/agents/aether-probe.md +133 -0
- package/.opencode/agents/aether-queen.md +286 -0
- package/.opencode/agents/aether-route-setter.md +130 -0
- package/.opencode/agents/aether-sage.md +106 -0
- package/.opencode/agents/aether-scout.md +101 -0
- package/.opencode/agents/aether-surveyor-disciplines.md +386 -0
- package/.opencode/agents/aether-surveyor-nest.md +324 -0
- package/.opencode/agents/aether-surveyor-pathogens.md +259 -0
- package/.opencode/agents/aether-surveyor-provisions.md +329 -0
- package/.opencode/agents/aether-tracker.md +137 -0
- package/.opencode/agents/aether-watcher.md +174 -0
- package/.opencode/agents/aether-weaver.md +130 -0
- package/.opencode/commands/ant/archaeology.md +338 -0
- package/.opencode/commands/ant/build.md +1200 -0
- package/.opencode/commands/ant/chaos.md +346 -0
- package/.opencode/commands/ant/colonize.md +202 -0
- package/.opencode/commands/ant/continue.md +938 -0
- package/.opencode/commands/ant/council.md +305 -0
- package/.opencode/commands/ant/dream.md +262 -0
- package/.opencode/commands/ant/entomb.md +367 -0
- package/.opencode/commands/ant/feedback.md +80 -0
- package/.opencode/commands/ant/flag.md +137 -0
- package/.opencode/commands/ant/flags.md +153 -0
- package/.opencode/commands/ant/focus.md +56 -0
- package/.opencode/commands/ant/help.md +124 -0
- package/.opencode/commands/ant/history.md +127 -0
- package/.opencode/commands/ant/init.md +337 -0
- package/.opencode/commands/ant/interpret.md +256 -0
- package/.opencode/commands/ant/lay-eggs.md +141 -0
- package/.opencode/commands/ant/maturity.md +92 -0
- package/.opencode/commands/ant/memory-details.md +77 -0
- package/.opencode/commands/ant/migrate-state.md +153 -0
- package/.opencode/commands/ant/oracle.md +338 -0
- package/.opencode/commands/ant/organize.md +224 -0
- package/.opencode/commands/ant/pause-colony.md +220 -0
- package/.opencode/commands/ant/phase.md +123 -0
- package/.opencode/commands/ant/plan.md +531 -0
- package/.opencode/commands/ant/redirect.md +67 -0
- package/.opencode/commands/ant/resume-colony.md +178 -0
- package/.opencode/commands/ant/resume.md +363 -0
- package/.opencode/commands/ant/seal.md +247 -0
- package/.opencode/commands/ant/status.md +272 -0
- package/.opencode/commands/ant/swarm.md +357 -0
- package/.opencode/commands/ant/tunnels.md +406 -0
- package/.opencode/commands/ant/update.md +191 -0
- package/.opencode/commands/ant/verify-castes.md +85 -0
- package/.opencode/commands/ant/watch.md +220 -0
- package/.opencode/opencode.json +3 -0
- package/CHANGELOG.md +325 -0
- package/DISCLAIMER.md +74 -0
- package/LICENSE +21 -0
- package/README.md +258 -0
- package/bin/cli.js +2436 -0
- package/bin/generate-commands.sh +291 -0
- package/bin/lib/caste-colors.js +57 -0
- package/bin/lib/colors.js +76 -0
- package/bin/lib/errors.js +255 -0
- package/bin/lib/event-types.js +190 -0
- package/bin/lib/file-lock.js +695 -0
- package/bin/lib/init.js +454 -0
- package/bin/lib/logger.js +242 -0
- package/bin/lib/model-profiles.js +445 -0
- package/bin/lib/model-verify.js +288 -0
- package/bin/lib/nestmate-loader.js +130 -0
- package/bin/lib/proxy-health.js +253 -0
- package/bin/lib/spawn-logger.js +266 -0
- package/bin/lib/state-guard.js +602 -0
- package/bin/lib/state-sync.js +516 -0
- package/bin/lib/telemetry.js +441 -0
- package/bin/lib/update-transaction.js +1454 -0
- package/bin/npx-install.js +178 -0
- package/bin/sync-to-runtime.sh +6 -0
- package/bin/validate-package.sh +88 -0
- package/package.json +70 -0
|
@@ -0,0 +1,575 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Pheromone Exchange Module
|
|
3
|
+
# JSON/XML bidirectional conversion for pheromone signals
|
|
4
|
+
#
|
|
5
|
+
# Usage: source .aether/exchange/pheromone-xml.sh
|
|
6
|
+
# xml-pheromone-export <pheromone_json> [output_xml]
|
|
7
|
+
# xml-pheromone-import <pheromone_xml> [output_json]
|
|
8
|
+
# xml-pheromone-validate <pheromone_xml>
|
|
9
|
+
# xml-pheromone-merge <colony_prefix> <xml_files...> [output_xml]
|
|
10
|
+
|
|
11
|
+
# Don't use set -e for library-style scripts - let callers handle errors
|
|
12
|
+
# set -euo pipefail
|
|
13
|
+
|
|
14
|
+
# Source dependencies - handle being sourced vs executed
|
|
15
|
+
if [[ -n "${BASH_SOURCE[0]:-}" ]]; then
|
|
16
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
17
|
+
else
|
|
18
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
19
|
+
fi
|
|
20
|
+
source "$SCRIPT_DIR/utils/xml-core.sh"
|
|
21
|
+
|
|
22
|
+
# Ensure tool availability variables are available
|
|
23
|
+
if [[ -z "${XMLLINT_AVAILABLE:-}" ]]; then
|
|
24
|
+
XMLLINT_AVAILABLE=false
|
|
25
|
+
command -v xmllint >/dev/null 2>&1 && XMLLINT_AVAILABLE=true
|
|
26
|
+
fi
|
|
27
|
+
if [[ -z "${XMLSTARLET_AVAILABLE:-}" ]]; then
|
|
28
|
+
XMLSTARLET_AVAILABLE=false
|
|
29
|
+
command -v xmlstarlet >/dev/null 2>&1 && XMLSTARLET_AVAILABLE=true
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
# ============================================================================
|
|
33
|
+
# Pheromone Export (JSON to XML)
|
|
34
|
+
# ============================================================================
|
|
35
|
+
|
|
36
|
+
# xml-pheromone-export: Convert pheromone JSON to XML format
|
|
37
|
+
# Usage: xml-pheromone-export <pheromone_json_file> [output_xml_file]
|
|
38
|
+
# Returns: {"ok":true,"result":{"xml":"...","path":"..."}}
|
|
39
|
+
xml-pheromone-export() {
|
|
40
|
+
local json_file="${1:-}"
|
|
41
|
+
local output_xml="${2:-}"
|
|
42
|
+
local xsd_file="${3:-.aether/schemas/pheromone.xsd}"
|
|
43
|
+
|
|
44
|
+
[[ -z "$json_file" ]] && { xml_json_err "MISSING_ARG" "Missing JSON file argument"; return 1; }
|
|
45
|
+
[[ -f "$json_file" ]] || { xml_json_err "FILE_NOT_FOUND" "JSON file not found: $json_file"; return 1; }
|
|
46
|
+
|
|
47
|
+
# Validate JSON
|
|
48
|
+
if ! jq empty "$json_file" 2>/dev/null; then
|
|
49
|
+
xml_json_err "PARSE_ERROR" "Invalid JSON file: $json_file"
|
|
50
|
+
return 1
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
# Generate ISO timestamp
|
|
54
|
+
local generated_at
|
|
55
|
+
generated_at=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
56
|
+
|
|
57
|
+
# Extract metadata
|
|
58
|
+
local version colony_id
|
|
59
|
+
version=$(jq -r '.version // "1.0.0"' "$json_file")
|
|
60
|
+
colony_id=$(jq -r '.colony_id // "unknown"' "$json_file")
|
|
61
|
+
|
|
62
|
+
# Build XML header
|
|
63
|
+
local xml_output
|
|
64
|
+
xml_output="<?xml version=\"1.0\" encoding=\"UTF-8\"?>
|
|
65
|
+
<pheromones xmlns=\"http://aether.colony/schemas/pheromones\"
|
|
66
|
+
xmlns:ph=\"http://aether.colony/schemas/pheromones\"
|
|
67
|
+
version=\"$version\"
|
|
68
|
+
generated_at=\"$generated_at\"
|
|
69
|
+
colony_id=\"$colony_id\">"
|
|
70
|
+
|
|
71
|
+
# Add metadata
|
|
72
|
+
local source_type context
|
|
73
|
+
source_type=$(jq -r '.metadata.source.type // "system"' "$json_file" 2>/dev/null || echo "system")
|
|
74
|
+
context=$(jq -r '.metadata.context // "Colony pheromone signals"' "$json_file" 2>/dev/null || echo "Colony pheromone signals")
|
|
75
|
+
|
|
76
|
+
xml_output="$xml_output
|
|
77
|
+
<metadata>
|
|
78
|
+
<source type=\"$source_type\">aether-pheromone-converter</source>
|
|
79
|
+
<context>$(echo "$context" | sed 's/&/\&/g; s/</\</g; s/>/\>/g')</context>
|
|
80
|
+
</metadata>"
|
|
81
|
+
|
|
82
|
+
# Process signals
|
|
83
|
+
local sig_array_length
|
|
84
|
+
sig_array_length=$(jq '.signals | length' "$json_file" 2>/dev/null || echo "0")
|
|
85
|
+
|
|
86
|
+
local sig_idx=0
|
|
87
|
+
while [[ $sig_idx -lt $sig_array_length ]]; do
|
|
88
|
+
local signal
|
|
89
|
+
signal=$(jq -c ".signals[$sig_idx]" "$json_file" 2>/dev/null)
|
|
90
|
+
[[ -n "$signal" ]] || { ((sig_idx++)); continue; }
|
|
91
|
+
|
|
92
|
+
# Extract signal fields
|
|
93
|
+
local sig_id sig_type priority source created_at expires_at active
|
|
94
|
+
sig_id=$(echo "$signal" | jq -r '.id // "sig_'"$(date +%s)"'_'"$sig_idx"'"')
|
|
95
|
+
sig_type=$(echo "$signal" | jq -r '.type // "FOCUS"' | tr '[:lower:]' '[:upper:]')
|
|
96
|
+
priority=$(echo "$signal" | jq -r '.priority // "normal"' | tr '[:upper:]' '[:lower:]')
|
|
97
|
+
source=$(echo "$signal" | jq -r '.source // "system"')
|
|
98
|
+
created_at=$(echo "$signal" | jq -r '.created_at // "'"$generated_at"'"')
|
|
99
|
+
expires_at=$(echo "$signal" | jq -r '.expires_at // empty')
|
|
100
|
+
active=$(echo "$signal" | jq -r '.active // true')
|
|
101
|
+
|
|
102
|
+
# Validate signal type
|
|
103
|
+
case "$sig_type" in
|
|
104
|
+
FOCUS|REDIRECT|FEEDBACK) ;;
|
|
105
|
+
*) sig_type="FOCUS" ;;
|
|
106
|
+
esac
|
|
107
|
+
|
|
108
|
+
# Validate priority
|
|
109
|
+
case "$priority" in
|
|
110
|
+
critical|high|normal|low) ;;
|
|
111
|
+
*) priority="normal" ;;
|
|
112
|
+
esac
|
|
113
|
+
|
|
114
|
+
# Build signal element
|
|
115
|
+
xml_output="$xml_output
|
|
116
|
+
<signal id=\"$(echo "$sig_id" | sed 's/&/\&/g; s/</\</g; s/>/\>/g; s/"/\"/g')\"
|
|
117
|
+
type=\"$sig_type\"
|
|
118
|
+
priority=\"$priority\"
|
|
119
|
+
source=\"$(echo "$source" | sed 's/&/\&/g; s/</\</g; s/>/\>/g; s/"/\"/g')\"
|
|
120
|
+
created_at=\"$created_at\""
|
|
121
|
+
|
|
122
|
+
[[ -n "$expires_at" && "$expires_at" != "null" ]] && xml_output="$xml_output
|
|
123
|
+
expires_at=\"$expires_at\""
|
|
124
|
+
|
|
125
|
+
xml_output="$xml_output
|
|
126
|
+
active=\"$active\">"
|
|
127
|
+
|
|
128
|
+
# Content section
|
|
129
|
+
# Handle both string content (.content = "text") and object content (.content.text = "text")
|
|
130
|
+
local content_text
|
|
131
|
+
content_text=$(echo "$signal" | jq -r 'if (.content | type) == "string" then .content elif .content.text then .content.text else .message // "" end')
|
|
132
|
+
if [[ -n "$content_text" ]]; then
|
|
133
|
+
xml_output="$xml_output
|
|
134
|
+
<content>
|
|
135
|
+
<text>$(echo "$content_text" | sed 's/&/\&/g; s/</\</g; s/>/\>/g')</text>
|
|
136
|
+
</content>"
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
xml_output="$xml_output
|
|
140
|
+
</signal>"
|
|
141
|
+
|
|
142
|
+
((sig_idx++))
|
|
143
|
+
done
|
|
144
|
+
|
|
145
|
+
xml_output="$xml_output
|
|
146
|
+
</pheromones>"
|
|
147
|
+
|
|
148
|
+
# Validate against schema if available
|
|
149
|
+
local validated=false
|
|
150
|
+
if [[ -f "$xsd_file" && "$XMLLINT_AVAILABLE" == "true" ]]; then
|
|
151
|
+
local temp_xml
|
|
152
|
+
temp_xml=$(mktemp)
|
|
153
|
+
echo "$xml_output" > "$temp_xml"
|
|
154
|
+
if xmllint --nonet --noent --noout --schema "$xsd_file" "$temp_xml" 2>/dev/null; then
|
|
155
|
+
validated=true
|
|
156
|
+
fi
|
|
157
|
+
rm -f "$temp_xml"
|
|
158
|
+
fi
|
|
159
|
+
|
|
160
|
+
# Output result
|
|
161
|
+
if [[ -n "$output_xml" ]]; then
|
|
162
|
+
echo "$xml_output" > "$output_xml"
|
|
163
|
+
xml_json_ok "{\"path\":\"$output_xml\",\"validated\":$validated}"
|
|
164
|
+
else
|
|
165
|
+
local escaped_xml
|
|
166
|
+
escaped_xml=$(echo "$xml_output" | jq -Rs '.')
|
|
167
|
+
xml_json_ok "{\"xml\":$escaped_xml,\"validated\":$validated}"
|
|
168
|
+
fi
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
# ============================================================================
|
|
172
|
+
# Pheromone Import (XML to JSON)
|
|
173
|
+
# ============================================================================
|
|
174
|
+
|
|
175
|
+
# xml-pheromone-import: Convert pheromone XML back to JSON
|
|
176
|
+
# Usage: xml-pheromone-import <pheromone_xml_file> [output_json_file]
|
|
177
|
+
# Returns: {"ok":true,"result":{"json":"...","signals":N,"path":"..."}}
|
|
178
|
+
xml-pheromone-import() {
|
|
179
|
+
local xml_file="${1:-}"
|
|
180
|
+
local output_json="${2:-}"
|
|
181
|
+
local preserve_prefixes="${3:-false}"
|
|
182
|
+
|
|
183
|
+
[[ -z "$xml_file" ]] && { xml_json_err "MISSING_ARG" "Missing XML file argument"; return 1; }
|
|
184
|
+
[[ -f "$xml_file" ]] || { xml_json_err "FILE_NOT_FOUND" "XML file not found: $xml_file"; return 1; }
|
|
185
|
+
|
|
186
|
+
# Check well-formedness
|
|
187
|
+
xmllint --nonet --noent --noout "$xml_file" 2>/dev/null || {
|
|
188
|
+
xml_json_err "PARSE_ERROR" "XML is not well-formed"
|
|
189
|
+
return 1
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
# Extract metadata using XPath
|
|
193
|
+
local version colony_id generated_at
|
|
194
|
+
if [[ "$XMLLINT_AVAILABLE" == "true" ]]; then
|
|
195
|
+
version=$(xmllint --nonet --noent --xpath "string(/*/@version)" "$xml_file" 2>/dev/null || echo "1.0.0")
|
|
196
|
+
colony_id=$(xmllint --nonet --noent --xpath "string(/*/@colony_id)" "$xml_file" 2>/dev/null || echo "unknown")
|
|
197
|
+
generated_at=$(xmllint --nonet --noent --xpath "string(/*/@generated_at)" "$xml_file" 2>/dev/null || echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ")")
|
|
198
|
+
else
|
|
199
|
+
xml_json_err "TOOL_NOT_AVAILABLE" "xmllint required for XML import"
|
|
200
|
+
return 1
|
|
201
|
+
fi
|
|
202
|
+
|
|
203
|
+
# Build JSON structure
|
|
204
|
+
local json_output
|
|
205
|
+
json_output=$(jq -n \
|
|
206
|
+
--arg version "$version" \
|
|
207
|
+
--arg colony_id "$colony_id" \
|
|
208
|
+
--arg generated_at "$generated_at" \
|
|
209
|
+
'{
|
|
210
|
+
version: $version,
|
|
211
|
+
colony_id: $colony_id,
|
|
212
|
+
generated_at: $generated_at,
|
|
213
|
+
signals: []
|
|
214
|
+
}')
|
|
215
|
+
|
|
216
|
+
# Extract signals - use xmlstarlet if available, fallback to grep/awk
|
|
217
|
+
if [[ "$XMLSTARLET_AVAILABLE" == "true" ]]; then
|
|
218
|
+
# Use xmlstarlet for proper namespace handling
|
|
219
|
+
local signals_json
|
|
220
|
+
signals_json=$(xmlstarlet sel -N ph="http://aether.colony/schemas/pheromones" \
|
|
221
|
+
-t -m "//ph:signal" \
|
|
222
|
+
-o '{"id":"' -v "@id" -o '","type":"' -v "@type" -o '","priority":"' -v "@priority" -o '","source":"' -v "@source" -o '","created_at":"' -v "@created_at" -o '","active":' -v "@active" -o '}' \
|
|
223
|
+
-n "$xml_file" 2>/dev/null | jq -s '.')
|
|
224
|
+
|
|
225
|
+
# Extract content text for each signal
|
|
226
|
+
local idx=0
|
|
227
|
+
local enriched_signals="[]"
|
|
228
|
+
while true; do
|
|
229
|
+
local content_text
|
|
230
|
+
content_text=$(xmlstarlet sel -N ph="http://aether.colony/schemas/pheromones" \
|
|
231
|
+
-t -v "//ph:signal[$idx + 1]/ph:content/ph:text" "$xml_file" 2>/dev/null || echo "")
|
|
232
|
+
|
|
233
|
+
if [[ -z "$content_text" && $idx -gt 0 ]]; then
|
|
234
|
+
break
|
|
235
|
+
fi
|
|
236
|
+
|
|
237
|
+
# Add content to signal
|
|
238
|
+
enriched_signals=$(echo "$signals_json" | jq --arg idx "$idx" --arg text "$content_text" '
|
|
239
|
+
.[$idx | tonumber] |= . + {content: {text: $text}}'
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
((idx++))
|
|
243
|
+
[[ $idx -gt 100 ]] && break # Safety limit
|
|
244
|
+
done
|
|
245
|
+
|
|
246
|
+
# Merge signals into output
|
|
247
|
+
if [[ "$enriched_signals" != "[]" ]]; then
|
|
248
|
+
json_output=$(echo "$json_output" | jq --argjson signals "$enriched_signals" '.signals = $signals')
|
|
249
|
+
else
|
|
250
|
+
json_output=$(echo "$json_output" | jq --argjson signals "$signals_json" '.signals = $signals')
|
|
251
|
+
fi
|
|
252
|
+
else
|
|
253
|
+
# Fallback: basic extraction with grep/sed
|
|
254
|
+
local fallback_signals="[]"
|
|
255
|
+
while IFS= read -r line; do
|
|
256
|
+
if [[ "$line" =~ id=\"([^\"]+)\" ]]; then
|
|
257
|
+
local sid="${BASH_REMATCH[1]}"
|
|
258
|
+
local stype="FOCUS"
|
|
259
|
+
local spriority="normal"
|
|
260
|
+
|
|
261
|
+
# Try to extract type and priority
|
|
262
|
+
if [[ "$line" =~ type=\"([^\"]+)\" ]]; then
|
|
263
|
+
stype="${BASH_REMATCH[1]}"
|
|
264
|
+
fi
|
|
265
|
+
if [[ "$line" =~ priority=\"([^\"]+)\" ]]; then
|
|
266
|
+
spriority="${BASH_REMATCH[1]}"
|
|
267
|
+
fi
|
|
268
|
+
|
|
269
|
+
# Remove namespace prefix if not preserving
|
|
270
|
+
if [[ "$preserve_prefixes" != "true" ]]; then
|
|
271
|
+
sid=$(echo "$sid" | sed 's/^[^:]*://')
|
|
272
|
+
fi
|
|
273
|
+
|
|
274
|
+
fallback_signals=$(echo "$fallback_signals" | jq \
|
|
275
|
+
--arg id "$sid" \
|
|
276
|
+
--arg type "$stype" \
|
|
277
|
+
--arg priority "$spriority" \
|
|
278
|
+
'. + [{id: $id, type: $type, priority: $priority, source: "xml-import", created_at: "'"$generated_at"'", active: true}]')
|
|
279
|
+
fi
|
|
280
|
+
done < <(grep '<signal' "$xml_file")
|
|
281
|
+
|
|
282
|
+
json_output=$(echo "$json_output" | jq --argjson signals "$fallback_signals" '.signals = $signals')
|
|
283
|
+
fi
|
|
284
|
+
|
|
285
|
+
local signal_count
|
|
286
|
+
signal_count=$(echo "$json_output" | jq '.signals | length')
|
|
287
|
+
|
|
288
|
+
# Output result
|
|
289
|
+
if [[ -n "$output_json" ]]; then
|
|
290
|
+
echo "$json_output" > "$output_json"
|
|
291
|
+
xml_json_ok "{\"path\":\"$output_json\",\"signals\":$signal_count}"
|
|
292
|
+
else
|
|
293
|
+
local escaped_json
|
|
294
|
+
escaped_json=$(echo "$json_output" | jq -Rs '.')
|
|
295
|
+
xml_json_ok "{\"json\":$escaped_json,\"signals\":$signal_count}"
|
|
296
|
+
fi
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
# ============================================================================
|
|
300
|
+
# Pheromone Merge (Multiple Colonies)
|
|
301
|
+
# ============================================================================
|
|
302
|
+
|
|
303
|
+
# xml-pheromone-merge: Merge pheromone XML from multiple colonies
|
|
304
|
+
# Usage: xml-pheromone-merge <output_xml> <input_xml_files...>
|
|
305
|
+
# Options:
|
|
306
|
+
# --namespace <prefix> - Add colony prefix to signal IDs (default: auto-generate from colony_id)
|
|
307
|
+
# --deduplicate - Remove duplicate signals by ID (default: true)
|
|
308
|
+
# --target <path> - Target output file (default: ~/.aether/eternal/pheromones.xml)
|
|
309
|
+
# Returns: {"ok":true,"result":{"path":"...","signals":N,"colonies":M}}
|
|
310
|
+
xml-pheromone-merge() {
|
|
311
|
+
local output_file=""
|
|
312
|
+
local namespace_prefix=""
|
|
313
|
+
local deduplicate=true
|
|
314
|
+
local input_files=()
|
|
315
|
+
local arg_idx=0
|
|
316
|
+
|
|
317
|
+
# Parse arguments
|
|
318
|
+
while [[ $arg_idx -lt $# ]]; do
|
|
319
|
+
local arg="${*:$((arg_idx + 1)):1}"
|
|
320
|
+
case "$arg" in
|
|
321
|
+
--namespace)
|
|
322
|
+
namespace_prefix="${*:$((arg_idx + 2)):1}"
|
|
323
|
+
((arg_idx += 2))
|
|
324
|
+
;;
|
|
325
|
+
--no-deduplicate)
|
|
326
|
+
deduplicate=false
|
|
327
|
+
((arg_idx++))
|
|
328
|
+
;;
|
|
329
|
+
--deduplicate)
|
|
330
|
+
deduplicate=true
|
|
331
|
+
((arg_idx++))
|
|
332
|
+
;;
|
|
333
|
+
--target)
|
|
334
|
+
output_file="${*:$((arg_idx + 2)):1}"
|
|
335
|
+
((arg_idx += 2))
|
|
336
|
+
;;
|
|
337
|
+
-*)
|
|
338
|
+
xml_json_err "INVALID_ARG" "Unknown option: $arg"
|
|
339
|
+
return 1
|
|
340
|
+
;;
|
|
341
|
+
*)
|
|
342
|
+
if [[ -z "$output_file" ]]; then
|
|
343
|
+
output_file="$arg"
|
|
344
|
+
else
|
|
345
|
+
input_files+=("$arg")
|
|
346
|
+
fi
|
|
347
|
+
((arg_idx++))
|
|
348
|
+
;;
|
|
349
|
+
esac
|
|
350
|
+
done
|
|
351
|
+
|
|
352
|
+
# Default output path
|
|
353
|
+
[[ -z "$output_file" ]] && output_file="${HOME}/.aether/eternal/pheromones.xml"
|
|
354
|
+
|
|
355
|
+
# Validate input files
|
|
356
|
+
if [[ ${#input_files[@]} -eq 0 ]]; then
|
|
357
|
+
xml_json_err "MISSING_ARG" "No input XML files specified"
|
|
358
|
+
return 1
|
|
359
|
+
fi
|
|
360
|
+
|
|
361
|
+
for file in "${input_files[@]}"; do
|
|
362
|
+
[[ -f "$file" ]] || { xml_json_err "FILE_NOT_FOUND" "Input file not found: $file"; return 1; }
|
|
363
|
+
done
|
|
364
|
+
|
|
365
|
+
# Ensure output directory exists
|
|
366
|
+
mkdir -p "$(dirname "$output_file")"
|
|
367
|
+
|
|
368
|
+
# Generate merged XML
|
|
369
|
+
local generated_at
|
|
370
|
+
generated_at=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
371
|
+
|
|
372
|
+
local merged_xml="<?xml version=\"1.0\" encoding=\"UTF-8\"?>
|
|
373
|
+
<pheromones xmlns=\"http://aether.colony/schemas/pheromones\"
|
|
374
|
+
xmlns:ph=\"http://aether.colony/schemas/pheromones\"
|
|
375
|
+
version=\"1.0.0\"
|
|
376
|
+
generated_at=\"$generated_at\"
|
|
377
|
+
colony_id=\"merged\">"
|
|
378
|
+
|
|
379
|
+
merged_xml="$merged_xml
|
|
380
|
+
<metadata>
|
|
381
|
+
<source type=\"system\">aether-pheromone-merge</source>
|
|
382
|
+
<context>Merged pheromones from ${#input_files[@]} colonies</context>
|
|
383
|
+
</metadata>"
|
|
384
|
+
|
|
385
|
+
# Track unique signal IDs for deduplication
|
|
386
|
+
declare -A seen_ids
|
|
387
|
+
local total_signals=0
|
|
388
|
+
local unique_signals=0
|
|
389
|
+
local colonies_merged=0
|
|
390
|
+
|
|
391
|
+
for input_file in "${input_files[@]}"; do
|
|
392
|
+
# Get colony ID from source file
|
|
393
|
+
local source_colony_id
|
|
394
|
+
if [[ "$XMLLINT_AVAILABLE" == "true" ]]; then
|
|
395
|
+
source_colony_id=$(xmllint --nonet --noent --xpath "string(/*/@colony_id)" "$input_file" 2>/dev/null || echo "colony_$colonies_merged")
|
|
396
|
+
else
|
|
397
|
+
source_colony_id=$(grep -o 'colony_id="[^"]*"' "$input_file" | head -1 | cut -d'"' -f2 || echo "colony_$colonies_merged")
|
|
398
|
+
fi
|
|
399
|
+
|
|
400
|
+
# Determine prefix for this colony
|
|
401
|
+
local colony_prefix
|
|
402
|
+
if [[ -n "$namespace_prefix" ]]; then
|
|
403
|
+
colony_prefix="$namespace_prefix"
|
|
404
|
+
else
|
|
405
|
+
colony_prefix="$source_colony_id"
|
|
406
|
+
fi
|
|
407
|
+
|
|
408
|
+
# Extract signals from this file using xmlstarlet
|
|
409
|
+
if [[ "$XMLSTARLET_AVAILABLE" == "true" ]]; then
|
|
410
|
+
# Get signal count
|
|
411
|
+
local sig_count
|
|
412
|
+
sig_count=$(xmlstarlet sel -N ph="http://aether.colony/schemas/pheromones" \
|
|
413
|
+
-t -v "count(//ph:signal)" "$input_file" 2>/dev/null || echo "0")
|
|
414
|
+
|
|
415
|
+
local idx=1
|
|
416
|
+
while [[ $idx -le $sig_count ]]; do
|
|
417
|
+
# Extract full signal element
|
|
418
|
+
local sig_xml
|
|
419
|
+
sig_xml=$(xmlstarlet sel -N ph="http://aether.colony/schemas/pheromones" \
|
|
420
|
+
-t -c "//ph:signal[$idx]" "$input_file" 2>/dev/null)
|
|
421
|
+
|
|
422
|
+
if [[ -n "$sig_xml" ]]; then
|
|
423
|
+
# Extract original ID
|
|
424
|
+
local orig_id
|
|
425
|
+
orig_id=$(echo "$sig_xml" | grep -oE 'id="[^"]+"' | head -1 | cut -d'"' -f2)
|
|
426
|
+
local new_id="${colony_prefix}:${orig_id}"
|
|
427
|
+
|
|
428
|
+
((total_signals++))
|
|
429
|
+
|
|
430
|
+
# Check for duplicates
|
|
431
|
+
if [[ "$deduplicate" == "true" ]]; then
|
|
432
|
+
if [[ -n "${seen_ids[$new_id]:-}" ]]; then
|
|
433
|
+
((idx++))
|
|
434
|
+
continue
|
|
435
|
+
fi
|
|
436
|
+
seen_ids[$new_id]=1
|
|
437
|
+
fi
|
|
438
|
+
|
|
439
|
+
# Replace ID with prefixed version
|
|
440
|
+
sig_xml=$(echo "$sig_xml" | sed "s/id=\"$orig_id\"/id=\"$new_id\"/")
|
|
441
|
+
|
|
442
|
+
# Add signal to merged XML
|
|
443
|
+
merged_xml="$merged_xml
|
|
444
|
+
$sig_xml"
|
|
445
|
+
((unique_signals++))
|
|
446
|
+
fi
|
|
447
|
+
((idx++))
|
|
448
|
+
done
|
|
449
|
+
else
|
|
450
|
+
# Fallback: extract with awk and sed
|
|
451
|
+
local sig_block=""
|
|
452
|
+
local in_signal=false
|
|
453
|
+
while IFS= read -r line; do
|
|
454
|
+
if echo "$line" | grep -qE '^[[:space:]]*<signal[[:space:]]'; then
|
|
455
|
+
in_signal=true
|
|
456
|
+
sig_block="$line"
|
|
457
|
+
# Extract and prefix ID
|
|
458
|
+
if [[ "$line" =~ id=\"([^\"]+)\" ]]; then
|
|
459
|
+
local orig_id="${BASH_REMATCH[1]}"
|
|
460
|
+
local new_id="${colony_prefix}:${orig_id}"
|
|
461
|
+
line=$(echo "$line" | sed "s/id=\"$orig_id\"/id=\"$new_id\"/")
|
|
462
|
+
fi
|
|
463
|
+
elif [[ "$in_signal" == true ]]; then
|
|
464
|
+
sig_block="$sig_block
|
|
465
|
+
$line"
|
|
466
|
+
if echo "$line" | grep -qE '</signal>'; then
|
|
467
|
+
# Process complete signal
|
|
468
|
+
local signal_id
|
|
469
|
+
if [[ "$sig_block" =~ id=\"([^\"]+)\" ]]; then
|
|
470
|
+
signal_id="${BASH_REMATCH[1]}"
|
|
471
|
+
((total_signals++))
|
|
472
|
+
|
|
473
|
+
# Check for duplicates
|
|
474
|
+
if [[ "$deduplicate" == "true" ]]; then
|
|
475
|
+
if [[ -n "${seen_ids[$signal_id]:-}" ]]; then
|
|
476
|
+
in_signal=false
|
|
477
|
+
sig_block=""
|
|
478
|
+
continue
|
|
479
|
+
fi
|
|
480
|
+
seen_ids[$signal_id]=1
|
|
481
|
+
fi
|
|
482
|
+
|
|
483
|
+
# Add signal to merged XML
|
|
484
|
+
merged_xml="$merged_xml
|
|
485
|
+
$sig_block"
|
|
486
|
+
((unique_signals++))
|
|
487
|
+
fi
|
|
488
|
+
in_signal=false
|
|
489
|
+
sig_block=""
|
|
490
|
+
fi
|
|
491
|
+
fi
|
|
492
|
+
done < "$input_file"
|
|
493
|
+
fi
|
|
494
|
+
|
|
495
|
+
((colonies_merged++))
|
|
496
|
+
done
|
|
497
|
+
|
|
498
|
+
# Close root element
|
|
499
|
+
merged_xml="$merged_xml
|
|
500
|
+
</pheromones>"
|
|
501
|
+
|
|
502
|
+
# Write output
|
|
503
|
+
echo "$merged_xml" > "$output_file"
|
|
504
|
+
|
|
505
|
+
xml_json_ok "{\"path\":\"$output_file\",\"signals\":$unique_signals,\"colonies\":$colonies_merged,\"duplicates_removed\":$((total_signals - unique_signals))}"
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
# ============================================================================
|
|
509
|
+
# Pheromone Validation
|
|
510
|
+
# ============================================================================
|
|
511
|
+
|
|
512
|
+
# xml-pheromone-validate: Validate pheromone XML against schema
|
|
513
|
+
# Usage: xml-pheromone-validate <pheromone_xml> [xsd_schema]
|
|
514
|
+
# Returns: {"ok":true,"result":{"valid":true,"errors":[]}}
|
|
515
|
+
xml-pheromone-validate() {
|
|
516
|
+
local xml_file="${1:-}"
|
|
517
|
+
local xsd_file="${2:-.aether/schemas/pheromone.xsd}"
|
|
518
|
+
|
|
519
|
+
[[ -z "$xml_file" ]] && { xml_json_err "MISSING_ARG" "Missing XML file argument"; return 1; }
|
|
520
|
+
[[ -f "$xml_file" ]] || { xml_json_err "FILE_NOT_FOUND" "XML file not found: $xml_file"; return 1; }
|
|
521
|
+
|
|
522
|
+
if [[ "$XMLLINT_AVAILABLE" != "true" ]]; then
|
|
523
|
+
xml_json_err "TOOL_NOT_AVAILABLE" "xmllint required for validation"
|
|
524
|
+
return 1
|
|
525
|
+
fi
|
|
526
|
+
|
|
527
|
+
if [[ ! -f "$xsd_file" ]]; then
|
|
528
|
+
xml_json_err "SCHEMA_NOT_FOUND" "XSD schema not found: $xsd_file"
|
|
529
|
+
return 1
|
|
530
|
+
fi
|
|
531
|
+
|
|
532
|
+
local errors
|
|
533
|
+
errors=$(xmllint --nonet --noent --noout --schema "$xsd_file" "$xml_file" 2>&1) && {
|
|
534
|
+
xml_json_ok '{"valid":true,"errors":[]}'
|
|
535
|
+
return 0
|
|
536
|
+
} || {
|
|
537
|
+
local escaped_errors
|
|
538
|
+
escaped_errors=$(echo "$errors" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\t/\\t/g' | tr '\n' ' ')
|
|
539
|
+
xml_json_ok "{\"valid\":false,\"errors\":[\"$escaped_errors\"]}"
|
|
540
|
+
return 0
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
# ============================================================================
|
|
545
|
+
# Namespace Utilities
|
|
546
|
+
# ============================================================================
|
|
547
|
+
|
|
548
|
+
# xml-pheromone-prefix-id: Add namespace prefix to signal ID
|
|
549
|
+
# Usage: xml-pheromone-prefix-id <signal_id> <colony_prefix>
|
|
550
|
+
# Returns: Prefixed ID (direct output, not JSON)
|
|
551
|
+
xml-pheromone-prefix-id() {
|
|
552
|
+
local signal_id="${1:-}"
|
|
553
|
+
local colony_prefix="${2:-}"
|
|
554
|
+
|
|
555
|
+
[[ -z "$signal_id" ]] && { echo ""; return 1; }
|
|
556
|
+
[[ -z "$colony_prefix" ]] && { echo "$signal_id"; return 0; }
|
|
557
|
+
|
|
558
|
+
echo "${colony_prefix}:${signal_id}"
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
# xml-pheromone-deprefix-id: Remove namespace prefix from signal ID
|
|
562
|
+
# Usage: xml-pheromone-deprefix-id <prefixed_id>
|
|
563
|
+
# Returns: Original ID (direct output, not JSON)
|
|
564
|
+
xml-pheromone-deprefix-id() {
|
|
565
|
+
local prefixed_id="${1:-}"
|
|
566
|
+
|
|
567
|
+
[[ -z "$prefixed_id" ]] && { echo ""; return 1; }
|
|
568
|
+
|
|
569
|
+
# Extract ID after colon
|
|
570
|
+
echo "$prefixed_id" | sed 's/^[^:]*://'
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
# Export functions
|
|
574
|
+
export -f xml-pheromone-export xml-pheromone-import xml-pheromone-validate xml-pheromone-merge
|
|
575
|
+
export -f xml-pheromone-prefix-id xml-pheromone-deprefix-id
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<pheromones xmlns="http://aether.colony/schemas/pheromones"
|
|
3
|
+
xmlns:ph="http://aether.colony/schemas/pheromones"
|
|
4
|
+
version="1.0.0"
|
|
5
|
+
generated_at="2026-02-17T23:51:44Z"
|
|
6
|
+
colony_id="aether-dev">
|
|
7
|
+
<metadata>
|
|
8
|
+
<source type="system">aether-pheromone-converter</source>
|
|
9
|
+
<context>Colony pheromone signals</context>
|
|
10
|
+
</metadata>
|
|
11
|
+
<signal id="sig_focus_001"
|
|
12
|
+
type="FOCUS"
|
|
13
|
+
priority="normal"
|
|
14
|
+
source="user"
|
|
15
|
+
created_at="2026-02-16T10:00:00Z"
|
|
16
|
+
expires_at="2026-02-17T10:00:00Z"
|
|
17
|
+
active="true">
|
|
18
|
+
<content>
|
|
19
|
+
<text>XML migration and pheromone system implementation</text>
|
|
20
|
+
</content>
|
|
21
|
+
</signal>
|
|
22
|
+
<signal id="sig_redirect_001"
|
|
23
|
+
type="REDIRECT"
|
|
24
|
+
priority="high"
|
|
25
|
+
source="system"
|
|
26
|
+
created_at="2026-02-16T08:00:00Z"
|
|
27
|
+
expires_at="2026-03-16T08:00:00Z"
|
|
28
|
+
active="true">
|
|
29
|
+
<content>
|
|
30
|
+
<text>Avoid editing runtime/ directly - edit .aether/ instead</text>
|
|
31
|
+
</content>
|
|
32
|
+
</signal>
|
|
33
|
+
<signal id="sig_feedback_001"
|
|
34
|
+
type="FEEDBACK"
|
|
35
|
+
priority="low"
|
|
36
|
+
source="worker_builder"
|
|
37
|
+
created_at="2026-02-16T12:00:00Z"
|
|
38
|
+
active="true">
|
|
39
|
+
<content>
|
|
40
|
+
<text>Test coverage is good, continue maintaining 80%+ coverage</text>
|
|
41
|
+
</content>
|
|
42
|
+
</signal>
|
|
43
|
+
<signal id="sig_focus_1771366307000"
|
|
44
|
+
type="FOCUS"
|
|
45
|
+
priority="normal"
|
|
46
|
+
source="user"
|
|
47
|
+
created_at="2026-02-17T22:11:47Z"
|
|
48
|
+
expires_at="phase_end"
|
|
49
|
+
active="true">
|
|
50
|
+
<content>
|
|
51
|
+
<text>test area for pheromone unification</text>
|
|
52
|
+
</content>
|
|
53
|
+
</signal>
|
|
54
|
+
<signal id="sig_focus_1771366386000"
|
|
55
|
+
type="FOCUS"
|
|
56
|
+
priority="normal"
|
|
57
|
+
source="user"
|
|
58
|
+
created_at="2026-02-17T22:13:06Z"
|
|
59
|
+
expires_at="phase_end"
|
|
60
|
+
active="true">
|
|
61
|
+
<content>
|
|
62
|
+
<text>test area</text>
|
|
63
|
+
</content>
|
|
64
|
+
</signal>
|
|
65
|
+
<signal id="sig_redirect_1771366398000"
|
|
66
|
+
type="REDIRECT"
|
|
67
|
+
priority="high"
|
|
68
|
+
source="user"
|
|
69
|
+
created_at="2026-02-17T22:13:18Z"
|
|
70
|
+
expires_at="phase_end"
|
|
71
|
+
active="true">
|
|
72
|
+
<content>
|
|
73
|
+
<text>avoid direct runtime edits</text>
|
|
74
|
+
</content>
|
|
75
|
+
</signal>
|
|
76
|
+
<signal id="sig_feedback_1771366398000"
|
|
77
|
+
type="FEEDBACK"
|
|
78
|
+
priority="low"
|
|
79
|
+
source="user"
|
|
80
|
+
created_at="2026-02-17T22:13:18Z"
|
|
81
|
+
expires_at="phase_end"
|
|
82
|
+
active="true">
|
|
83
|
+
<content>
|
|
84
|
+
<text>keep commits small</text>
|
|
85
|
+
</content>
|
|
86
|
+
</signal>
|
|
87
|
+
</pheromones>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<queen-wisdom xmlns="http://aether.colony/schemas/queen-wisdom/1.0"
|
|
3
|
+
xmlns:qw="http://aether.colony/schemas/queen-wisdom/1.0">
|
|
4
|
+
<metadata>
|
|
5
|
+
<version>1.0.0</version>
|
|
6
|
+
<created>2026-02-18T01:48:47Z</created>
|
|
7
|
+
<modified>2026-02-18T01:48:47Z</modified>
|
|
8
|
+
<colony_id></colony_id>
|
|
9
|
+
</metadata>
|
|
10
|
+
<philosophies>
|
|
11
|
+
</philosophies>
|
|
12
|
+
<patterns>
|
|
13
|
+
</patterns>
|
|
14
|
+
</queen-wisdom>
|