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.
Files changed (207) hide show
  1. package/.aether/CONTEXT.md +160 -0
  2. package/.aether/QUEEN.md +84 -0
  3. package/.aether/aether-utils.sh +7749 -0
  4. package/.aether/docs/QUEEN-SYSTEM.md +211 -0
  5. package/.aether/docs/README.md +68 -0
  6. package/.aether/docs/caste-system.md +48 -0
  7. package/.aether/docs/disciplines/DISCIPLINES.md +93 -0
  8. package/.aether/docs/disciplines/coding-standards.md +197 -0
  9. package/.aether/docs/disciplines/debugging.md +207 -0
  10. package/.aether/docs/disciplines/learning.md +254 -0
  11. package/.aether/docs/disciplines/tdd.md +257 -0
  12. package/.aether/docs/disciplines/verification-loop.md +167 -0
  13. package/.aether/docs/disciplines/verification.md +116 -0
  14. package/.aether/docs/error-codes.md +268 -0
  15. package/.aether/docs/known-issues.md +233 -0
  16. package/.aether/docs/pheromones.md +205 -0
  17. package/.aether/docs/queen-commands.md +97 -0
  18. package/.aether/exchange/colony-registry.xml +11 -0
  19. package/.aether/exchange/pheromone-xml.sh +575 -0
  20. package/.aether/exchange/pheromones.xml +87 -0
  21. package/.aether/exchange/queen-wisdom.xml +14 -0
  22. package/.aether/exchange/registry-xml.sh +273 -0
  23. package/.aether/exchange/wisdom-xml.sh +319 -0
  24. package/.aether/midden/approach-changes.md +5 -0
  25. package/.aether/midden/build-failures.md +5 -0
  26. package/.aether/midden/test-failures.md +5 -0
  27. package/.aether/model-profiles.yaml +100 -0
  28. package/.aether/rules/aether-colony.md +134 -0
  29. package/.aether/schemas/aether-types.xsd +255 -0
  30. package/.aether/schemas/colony-registry.xsd +309 -0
  31. package/.aether/schemas/example-prompt-builder.xml +234 -0
  32. package/.aether/schemas/pheromone.xsd +163 -0
  33. package/.aether/schemas/prompt.xsd +416 -0
  34. package/.aether/schemas/queen-wisdom.xsd +325 -0
  35. package/.aether/schemas/worker-priming.xsd +276 -0
  36. package/.aether/templates/QUEEN.md.template +79 -0
  37. package/.aether/templates/colony-state-reset.jq.template +22 -0
  38. package/.aether/templates/colony-state.template.json +35 -0
  39. package/.aether/templates/constraints.template.json +9 -0
  40. package/.aether/templates/crowned-anthill.template.md +36 -0
  41. package/.aether/templates/handoff-build-error.template.md +30 -0
  42. package/.aether/templates/handoff-build-success.template.md +39 -0
  43. package/.aether/templates/handoff.template.md +40 -0
  44. package/.aether/templates/learning-observations.template.json +6 -0
  45. package/.aether/templates/midden.template.json +7 -0
  46. package/.aether/templates/pheromones.template.json +6 -0
  47. package/.aether/templates/session.template.json +9 -0
  48. package/.aether/utils/atomic-write.sh +219 -0
  49. package/.aether/utils/chamber-compare.sh +193 -0
  50. package/.aether/utils/chamber-utils.sh +297 -0
  51. package/.aether/utils/colorize-log.sh +132 -0
  52. package/.aether/utils/error-handler.sh +212 -0
  53. package/.aether/utils/file-lock.sh +158 -0
  54. package/.aether/utils/queen-to-md.xsl +395 -0
  55. package/.aether/utils/semantic-cli.sh +413 -0
  56. package/.aether/utils/spawn-tree.sh +428 -0
  57. package/.aether/utils/spawn-with-model.sh +56 -0
  58. package/.aether/utils/state-loader.sh +215 -0
  59. package/.aether/utils/swarm-display.sh +268 -0
  60. package/.aether/utils/watch-spawn-tree.sh +253 -0
  61. package/.aether/utils/xml-compose.sh +253 -0
  62. package/.aether/utils/xml-convert.sh +273 -0
  63. package/.aether/utils/xml-core.sh +186 -0
  64. package/.aether/utils/xml-query.sh +201 -0
  65. package/.aether/utils/xml-utils.sh +110 -0
  66. package/.aether/workers.md +765 -0
  67. package/.claude/agents/ant/aether-ambassador.md +264 -0
  68. package/.claude/agents/ant/aether-archaeologist.md +322 -0
  69. package/.claude/agents/ant/aether-auditor.md +266 -0
  70. package/.claude/agents/ant/aether-builder.md +187 -0
  71. package/.claude/agents/ant/aether-chaos.md +268 -0
  72. package/.claude/agents/ant/aether-chronicler.md +304 -0
  73. package/.claude/agents/ant/aether-gatekeeper.md +325 -0
  74. package/.claude/agents/ant/aether-includer.md +373 -0
  75. package/.claude/agents/ant/aether-keeper.md +271 -0
  76. package/.claude/agents/ant/aether-measurer.md +317 -0
  77. package/.claude/agents/ant/aether-probe.md +210 -0
  78. package/.claude/agents/ant/aether-queen.md +325 -0
  79. package/.claude/agents/ant/aether-route-setter.md +173 -0
  80. package/.claude/agents/ant/aether-sage.md +353 -0
  81. package/.claude/agents/ant/aether-scout.md +142 -0
  82. package/.claude/agents/ant/aether-surveyor-disciplines.md +416 -0
  83. package/.claude/agents/ant/aether-surveyor-nest.md +354 -0
  84. package/.claude/agents/ant/aether-surveyor-pathogens.md +288 -0
  85. package/.claude/agents/ant/aether-surveyor-provisions.md +359 -0
  86. package/.claude/agents/ant/aether-tracker.md +265 -0
  87. package/.claude/agents/ant/aether-watcher.md +244 -0
  88. package/.claude/agents/ant/aether-weaver.md +247 -0
  89. package/.claude/commands/ant/archaeology.md +341 -0
  90. package/.claude/commands/ant/build.md +1160 -0
  91. package/.claude/commands/ant/chaos.md +349 -0
  92. package/.claude/commands/ant/colonize.md +270 -0
  93. package/.claude/commands/ant/continue.md +1070 -0
  94. package/.claude/commands/ant/council.md +309 -0
  95. package/.claude/commands/ant/dream.md +265 -0
  96. package/.claude/commands/ant/entomb.md +487 -0
  97. package/.claude/commands/ant/feedback.md +78 -0
  98. package/.claude/commands/ant/flag.md +139 -0
  99. package/.claude/commands/ant/flags.md +155 -0
  100. package/.claude/commands/ant/focus.md +58 -0
  101. package/.claude/commands/ant/help.md +122 -0
  102. package/.claude/commands/ant/history.md +137 -0
  103. package/.claude/commands/ant/init.md +409 -0
  104. package/.claude/commands/ant/interpret.md +267 -0
  105. package/.claude/commands/ant/lay-eggs.md +201 -0
  106. package/.claude/commands/ant/maturity.md +102 -0
  107. package/.claude/commands/ant/memory-details.md +77 -0
  108. package/.claude/commands/ant/migrate-state.md +165 -0
  109. package/.claude/commands/ant/oracle.md +387 -0
  110. package/.claude/commands/ant/organize.md +227 -0
  111. package/.claude/commands/ant/pause-colony.md +247 -0
  112. package/.claude/commands/ant/phase.md +126 -0
  113. package/.claude/commands/ant/plan.md +544 -0
  114. package/.claude/commands/ant/redirect.md +58 -0
  115. package/.claude/commands/ant/resume-colony.md +182 -0
  116. package/.claude/commands/ant/resume.md +363 -0
  117. package/.claude/commands/ant/seal.md +306 -0
  118. package/.claude/commands/ant/status.md +272 -0
  119. package/.claude/commands/ant/swarm.md +361 -0
  120. package/.claude/commands/ant/tunnels.md +425 -0
  121. package/.claude/commands/ant/update.md +209 -0
  122. package/.claude/commands/ant/verify-castes.md +95 -0
  123. package/.claude/commands/ant/watch.md +238 -0
  124. package/.opencode/agents/aether-ambassador.md +140 -0
  125. package/.opencode/agents/aether-archaeologist.md +108 -0
  126. package/.opencode/agents/aether-auditor.md +144 -0
  127. package/.opencode/agents/aether-builder.md +184 -0
  128. package/.opencode/agents/aether-chaos.md +115 -0
  129. package/.opencode/agents/aether-chronicler.md +122 -0
  130. package/.opencode/agents/aether-gatekeeper.md +116 -0
  131. package/.opencode/agents/aether-includer.md +117 -0
  132. package/.opencode/agents/aether-keeper.md +177 -0
  133. package/.opencode/agents/aether-measurer.md +128 -0
  134. package/.opencode/agents/aether-probe.md +133 -0
  135. package/.opencode/agents/aether-queen.md +286 -0
  136. package/.opencode/agents/aether-route-setter.md +130 -0
  137. package/.opencode/agents/aether-sage.md +106 -0
  138. package/.opencode/agents/aether-scout.md +101 -0
  139. package/.opencode/agents/aether-surveyor-disciplines.md +386 -0
  140. package/.opencode/agents/aether-surveyor-nest.md +324 -0
  141. package/.opencode/agents/aether-surveyor-pathogens.md +259 -0
  142. package/.opencode/agents/aether-surveyor-provisions.md +329 -0
  143. package/.opencode/agents/aether-tracker.md +137 -0
  144. package/.opencode/agents/aether-watcher.md +174 -0
  145. package/.opencode/agents/aether-weaver.md +130 -0
  146. package/.opencode/commands/ant/archaeology.md +338 -0
  147. package/.opencode/commands/ant/build.md +1200 -0
  148. package/.opencode/commands/ant/chaos.md +346 -0
  149. package/.opencode/commands/ant/colonize.md +202 -0
  150. package/.opencode/commands/ant/continue.md +938 -0
  151. package/.opencode/commands/ant/council.md +305 -0
  152. package/.opencode/commands/ant/dream.md +262 -0
  153. package/.opencode/commands/ant/entomb.md +367 -0
  154. package/.opencode/commands/ant/feedback.md +80 -0
  155. package/.opencode/commands/ant/flag.md +137 -0
  156. package/.opencode/commands/ant/flags.md +153 -0
  157. package/.opencode/commands/ant/focus.md +56 -0
  158. package/.opencode/commands/ant/help.md +124 -0
  159. package/.opencode/commands/ant/history.md +127 -0
  160. package/.opencode/commands/ant/init.md +337 -0
  161. package/.opencode/commands/ant/interpret.md +256 -0
  162. package/.opencode/commands/ant/lay-eggs.md +141 -0
  163. package/.opencode/commands/ant/maturity.md +92 -0
  164. package/.opencode/commands/ant/memory-details.md +77 -0
  165. package/.opencode/commands/ant/migrate-state.md +153 -0
  166. package/.opencode/commands/ant/oracle.md +338 -0
  167. package/.opencode/commands/ant/organize.md +224 -0
  168. package/.opencode/commands/ant/pause-colony.md +220 -0
  169. package/.opencode/commands/ant/phase.md +123 -0
  170. package/.opencode/commands/ant/plan.md +531 -0
  171. package/.opencode/commands/ant/redirect.md +67 -0
  172. package/.opencode/commands/ant/resume-colony.md +178 -0
  173. package/.opencode/commands/ant/resume.md +363 -0
  174. package/.opencode/commands/ant/seal.md +247 -0
  175. package/.opencode/commands/ant/status.md +272 -0
  176. package/.opencode/commands/ant/swarm.md +357 -0
  177. package/.opencode/commands/ant/tunnels.md +406 -0
  178. package/.opencode/commands/ant/update.md +191 -0
  179. package/.opencode/commands/ant/verify-castes.md +85 -0
  180. package/.opencode/commands/ant/watch.md +220 -0
  181. package/.opencode/opencode.json +3 -0
  182. package/CHANGELOG.md +325 -0
  183. package/DISCLAIMER.md +74 -0
  184. package/LICENSE +21 -0
  185. package/README.md +258 -0
  186. package/bin/cli.js +2436 -0
  187. package/bin/generate-commands.sh +291 -0
  188. package/bin/lib/caste-colors.js +57 -0
  189. package/bin/lib/colors.js +76 -0
  190. package/bin/lib/errors.js +255 -0
  191. package/bin/lib/event-types.js +190 -0
  192. package/bin/lib/file-lock.js +695 -0
  193. package/bin/lib/init.js +454 -0
  194. package/bin/lib/logger.js +242 -0
  195. package/bin/lib/model-profiles.js +445 -0
  196. package/bin/lib/model-verify.js +288 -0
  197. package/bin/lib/nestmate-loader.js +130 -0
  198. package/bin/lib/proxy-health.js +253 -0
  199. package/bin/lib/spawn-logger.js +266 -0
  200. package/bin/lib/state-guard.js +602 -0
  201. package/bin/lib/state-sync.js +516 -0
  202. package/bin/lib/telemetry.js +441 -0
  203. package/bin/lib/update-transaction.js +1454 -0
  204. package/bin/npx-install.js +178 -0
  205. package/bin/sync-to-runtime.sh +6 -0
  206. package/bin/validate-package.sh +88 -0
  207. package/package.json +70 -0
@@ -0,0 +1,413 @@
1
+ #!/bin/bash
2
+ # Semantic CLI - Shell interface to Python semantic layer
3
+ #
4
+ # Provides semantic search and indexing capabilities for Aether colony.
5
+ # Uses Python semantic_layer.py for embeddings and similarity search.
6
+ #
7
+ # Usage:
8
+ # source .aether/utils/semantic-cli.sh
9
+ # semantic-init # Initialize semantic store
10
+ # semantic-index "text" # Add text to index
11
+ # semantic-search "query" # Find similar entries
12
+ # semantic-rebuild # Rebuild from all sources
13
+
14
+ # Only set strict mode when executed directly, not when sourced
15
+ if [[ "${BASH_SOURCE[0]:-$0}" == "${0}" ]]; then
16
+ set -euo pipefail
17
+ fi
18
+
19
+ # Get script directory for relative paths
20
+ # Fallback for when BASH_SOURCE isn't set (non-interactive sourcing)
21
+ if [[ -n "${BASH_SOURCE[0]:-}" ]]; then
22
+ SEMANTIC_CLI_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
23
+ else
24
+ # Try to find .aether directory from current location
25
+ if [[ -d ".aether" ]]; then
26
+ SEMANTIC_CLI_DIR="$(pwd)/.aether/utils"
27
+ elif [[ -d "../.aether" ]]; then
28
+ SEMANTIC_CLI_DIR="$(cd .. && pwd)/.aether/utils"
29
+ else
30
+ # Last resort - use aether-utils.sh's detected AETHER_DIR if available
31
+ SEMANTIC_CLI_DIR="${AETHER_DIR:-$HOME/.aether/system}/utils"
32
+ fi
33
+ fi
34
+ AETHER_DIR="$(dirname "$SEMANTIC_CLI_DIR")"
35
+ PROJECT_ROOT="$(dirname "$AETHER_DIR")"
36
+
37
+ # Data directory for semantic store
38
+ SEMANTIC_DATA_DIR="${AETHER_DIR}/data/semantic"
39
+ SEMANTIC_EMBEDDINGS_FILE="${SEMANTIC_DATA_DIR}/embeddings.json"
40
+
41
+ # Check if Python dependencies are available
42
+ semantic-check-deps() {
43
+ python3 -c "import sys; sys.path.insert(0, '$AETHER_DIR'); from semantic_layer import EmbeddingModel; print('ok')" 2>/dev/null
44
+ }
45
+
46
+ # Initialize semantic store directory
47
+ semantic-init() {
48
+ mkdir -p "$SEMANTIC_DATA_DIR"
49
+
50
+ if [[ ! -f "$SEMANTIC_DATA_DIR/index.json" ]]; then
51
+ cat > "$SEMANTIC_DATA_DIR/index.json" << 'EOF'
52
+ {
53
+ "version": "1.0",
54
+ "entries": [],
55
+ "last_updated": null,
56
+ "stats": {
57
+ "total_entries": 0,
58
+ "by_source": {}
59
+ }
60
+ }
61
+ EOF
62
+ fi
63
+
64
+ if [[ ! -f "$SEMANTIC_EMBEDDINGS_FILE" ]]; then
65
+ echo '{"embeddings":{}}' > "$SEMANTIC_EMBEDDINGS_FILE"
66
+ fi
67
+ }
68
+
69
+ # Index a single text entry
70
+ # Usage: semantic-index <text> <source> [entry_id]
71
+ semantic-index() {
72
+ local text="${1:-}"
73
+ local source="${2:-unknown}"
74
+ local entry_id="${3:-}"
75
+
76
+ if [[ -z "$text" ]]; then
77
+ json_err 1 "semantic-index requires text argument"
78
+ return 1
79
+ fi
80
+
81
+ semantic-init
82
+
83
+ # Generate entry ID if not provided
84
+ if [[ -z "$entry_id" ]]; then
85
+ entry_id="${source}_$(date +%s)_$((RANDOM % 10000))"
86
+ fi
87
+
88
+ local timestamp
89
+ timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)
90
+
91
+ # Call Python to compute embedding and save everything
92
+ python3 << PYTHON_SCRIPT 2>/dev/null
93
+ import sys
94
+ import json
95
+ sys.path.insert(0, '$AETHER_DIR')
96
+ from semantic_layer import EmbeddingModel
97
+
98
+ # Compute embedding
99
+ model = EmbeddingModel()
100
+ embedding = model.encode('''$text''')
101
+
102
+ # Load existing embeddings
103
+ try:
104
+ with open('$SEMANTIC_EMBEDDINGS_FILE', 'r') as f:
105
+ emb_store = json.load(f)
106
+ except:
107
+ emb_store = {'embeddings': {}}
108
+
109
+ # Store embedding
110
+ emb_store['embeddings']['$entry_id'] = {
111
+ 'embedding': embedding,
112
+ 'text': '''$text''',
113
+ 'source': '$source',
114
+ 'indexed_at': '$timestamp'
115
+ }
116
+
117
+ # Save embeddings
118
+ with open('$SEMANTIC_EMBEDDINGS_FILE', 'w') as f:
119
+ json.dump(emb_store, f)
120
+
121
+ # Update index
122
+ try:
123
+ with open('$SEMANTIC_DATA_DIR/index.json', 'r') as f:
124
+ index = json.load(f)
125
+ except:
126
+ index = {'version': '1.0', 'entries': [], 'stats': {}}
127
+
128
+ index['entries'].append({
129
+ 'id': '$entry_id',
130
+ 'source': '$source',
131
+ 'text_preview': '''${text:0:200}''',
132
+ 'indexed_at': '$timestamp'
133
+ })
134
+ index['last_updated'] = '$timestamp'
135
+ index['stats']['total_entries'] = len(index['entries'])
136
+
137
+ by_source = {}
138
+ for e in index['entries']:
139
+ src = e.get('source', 'unknown')
140
+ by_source[src] = by_source.get(src, 0) + 1
141
+ index['stats']['by_source'] = by_source
142
+
143
+ with open('$SEMANTIC_DATA_DIR/index.json', 'w') as f:
144
+ json.dump(index, f, indent=2)
145
+
146
+ print(json.dumps({
147
+ 'ok': True,
148
+ 'entry_id': '$entry_id',
149
+ 'embedding_dim': len(embedding),
150
+ 'source': '$source'
151
+ }))
152
+ PYTHON_SCRIPT
153
+ }
154
+
155
+ # Search for similar entries
156
+ # Usage: semantic-search <query> [top_k] [threshold] [source_filter]
157
+ semantic-search() {
158
+ local query="${1:-}"
159
+ local top_k="${2:-5}"
160
+ local threshold="${3:-0.5}"
161
+ local source_filter="${4:-}"
162
+
163
+ if [[ -z "$query" ]]; then
164
+ json_err 1 "semantic-search requires query argument"
165
+ return 1
166
+ fi
167
+
168
+ if [[ ! -f "$SEMANTIC_EMBEDDINGS_FILE" ]]; then
169
+ json_ok '{"results":[]}' "No semantic index found. Run semantic-init first."
170
+ return 0
171
+ fi
172
+
173
+ # Call Python to search
174
+ python3 << PYTHON_SCRIPT 2>/dev/null
175
+ import sys
176
+ import json
177
+ import math
178
+ sys.path.insert(0, '$AETHER_DIR')
179
+ from semantic_layer import EmbeddingModel
180
+
181
+ def cosine_similarity(v1, v2):
182
+ dot = sum(a*b for a,b in zip(v1, v2))
183
+ norm1 = math.sqrt(sum(a*a for a in v1))
184
+ norm2 = math.sqrt(sum(b*b for b in v2))
185
+ if norm1 == 0 or norm2 == 0:
186
+ return 0.0
187
+ return dot / (norm1 * norm2)
188
+
189
+ # Compute query embedding
190
+ model = EmbeddingModel()
191
+ query_emb = model.encode('''$query''')
192
+
193
+ # Load stored embeddings
194
+ with open('$SEMANTIC_EMBEDDINGS_FILE', 'r') as f:
195
+ emb_store = json.load(f)
196
+
197
+ # Search
198
+ results = []
199
+ for entry_id, data in emb_store.get('embeddings', {}).items():
200
+ # Source filter
201
+ source = data.get('source', '')
202
+ if '$source_filter' and source != '$source_filter':
203
+ continue
204
+
205
+ stored_emb = data.get('embedding', [])
206
+ if not stored_emb:
207
+ continue
208
+
209
+ similarity = cosine_similarity(query_emb, stored_emb)
210
+
211
+ if similarity >= $threshold:
212
+ results.append({
213
+ 'id': entry_id,
214
+ 'text': data.get('text', ''),
215
+ 'source': source,
216
+ 'similarity': round(similarity, 3),
217
+ 'indexed_at': data.get('indexed_at', '')
218
+ })
219
+
220
+ # Sort by similarity
221
+ results.sort(key=lambda x: x['similarity'], reverse=True)
222
+ results = results[:$top_k]
223
+
224
+ print(json.dumps({
225
+ 'ok': True,
226
+ 'query': '''$query''',
227
+ 'count': len(results),
228
+ 'results': results
229
+ }))
230
+ PYTHON_SCRIPT
231
+ }
232
+
233
+ # Find similar entries to check for duplicates
234
+ semantic-find-duplicate() {
235
+ local text="${1:-}"
236
+ local threshold="${2:-0.85}"
237
+
238
+ if [[ -z "$text" ]]; then
239
+ json_err 1 "semantic-find-duplicate requires text argument"
240
+ return 1
241
+ fi
242
+
243
+ local result
244
+ result=$(semantic-search "$text" 3 "$threshold")
245
+
246
+ local count
247
+ count=$(echo "$result" | jq -r '.count // 0')
248
+
249
+ if [[ "$count" -gt 0 ]]; then
250
+ echo "$result" | jq '. + {"is_duplicate": true}'
251
+ else
252
+ json_ok "[]" "No duplicates found"
253
+ fi
254
+ }
255
+
256
+ # Rebuild entire index from all Aether data sources
257
+ semantic-rebuild() {
258
+ echo "Rebuilding semantic index from all sources..."
259
+
260
+ # Reset
261
+ rm -rf "$SEMANTIC_DATA_DIR"/*
262
+ semantic-init
263
+
264
+ local count=0
265
+
266
+ # Index flags
267
+ if [[ -f "$AETHER_DIR/data/flags.json" ]]; then
268
+ echo " Indexing flags..."
269
+ local flags_json
270
+ flags_json=$(jq -c '.flags[]' "$AETHER_DIR/data/flags.json" 2>/dev/null || echo "")
271
+
272
+ while IFS= read -r flag; do
273
+ [[ -z "$flag" ]] && continue
274
+ local flag_id flag_title flag_desc
275
+ flag_id=$(echo "$flag" | jq -r '.id // empty')
276
+ flag_title=$(echo "$flag" | jq -r '.title // empty')
277
+ flag_desc=$(echo "$flag" | jq -r '.description // empty')
278
+
279
+ if [[ -n "$flag_title" ]]; then
280
+ semantic-index "$flag_title: $flag_desc" "flags" "$flag_id" >/dev/null 2>&1 || true
281
+ ((count++)) || true
282
+ fi
283
+ done <<< "$flags_json"
284
+ fi
285
+
286
+ # Index dreams
287
+ if [[ -d "$AETHER_DIR/dreams" ]]; then
288
+ echo " Indexing dreams..."
289
+ for dream in "$AETHER_DIR/dreams"/*.md; do
290
+ [[ -f "$dream" ]] || continue
291
+ local dream_id dream_content
292
+ dream_id=$(basename "$dream" .md)
293
+ dream_content=$(head -100 "$dream" | tr '\n' ' ')
294
+
295
+ if [[ -n "$dream_content" ]]; then
296
+ semantic-index "$dream_content" "dreams" "$dream_id" >/dev/null 2>&1 || true
297
+ ((count++)) || true
298
+ fi
299
+ done
300
+ fi
301
+
302
+ # Index pheromones
303
+ if [[ -f "$AETHER_DIR/data/pheromones.json" ]]; then
304
+ echo " Indexing pheromones..."
305
+ local signals_json
306
+ signals_json=$(jq -c '.signals[]' "$AETHER_DIR/data/pheromones.json" 2>/dev/null || echo "")
307
+
308
+ while IFS= read -r signal; do
309
+ [[ -z "$signal" ]] && continue
310
+ local sig_id sig_type sig_content
311
+ sig_id=$(echo "$signal" | jq -r '.id // empty')
312
+ sig_type=$(echo "$signal" | jq -r '.type // empty')
313
+ sig_content=$(echo "$signal" | jq -r '.content.text // .content // empty')
314
+
315
+ if [[ -n "$sig_content" ]]; then
316
+ semantic-index "[$sig_type] $sig_content" "pheromones" "$sig_id" >/dev/null 2>&1 || true
317
+ ((count++)) || true
318
+ fi
319
+ done <<< "$signals_json"
320
+ fi
321
+
322
+ # Index QUEEN.md if exists
323
+ if [[ -f "$AETHER_DIR/data/QUEEN.md" ]]; then
324
+ echo " Indexing QUEEN.md..."
325
+ local queen_content
326
+ queen_content=$(cat "$AETHER_DIR/data/QUEEN.md" | tr '\n' ' ')
327
+ semantic-index "$queen_content" "queen" "queen-wisdom" >/dev/null 2>&1 || true
328
+ ((count++)) || true
329
+ fi
330
+
331
+ echo "✅ Indexed $count entries"
332
+ jq -c '.stats' "$SEMANTIC_DATA_DIR/index.json"
333
+ }
334
+
335
+ # Get context relevant to a task (for worker injection)
336
+ semantic-get-context() {
337
+ local task="${1:-}"
338
+ local max_results="${2:-3}"
339
+
340
+ if [[ -z "$task" ]]; then
341
+ echo ""
342
+ return 0
343
+ fi
344
+
345
+ if ! semantic-check-deps >/dev/null 2>&1; then
346
+ echo ""
347
+ return 0
348
+ fi
349
+
350
+ local result
351
+ result=$(semantic-search "$task" "$max_results" 0.5 2>/dev/null || echo '{"results":[]}')
352
+
353
+ local count
354
+ count=$(echo "$result" | jq -r '.count // 0')
355
+
356
+ if [[ "$count" -eq 0 ]]; then
357
+ echo ""
358
+ return 0
359
+ fi
360
+
361
+ echo "---"
362
+ echo "## Relevant Context (semantic search)"
363
+ echo ""
364
+ echo "$result" | jq -r '.results[] | "### \(.source // "unknown") (similarity: \(.similarity))\n\(.text[:200] // .text)\n"'
365
+ echo "---"
366
+ }
367
+
368
+ # Check semantic layer status
369
+ semantic-status() {
370
+ if [[ ! -f "$SEMANTIC_DATA_DIR/index.json" ]]; then
371
+ json_ok '{"initialized": false, "message": "Run semantic-init to initialize"}'
372
+ return 0
373
+ fi
374
+
375
+ local deps_ok
376
+ if semantic-check-deps >/dev/null 2>&1; then
377
+ deps_ok="true"
378
+ else
379
+ deps_ok="false"
380
+ fi
381
+
382
+ local entry_count
383
+ entry_count=$(jq '.entries | length' "$SEMANTIC_DATA_DIR/index.json" 2>/dev/null || echo "0")
384
+
385
+ jq -n --arg deps_ok "$deps_ok" --arg entries "$entry_count" \
386
+ '{"initialized": true, "dependencies_ok": ($deps_ok == "true"), "total_entries": ($entries | tonumber)}'
387
+ }
388
+
389
+ # Helper: Output JSON OK response
390
+ json_ok() {
391
+ local result="${1:-}"
392
+ local message="${2:-}"
393
+ jq -n --argjson result "$result" --arg message "$message" \
394
+ '{"ok": true, "result": $result, "message": $message}'
395
+ }
396
+
397
+ # Helper: Output JSON error response
398
+ json_err() {
399
+ local code="${1:-1}"
400
+ local message="${2:-Unknown error}"
401
+ jq -n --arg code "$code" --arg message "$message" \
402
+ '{"ok": false, "error": {"code": $code, "message": $message}}'
403
+ }
404
+
405
+ # Export functions
406
+ export -f semantic-init
407
+ export -f semantic-index
408
+ export -f semantic-search
409
+ export -f semantic-find-duplicate
410
+ export -f semantic-rebuild
411
+ export -f semantic-get-context
412
+ export -f semantic-status
413
+ export -f semantic-check-deps