aether-colony 5.0.0 → 5.2.1
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/aether-utils.sh +3226 -3345
- package/.aether/agents-claude/aether-ambassador.md +265 -0
- package/.aether/agents-claude/aether-archaeologist.md +327 -0
- package/.aether/agents-claude/aether-architect.md +236 -0
- package/.aether/agents-claude/aether-auditor.md +271 -0
- package/.aether/agents-claude/aether-builder.md +224 -0
- package/.aether/agents-claude/aether-chaos.md +269 -0
- package/.aether/agents-claude/aether-chronicler.md +305 -0
- package/.aether/agents-claude/aether-gatekeeper.md +330 -0
- package/.aether/agents-claude/aether-includer.md +374 -0
- package/.aether/agents-claude/aether-keeper.md +272 -0
- package/.aether/agents-claude/aether-measurer.md +322 -0
- package/.aether/agents-claude/aether-oracle.md +237 -0
- package/.aether/agents-claude/aether-probe.md +211 -0
- package/.aether/agents-claude/aether-queen.md +330 -0
- package/.aether/agents-claude/aether-route-setter.md +178 -0
- package/.aether/agents-claude/aether-sage.md +418 -0
- package/.aether/agents-claude/aether-scout.md +179 -0
- package/.aether/agents-claude/aether-surveyor-disciplines.md +417 -0
- package/.aether/agents-claude/aether-surveyor-nest.md +355 -0
- package/.aether/agents-claude/aether-surveyor-pathogens.md +289 -0
- package/.aether/agents-claude/aether-surveyor-provisions.md +360 -0
- package/.aether/agents-claude/aether-tracker.md +270 -0
- package/.aether/agents-claude/aether-watcher.md +280 -0
- package/.aether/agents-claude/aether-weaver.md +248 -0
- package/.aether/commands/archaeology.yaml +653 -0
- package/.aether/commands/build.yaml +1221 -0
- package/.aether/commands/chaos.yaml +653 -0
- package/.aether/commands/colonize.yaml +442 -0
- package/.aether/commands/continue.yaml +1484 -0
- package/.aether/commands/council.yaml +509 -0
- package/.aether/commands/data-clean.yaml +80 -0
- package/.aether/commands/dream.yaml +275 -0
- package/.aether/commands/entomb.yaml +863 -0
- package/.aether/commands/export-signals.yaml +64 -0
- package/.aether/commands/feedback.yaml +158 -0
- package/.aether/commands/flag.yaml +160 -0
- package/.aether/commands/flags.yaml +177 -0
- package/.aether/commands/focus.yaml +112 -0
- package/.aether/commands/help.yaml +167 -0
- package/.aether/commands/history.yaml +137 -0
- package/.aether/commands/import-signals.yaml +79 -0
- package/.aether/commands/init.yaml +502 -0
- package/.aether/commands/insert-phase.yaml +102 -0
- package/.aether/commands/interpret.yaml +285 -0
- package/.aether/commands/lay-eggs.yaml +224 -0
- package/.aether/commands/maturity.yaml +122 -0
- package/.aether/commands/memory-details.yaml +74 -0
- package/.aether/commands/migrate-state.yaml +174 -0
- package/.aether/commands/oracle.yaml +1224 -0
- package/.aether/commands/organize.yaml +446 -0
- package/.aether/commands/patrol.yaml +621 -0
- package/.aether/commands/pause-colony.yaml +424 -0
- package/.aether/commands/phase.yaml +124 -0
- package/.aether/commands/pheromones.yaml +153 -0
- package/.aether/commands/plan.yaml +1364 -0
- package/.aether/commands/preferences.yaml +63 -0
- package/.aether/commands/quick.yaml +104 -0
- package/.aether/commands/redirect.yaml +123 -0
- package/.aether/commands/resume-colony.yaml +375 -0
- package/.aether/commands/resume.yaml +407 -0
- package/.aether/commands/run.yaml +229 -0
- package/.aether/commands/seal.yaml +1214 -0
- package/.aether/commands/skill-create.yaml +337 -0
- package/.aether/commands/status.yaml +408 -0
- package/.aether/commands/swarm.yaml +352 -0
- package/.aether/commands/tunnels.yaml +814 -0
- package/.aether/commands/update.yaml +131 -0
- package/.aether/commands/verify-castes.yaml +159 -0
- package/.aether/commands/watch.yaml +454 -0
- package/.aether/docs/INCIDENT_TEMPLATE.md +32 -0
- package/.aether/docs/QUEEN-SYSTEM.md +11 -11
- package/.aether/docs/README.md +32 -2
- package/.aether/docs/command-playbooks/README.md +23 -0
- package/.aether/docs/command-playbooks/build-complete.md +349 -0
- package/.aether/docs/command-playbooks/build-context.md +282 -0
- package/.aether/docs/command-playbooks/build-full.md +1683 -0
- package/.aether/docs/command-playbooks/build-prep.md +284 -0
- package/.aether/docs/command-playbooks/build-verify.md +405 -0
- package/.aether/docs/command-playbooks/build-wave.md +749 -0
- package/.aether/docs/command-playbooks/continue-advance.md +524 -0
- package/.aether/docs/command-playbooks/continue-finalize.md +447 -0
- package/.aether/docs/command-playbooks/continue-full.md +1725 -0
- package/.aether/docs/command-playbooks/continue-gates.md +686 -0
- package/.aether/docs/command-playbooks/continue-verify.md +407 -0
- package/.aether/docs/context-continuity.md +84 -0
- package/.aether/docs/disciplines/DISCIPLINES.md +9 -7
- package/.aether/docs/error-codes.md +1 -1
- package/.aether/docs/known-issues.md +34 -173
- package/.aether/docs/pheromones.md +86 -6
- package/.aether/docs/plans/pheromone-display-plan.md +257 -0
- package/.aether/docs/queen-commands.md +10 -9
- package/.aether/docs/source-of-truth-map.md +132 -0
- package/.aether/docs/xml-utilities.md +47 -0
- package/.aether/rules/aether-colony.md +23 -13
- package/.aether/scripts/incident-test-add.sh +47 -0
- package/.aether/scripts/weekly-audit.sh +79 -0
- package/.aether/skills/.index.json +649 -0
- package/.aether/skills/colony/.manifest.json +16 -0
- package/.aether/skills/colony/build-discipline/SKILL.md +78 -0
- package/.aether/skills/colony/colony-interaction/SKILL.md +56 -0
- package/.aether/skills/colony/colony-lifecycle/SKILL.md +77 -0
- package/.aether/skills/colony/colony-visuals/SKILL.md +112 -0
- package/.aether/skills/colony/context-management/SKILL.md +80 -0
- package/.aether/skills/colony/error-presentation/SKILL.md +99 -0
- package/.aether/skills/colony/pheromone-protocol/SKILL.md +79 -0
- package/.aether/skills/colony/pheromone-visibility/SKILL.md +81 -0
- package/.aether/skills/colony/state-safety/SKILL.md +84 -0
- package/.aether/skills/colony/worker-priming/SKILL.md +82 -0
- package/.aether/skills/domain/.manifest.json +24 -0
- package/.aether/skills/domain/README.md +33 -0
- package/.aether/skills/domain/django/SKILL.md +49 -0
- package/.aether/skills/domain/docker/SKILL.md +52 -0
- package/.aether/skills/domain/golang/SKILL.md +52 -0
- package/.aether/skills/domain/graphql/SKILL.md +51 -0
- package/.aether/skills/domain/html-css/SKILL.md +48 -0
- package/.aether/skills/domain/nextjs/SKILL.md +45 -0
- package/.aether/skills/domain/nodejs/SKILL.md +53 -0
- package/.aether/skills/domain/postgresql/SKILL.md +53 -0
- package/.aether/skills/domain/prisma/SKILL.md +59 -0
- package/.aether/skills/domain/python/SKILL.md +50 -0
- package/.aether/skills/domain/rails/SKILL.md +52 -0
- package/.aether/skills/domain/react/SKILL.md +45 -0
- package/.aether/skills/domain/rest-api/SKILL.md +58 -0
- package/.aether/skills/domain/svelte/SKILL.md +47 -0
- package/.aether/skills/domain/tailwind/SKILL.md +45 -0
- package/.aether/skills/domain/testing/SKILL.md +53 -0
- package/.aether/skills/domain/typescript/SKILL.md +58 -0
- package/.aether/skills/domain/vue/SKILL.md +49 -0
- package/.aether/templates/QUEEN.md.template +23 -41
- package/.aether/templates/colony-state-reset.jq.template +1 -0
- package/.aether/templates/colony-state.template.json +4 -0
- package/.aether/templates/learning-observations.template.json +6 -0
- package/.aether/templates/midden.template.json +13 -0
- package/.aether/templates/pheromones.template.json +6 -0
- package/.aether/templates/session.template.json +9 -0
- package/.aether/utils/atomic-write.sh +63 -17
- package/.aether/utils/chamber-utils.sh +145 -2
- package/.aether/utils/council.sh +425 -0
- package/.aether/utils/emoji-audit.sh +166 -0
- package/.aether/utils/error-handler.sh +21 -7
- package/.aether/utils/file-lock.sh +182 -27
- package/.aether/utils/flag.sh +278 -0
- package/.aether/utils/hive.sh +572 -0
- package/.aether/utils/immune.sh +508 -0
- package/.aether/utils/learning.sh +1928 -0
- package/.aether/utils/midden.sh +520 -0
- package/.aether/utils/oracle/oracle.md +168 -0
- package/.aether/utils/oracle/oracle.sh +1023 -0
- package/.aether/utils/pheromone.sh +2029 -0
- package/.aether/utils/queen.sh +1710 -0
- package/.aether/utils/scan.sh +860 -0
- package/.aether/utils/semantic-cli.sh +10 -8
- package/.aether/utils/session.sh +816 -0
- package/.aether/utils/skills.sh +509 -0
- package/.aether/utils/spawn-tree.sh +103 -271
- package/.aether/utils/spawn.sh +260 -0
- package/.aether/utils/state-api.sh +389 -0
- package/.aether/utils/state-loader.sh +8 -6
- package/.aether/utils/suggest.sh +611 -0
- package/.aether/utils/swarm-display.sh +10 -1
- package/.aether/utils/swarm.sh +1004 -0
- package/.aether/utils/watch-spawn-tree.sh +11 -2
- package/.aether/utils/xml-compose.sh +2 -2
- package/.aether/utils/xml-convert.sh +9 -5
- package/.aether/utils/xml-core.sh +5 -9
- package/.aether/utils/xml-query.sh +4 -4
- package/.aether/workers.md +86 -67
- package/.claude/agents/ant/aether-ambassador.md +2 -1
- package/.claude/agents/ant/aether-archaeologist.md +6 -1
- package/.claude/agents/ant/aether-architect.md +236 -0
- package/.claude/agents/ant/aether-auditor.md +6 -1
- package/.claude/agents/ant/aether-builder.md +38 -1
- package/.claude/agents/ant/aether-chaos.md +2 -1
- package/.claude/agents/ant/aether-chronicler.md +1 -0
- package/.claude/agents/ant/aether-gatekeeper.md +6 -1
- package/.claude/agents/ant/aether-includer.md +1 -0
- package/.claude/agents/ant/aether-keeper.md +1 -0
- package/.claude/agents/ant/aether-measurer.md +6 -1
- package/.claude/agents/ant/aether-oracle.md +237 -0
- package/.claude/agents/ant/aether-probe.md +2 -1
- package/.claude/agents/ant/aether-queen.md +6 -1
- package/.claude/agents/ant/aether-route-setter.md +6 -1
- package/.claude/agents/ant/aether-sage.md +68 -3
- package/.claude/agents/ant/aether-scout.md +38 -1
- package/.claude/agents/ant/aether-surveyor-disciplines.md +2 -1
- package/.claude/agents/ant/aether-surveyor-nest.md +2 -1
- package/.claude/agents/ant/aether-surveyor-pathogens.md +2 -1
- package/.claude/agents/ant/aether-surveyor-provisions.md +2 -1
- package/.claude/agents/ant/aether-tracker.md +6 -1
- package/.claude/agents/ant/aether-watcher.md +37 -1
- package/.claude/agents/ant/aether-weaver.md +2 -1
- package/.claude/commands/ant/archaeology.md +1 -8
- package/.claude/commands/ant/build.md +43 -1159
- package/.claude/commands/ant/chaos.md +1 -14
- package/.claude/commands/ant/colonize.md +3 -14
- package/.claude/commands/ant/continue.md +40 -1026
- package/.claude/commands/ant/council.md +213 -15
- package/.claude/commands/ant/data-clean.md +81 -0
- package/.claude/commands/ant/dream.md +12 -9
- package/.claude/commands/ant/entomb.md +62 -87
- package/.claude/commands/ant/export-signals.md +57 -0
- package/.claude/commands/ant/feedback.md +18 -0
- package/.claude/commands/ant/flag.md +12 -0
- package/.claude/commands/ant/flags.md +22 -8
- package/.claude/commands/ant/focus.md +18 -0
- package/.claude/commands/ant/help.md +40 -8
- package/.claude/commands/ant/history.md +3 -0
- package/.claude/commands/ant/import-signals.md +71 -0
- package/.claude/commands/ant/init.md +349 -191
- package/.claude/commands/ant/insert-phase.md +105 -0
- package/.claude/commands/ant/interpret.md +11 -0
- package/.claude/commands/ant/lay-eggs.md +167 -158
- package/.claude/commands/ant/maturity.md +22 -11
- package/.claude/commands/ant/memory-details.md +77 -0
- package/.claude/commands/ant/migrate-state.md +6 -0
- package/.claude/commands/ant/oracle.md +317 -62
- package/.claude/commands/ant/organize.md +10 -5
- package/.claude/commands/ant/patrol.md +620 -0
- package/.claude/commands/ant/pause-colony.md +8 -22
- package/.claude/commands/ant/phase.md +26 -37
- package/.claude/commands/ant/pheromones.md +156 -0
- package/.claude/commands/ant/plan.md +199 -50
- package/.claude/commands/ant/preferences.md +65 -0
- package/.claude/commands/ant/quick.md +100 -0
- package/.claude/commands/ant/redirect.md +18 -0
- package/.claude/commands/ant/resume-colony.md +37 -22
- package/.claude/commands/ant/resume.md +60 -7
- package/.claude/commands/ant/run.md +231 -0
- package/.claude/commands/ant/seal.md +506 -78
- package/.claude/commands/ant/skill-create.md +286 -0
- package/.claude/commands/ant/status.md +171 -1
- package/.claude/commands/ant/swarm.md +11 -23
- package/.claude/commands/ant/tunnels.md +1 -0
- package/.claude/commands/ant/update.md +58 -135
- package/.claude/commands/ant/verify-castes.md +90 -42
- package/.claude/commands/ant/watch.md +1 -0
- package/.opencode/agents/aether-ambassador.md +1 -1
- package/.opencode/agents/aether-architect.md +133 -0
- package/.opencode/agents/aether-builder.md +3 -3
- package/.opencode/agents/aether-oracle.md +137 -0
- package/.opencode/agents/aether-queen.md +1 -1
- package/.opencode/agents/aether-route-setter.md +1 -1
- package/.opencode/agents/aether-scout.md +1 -1
- package/.opencode/agents/aether-surveyor-disciplines.md +6 -1
- package/.opencode/agents/aether-surveyor-nest.md +6 -1
- package/.opencode/agents/aether-surveyor-pathogens.md +6 -1
- package/.opencode/agents/aether-surveyor-provisions.md +6 -1
- package/.opencode/agents/aether-tracker.md +1 -1
- package/.opencode/agents/aether-watcher.md +1 -1
- package/.opencode/agents/aether-weaver.md +1 -1
- package/.opencode/commands/ant/archaeology.md +7 -14
- package/.opencode/commands/ant/build.md +54 -88
- package/.opencode/commands/ant/chaos.md +7 -24
- package/.opencode/commands/ant/colonize.md +10 -17
- package/.opencode/commands/ant/continue.md +595 -66
- package/.opencode/commands/ant/council.md +150 -18
- package/.opencode/commands/ant/data-clean.md +77 -0
- package/.opencode/commands/ant/dream.md +15 -17
- package/.opencode/commands/ant/entomb.md +28 -18
- package/.opencode/commands/ant/export-signals.md +54 -0
- package/.opencode/commands/ant/feedback.md +24 -5
- package/.opencode/commands/ant/flag.md +16 -4
- package/.opencode/commands/ant/flags.md +24 -10
- package/.opencode/commands/ant/focus.md +22 -5
- package/.opencode/commands/ant/help.md +41 -8
- package/.opencode/commands/ant/history.md +9 -0
- package/.opencode/commands/ant/import-signals.md +68 -0
- package/.opencode/commands/ant/init.md +396 -154
- package/.opencode/commands/ant/insert-phase.md +111 -0
- package/.opencode/commands/ant/interpret.md +16 -0
- package/.opencode/commands/ant/lay-eggs.md +184 -112
- package/.opencode/commands/ant/maturity.md +18 -2
- package/.opencode/commands/ant/memory-details.md +83 -0
- package/.opencode/commands/ant/migrate-state.md +12 -0
- package/.opencode/commands/ant/oracle.md +322 -67
- package/.opencode/commands/ant/organize.md +14 -12
- package/.opencode/commands/ant/patrol.md +626 -0
- package/.opencode/commands/ant/pause-colony.md +12 -29
- package/.opencode/commands/ant/phase.md +30 -40
- package/.opencode/commands/ant/pheromones.md +162 -0
- package/.opencode/commands/ant/plan.md +210 -57
- package/.opencode/commands/ant/preferences.md +71 -0
- package/.opencode/commands/ant/quick.md +91 -0
- package/.opencode/commands/ant/redirect.md +22 -5
- package/.opencode/commands/ant/resume-colony.md +41 -29
- package/.opencode/commands/ant/resume.md +80 -20
- package/.opencode/commands/ant/run.md +237 -0
- package/.opencode/commands/ant/seal.md +230 -25
- package/.opencode/commands/ant/skill-create.md +63 -0
- package/.opencode/commands/ant/status.md +125 -30
- package/.opencode/commands/ant/swarm.md +3 -345
- package/.opencode/commands/ant/tunnels.md +3 -9
- package/.opencode/commands/ant/update.md +63 -127
- package/.opencode/commands/ant/verify-castes.md +96 -42
- package/.opencode/commands/ant/watch.md +7 -0
- package/CHANGELOG.md +368 -1
- package/README.md +195 -324
- package/bin/cli.js +236 -429
- package/bin/generate-commands.js +186 -0
- package/bin/generate-commands.sh +128 -89
- package/bin/lib/spawn-logger.js +0 -15
- package/bin/lib/update-transaction.js +285 -35
- package/bin/npx-install.js +178 -0
- package/bin/validate-package.sh +85 -3
- package/package.json +16 -4
- package/.aether/CONTEXT.md +0 -160
- package/.aether/docs/QUEEN.md +0 -84
- package/.aether/exchange/colony-registry.xml +0 -11
- package/.aether/exchange/pheromones.xml +0 -87
- package/.aether/exchange/queen-wisdom.xml +0 -14
- package/.aether/model-profiles.yaml +0 -100
- package/.aether/utils/spawn-with-model.sh +0 -56
- package/bin/lib/model-profiles.js +0 -445
- package/bin/lib/model-verify.js +0 -288
- package/bin/lib/proxy-health.js +0 -253
- package/bin/lib/telemetry.js +0 -441
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Immune response system — trophallaxis repair and scarification
|
|
3
|
+
# Provides: _trophallaxis_diagnose, _trophallaxis_retry, _scar_add, _scar_list,
|
|
4
|
+
# _scar_check, _immune_auto_scar
|
|
5
|
+
#
|
|
6
|
+
# These functions are sourced by aether-utils.sh at startup.
|
|
7
|
+
# All shared infrastructure (json_ok, json_err, atomic_write, acquire_lock,
|
|
8
|
+
# release_lock, LOCK_DIR, COLONY_DATA_DIR, error constants) is available.
|
|
9
|
+
|
|
10
|
+
# ---------------------------------------------------------------------------
|
|
11
|
+
# Internal helpers
|
|
12
|
+
# ---------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
_immune_data_dir() {
|
|
15
|
+
echo "$COLONY_DATA_DIR/immune"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
_immune_scars_file() {
|
|
19
|
+
echo "$COLONY_DATA_DIR/immune/scars.json"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
_immune_retry_log_file() {
|
|
23
|
+
echo "$COLONY_DATA_DIR/immune/retry-log.json"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
_immune_ensure_dir() {
|
|
27
|
+
mkdir -p "$(_immune_data_dir)"
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
_immune_ensure_scars_file() {
|
|
31
|
+
local sf
|
|
32
|
+
sf="$(_immune_scars_file)"
|
|
33
|
+
_immune_ensure_dir
|
|
34
|
+
if [[ ! -f "$sf" ]]; then
|
|
35
|
+
printf '%s\n' '{"version":"1.0","scars":[]}' > "$sf"
|
|
36
|
+
fi
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
_immune_ensure_retry_log() {
|
|
40
|
+
local rf
|
|
41
|
+
rf="$(_immune_retry_log_file)"
|
|
42
|
+
_immune_ensure_dir
|
|
43
|
+
if [[ ! -f "$rf" ]]; then
|
|
44
|
+
printf '%s\n' '{"version":"1.0","tasks":{}}' > "$rf"
|
|
45
|
+
fi
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
# ---------------------------------------------------------------------------
|
|
49
|
+
# _trophallaxis_diagnose
|
|
50
|
+
# Usage: trophallaxis-diagnose --task-id <id> --failure <desc> [--phase N]
|
|
51
|
+
# ---------------------------------------------------------------------------
|
|
52
|
+
_trophallaxis_diagnose() {
|
|
53
|
+
local td_task_id=""
|
|
54
|
+
local td_failure=""
|
|
55
|
+
local td_phase=""
|
|
56
|
+
|
|
57
|
+
while [[ $# -gt 0 ]]; do
|
|
58
|
+
case "$1" in
|
|
59
|
+
--task-id) td_task_id="${2:-}"; shift 2 ;;
|
|
60
|
+
--failure) td_failure="${2:-}"; shift 2 ;;
|
|
61
|
+
--phase) td_phase="${2:-}"; shift 2 ;;
|
|
62
|
+
*) shift ;;
|
|
63
|
+
esac
|
|
64
|
+
done
|
|
65
|
+
|
|
66
|
+
if [[ -z "$td_task_id" ]]; then
|
|
67
|
+
json_err "$E_VALIDATION_FAILED" "trophallaxis-diagnose requires --task-id"
|
|
68
|
+
return
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
if [[ -z "$td_failure" ]]; then
|
|
72
|
+
json_err "$E_VALIDATION_FAILED" "trophallaxis-diagnose requires --failure"
|
|
73
|
+
return
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
local td_midden_file="$COLONY_DATA_DIR/midden/midden.json"
|
|
77
|
+
local td_related=0
|
|
78
|
+
local td_related_entries="[]"
|
|
79
|
+
local td_approach=""
|
|
80
|
+
|
|
81
|
+
# Search midden for related entries using keywords from failure description
|
|
82
|
+
if [[ -f "$td_midden_file" ]]; then
|
|
83
|
+
# Extract first keyword (longest word >= 4 chars) for search
|
|
84
|
+
local td_keyword
|
|
85
|
+
td_keyword=$(echo "$td_failure" | tr '[:upper:]' '[:lower:]' | \
|
|
86
|
+
grep -oE '[a-z]{4,}' | sort -rn -k1,1 | head -1 || echo "")
|
|
87
|
+
|
|
88
|
+
if [[ -n "$td_keyword" ]]; then
|
|
89
|
+
td_related=$(jq \
|
|
90
|
+
--arg q "$td_keyword" \
|
|
91
|
+
'[.entries // [] | .[] |
|
|
92
|
+
select(.acknowledged != true) |
|
|
93
|
+
select(.message | ascii_downcase | contains($q))
|
|
94
|
+
] | length' "$td_midden_file" 2>/dev/null || echo "0")
|
|
95
|
+
|
|
96
|
+
td_related_entries=$(jq \
|
|
97
|
+
--arg q "$td_keyword" \
|
|
98
|
+
'[.entries // [] | .[] |
|
|
99
|
+
select(.acknowledged != true) |
|
|
100
|
+
select(.message | ascii_downcase | contains($q)) |
|
|
101
|
+
{id, timestamp, category, source, message}
|
|
102
|
+
] | .[:5]' "$td_midden_file" 2>/dev/null || echo "[]")
|
|
103
|
+
else
|
|
104
|
+
# No usable keyword — scan all recent entries
|
|
105
|
+
td_related=$(jq '[.entries // [] | .[] | select(.acknowledged != true)] | length' \
|
|
106
|
+
"$td_midden_file" 2>/dev/null || echo "0")
|
|
107
|
+
fi
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
# Build diagnosis text
|
|
111
|
+
local td_diagnosis
|
|
112
|
+
if [[ "$td_related" -gt 0 ]]; then
|
|
113
|
+
td_diagnosis="Found $td_related related failure(s) in midden matching: $td_failure"
|
|
114
|
+
td_approach="Review related midden entries for patterns. Address root cause before retrying."
|
|
115
|
+
else
|
|
116
|
+
td_diagnosis="No related failures found in midden for: $td_failure"
|
|
117
|
+
td_approach="Investigate failure from first principles. Check logs and dependencies."
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
# Confidence: higher when related failures exist
|
|
121
|
+
local td_confidence
|
|
122
|
+
if [[ "$td_related" -ge 3 ]]; then
|
|
123
|
+
td_confidence="0.9"
|
|
124
|
+
elif [[ "$td_related" -ge 1 ]]; then
|
|
125
|
+
td_confidence="0.7"
|
|
126
|
+
else
|
|
127
|
+
td_confidence="0.4"
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
json_ok "$(jq -n \
|
|
131
|
+
--arg task_id "$td_task_id" \
|
|
132
|
+
--arg failure "$td_failure" \
|
|
133
|
+
--arg diagnosis "$td_diagnosis" \
|
|
134
|
+
--argjson related_failures "$td_related" \
|
|
135
|
+
--arg suggested_approach "$td_approach" \
|
|
136
|
+
--argjson confidence "$td_confidence" \
|
|
137
|
+
--argjson related_entries "$td_related_entries" \
|
|
138
|
+
'{
|
|
139
|
+
task_id: $task_id,
|
|
140
|
+
failure: $failure,
|
|
141
|
+
diagnosis: $diagnosis,
|
|
142
|
+
related_failures: $related_failures,
|
|
143
|
+
suggested_approach: $suggested_approach,
|
|
144
|
+
confidence: $confidence,
|
|
145
|
+
related_entries: $related_entries
|
|
146
|
+
}')"
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
# ---------------------------------------------------------------------------
|
|
150
|
+
# _trophallaxis_retry
|
|
151
|
+
# Usage: trophallaxis-retry --task-id <id> --diagnosis <json>
|
|
152
|
+
# ---------------------------------------------------------------------------
|
|
153
|
+
_trophallaxis_retry() {
|
|
154
|
+
local tr_task_id=""
|
|
155
|
+
local tr_diagnosis=""
|
|
156
|
+
|
|
157
|
+
while [[ $# -gt 0 ]]; do
|
|
158
|
+
case "$1" in
|
|
159
|
+
--task-id) tr_task_id="${2:-}"; shift 2 ;;
|
|
160
|
+
--diagnosis) tr_diagnosis="${2:-}"; shift 2 ;;
|
|
161
|
+
*) shift ;;
|
|
162
|
+
esac
|
|
163
|
+
done
|
|
164
|
+
|
|
165
|
+
if [[ -z "$tr_task_id" ]]; then
|
|
166
|
+
json_err "$E_VALIDATION_FAILED" "trophallaxis-retry requires --task-id"
|
|
167
|
+
return
|
|
168
|
+
fi
|
|
169
|
+
|
|
170
|
+
_immune_ensure_retry_log
|
|
171
|
+
|
|
172
|
+
local tr_log_file
|
|
173
|
+
tr_log_file="$(_immune_retry_log_file)"
|
|
174
|
+
local tr_timestamp
|
|
175
|
+
tr_timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
176
|
+
|
|
177
|
+
# Read current retry count for this task
|
|
178
|
+
local tr_current_count
|
|
179
|
+
tr_current_count=$(jq -r --arg tid "$tr_task_id" \
|
|
180
|
+
'.tasks[$tid].retry_count // 0' "$tr_log_file" 2>/dev/null || echo "0")
|
|
181
|
+
local tr_new_count=$(( tr_current_count + 1 ))
|
|
182
|
+
|
|
183
|
+
# Validate diagnosis JSON (graceful: use empty object if invalid)
|
|
184
|
+
local tr_diag_json
|
|
185
|
+
if echo "$tr_diagnosis" | jq empty 2>/dev/null; then
|
|
186
|
+
tr_diag_json="$tr_diagnosis"
|
|
187
|
+
else
|
|
188
|
+
tr_diag_json="{}"
|
|
189
|
+
fi
|
|
190
|
+
|
|
191
|
+
# Build the retry entry
|
|
192
|
+
local tr_entry
|
|
193
|
+
tr_entry=$(jq -n \
|
|
194
|
+
--arg ts "$tr_timestamp" \
|
|
195
|
+
--argjson retry_count "$tr_new_count" \
|
|
196
|
+
--argjson diagnosis "$tr_diag_json" \
|
|
197
|
+
'{timestamp: $ts, retry_count: $retry_count, diagnosis: $diagnosis}')
|
|
198
|
+
|
|
199
|
+
# Update log with locking
|
|
200
|
+
local tr_updated
|
|
201
|
+
if acquire_lock "$tr_log_file" 2>/dev/null; then
|
|
202
|
+
tr_updated=$(jq \
|
|
203
|
+
--arg tid "$tr_task_id" \
|
|
204
|
+
--argjson entry "$tr_entry" \
|
|
205
|
+
--argjson new_count "$tr_new_count" \
|
|
206
|
+
'.tasks[$tid] = {
|
|
207
|
+
retry_count: $new_count,
|
|
208
|
+
last_attempt: $entry.timestamp,
|
|
209
|
+
last_diagnosis: $entry.diagnosis,
|
|
210
|
+
history: ((.tasks[$tid].history // []) + [$entry])
|
|
211
|
+
}' "$tr_log_file" 2>/dev/null)
|
|
212
|
+
|
|
213
|
+
if [[ -n "$tr_updated" ]]; then
|
|
214
|
+
atomic_write "$tr_log_file" "$tr_updated"
|
|
215
|
+
fi
|
|
216
|
+
release_lock 2>/dev/null || true
|
|
217
|
+
else
|
|
218
|
+
# Lockless fallback
|
|
219
|
+
tr_updated=$(jq \
|
|
220
|
+
--arg tid "$tr_task_id" \
|
|
221
|
+
--argjson entry "$tr_entry" \
|
|
222
|
+
--argjson new_count "$tr_new_count" \
|
|
223
|
+
'.tasks[$tid] = {
|
|
224
|
+
retry_count: $new_count,
|
|
225
|
+
last_attempt: $entry.timestamp,
|
|
226
|
+
last_diagnosis: $entry.diagnosis,
|
|
227
|
+
history: ((.tasks[$tid].history // []) + [$entry])
|
|
228
|
+
}' "$tr_log_file" 2>/dev/null)
|
|
229
|
+
|
|
230
|
+
if [[ -n "$tr_updated" ]]; then
|
|
231
|
+
atomic_write "$tr_log_file" "$tr_updated"
|
|
232
|
+
fi
|
|
233
|
+
fi
|
|
234
|
+
|
|
235
|
+
json_ok "$(jq -n \
|
|
236
|
+
--arg task_id "$tr_task_id" \
|
|
237
|
+
--argjson retry_count "$tr_new_count" \
|
|
238
|
+
'{task_id: $task_id, retry_count: $retry_count, diagnosis_injected: true}')"
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
# ---------------------------------------------------------------------------
|
|
242
|
+
# _scar_add
|
|
243
|
+
# Usage: scar-add --pattern <desc> --severity <low|medium|high> [--phase N] [--source <src>]
|
|
244
|
+
# ---------------------------------------------------------------------------
|
|
245
|
+
_scar_add() {
|
|
246
|
+
local sa_pattern=""
|
|
247
|
+
local sa_severity=""
|
|
248
|
+
local sa_phase=""
|
|
249
|
+
local sa_source="unknown"
|
|
250
|
+
|
|
251
|
+
while [[ $# -gt 0 ]]; do
|
|
252
|
+
case "$1" in
|
|
253
|
+
--pattern) sa_pattern="${2:-}"; shift 2 ;;
|
|
254
|
+
--severity) sa_severity="${2:-}"; shift 2 ;;
|
|
255
|
+
--phase) sa_phase="${2:-}"; shift 2 ;;
|
|
256
|
+
--source) sa_source="${2:-}"; shift 2 ;;
|
|
257
|
+
*) shift ;;
|
|
258
|
+
esac
|
|
259
|
+
done
|
|
260
|
+
|
|
261
|
+
if [[ -z "$sa_pattern" ]]; then
|
|
262
|
+
json_err "$E_VALIDATION_FAILED" "scar-add requires --pattern"
|
|
263
|
+
return
|
|
264
|
+
fi
|
|
265
|
+
|
|
266
|
+
# Default severity if not provided
|
|
267
|
+
if [[ -z "$sa_severity" ]]; then
|
|
268
|
+
sa_severity="medium"
|
|
269
|
+
fi
|
|
270
|
+
|
|
271
|
+
# Validate severity
|
|
272
|
+
case "$sa_severity" in
|
|
273
|
+
low|medium|high) ;;
|
|
274
|
+
*)
|
|
275
|
+
json_err "$E_VALIDATION_FAILED" "scar-add --severity must be low, medium, or high"
|
|
276
|
+
return
|
|
277
|
+
;;
|
|
278
|
+
esac
|
|
279
|
+
|
|
280
|
+
_immune_ensure_scars_file
|
|
281
|
+
|
|
282
|
+
local sa_scars_file
|
|
283
|
+
sa_scars_file="$(_immune_scars_file)"
|
|
284
|
+
local sa_timestamp
|
|
285
|
+
sa_timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
286
|
+
local sa_id
|
|
287
|
+
sa_id="scar_$(date +%s)_$$"
|
|
288
|
+
|
|
289
|
+
# Build phase value for JSON
|
|
290
|
+
local sa_phase_val
|
|
291
|
+
if [[ -n "$sa_phase" ]]; then
|
|
292
|
+
sa_phase_val="$sa_phase"
|
|
293
|
+
else
|
|
294
|
+
sa_phase_val="null"
|
|
295
|
+
fi
|
|
296
|
+
|
|
297
|
+
local sa_new_scar
|
|
298
|
+
sa_new_scar=$(jq -n \
|
|
299
|
+
--arg id "$sa_id" \
|
|
300
|
+
--arg pattern "$sa_pattern" \
|
|
301
|
+
--arg severity "$sa_severity" \
|
|
302
|
+
--arg phase "$sa_phase_val" \
|
|
303
|
+
--arg source "$sa_source" \
|
|
304
|
+
--arg created_at "$sa_timestamp" \
|
|
305
|
+
'{
|
|
306
|
+
id: $id,
|
|
307
|
+
pattern: $pattern,
|
|
308
|
+
severity: $severity,
|
|
309
|
+
phase: (if $phase == "null" then null else ($phase | tonumber? // $phase) end),
|
|
310
|
+
source: $source,
|
|
311
|
+
created_at: $created_at,
|
|
312
|
+
retry_count: 0,
|
|
313
|
+
active: true
|
|
314
|
+
}')
|
|
315
|
+
|
|
316
|
+
local sa_updated
|
|
317
|
+
if acquire_lock "$sa_scars_file" 2>/dev/null; then
|
|
318
|
+
sa_updated=$(jq \
|
|
319
|
+
--argjson scar "$sa_new_scar" \
|
|
320
|
+
'.scars += [$scar]' "$sa_scars_file" 2>/dev/null)
|
|
321
|
+
if [[ -n "$sa_updated" ]]; then
|
|
322
|
+
atomic_write "$sa_scars_file" "$sa_updated"
|
|
323
|
+
fi
|
|
324
|
+
release_lock 2>/dev/null || true
|
|
325
|
+
else
|
|
326
|
+
sa_updated=$(jq \
|
|
327
|
+
--argjson scar "$sa_new_scar" \
|
|
328
|
+
'.scars += [$scar]' "$sa_scars_file" 2>/dev/null)
|
|
329
|
+
if [[ -n "$sa_updated" ]]; then
|
|
330
|
+
atomic_write "$sa_scars_file" "$sa_updated"
|
|
331
|
+
fi
|
|
332
|
+
fi
|
|
333
|
+
|
|
334
|
+
local sa_count
|
|
335
|
+
sa_count=$(jq '[.scars[]] | length' "$sa_scars_file" 2>/dev/null || echo "1")
|
|
336
|
+
|
|
337
|
+
json_ok "$(jq -n \
|
|
338
|
+
--arg id "$sa_id" \
|
|
339
|
+
--argjson scar_count "$sa_count" \
|
|
340
|
+
'{id: $id, scar_count: $scar_count}')"
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
# ---------------------------------------------------------------------------
|
|
344
|
+
# _scar_list
|
|
345
|
+
# Usage: scar-list [--active] [--severity <level>]
|
|
346
|
+
# ---------------------------------------------------------------------------
|
|
347
|
+
_scar_list() {
|
|
348
|
+
local sl_active_only=false
|
|
349
|
+
local sl_severity=""
|
|
350
|
+
|
|
351
|
+
while [[ $# -gt 0 ]]; do
|
|
352
|
+
case "$1" in
|
|
353
|
+
--active) sl_active_only=true; shift ;;
|
|
354
|
+
--severity) sl_severity="${2:-}"; shift 2 ;;
|
|
355
|
+
*) shift ;;
|
|
356
|
+
esac
|
|
357
|
+
done
|
|
358
|
+
|
|
359
|
+
local sl_scars_file
|
|
360
|
+
sl_scars_file="$(_immune_scars_file)"
|
|
361
|
+
|
|
362
|
+
if [[ ! -f "$sl_scars_file" ]]; then
|
|
363
|
+
json_ok '{"total":0,"active":0,"scars":[]}'
|
|
364
|
+
return 0
|
|
365
|
+
fi
|
|
366
|
+
|
|
367
|
+
local sl_result
|
|
368
|
+
sl_result=$(jq \
|
|
369
|
+
--argjson active_only "$sl_active_only" \
|
|
370
|
+
--arg severity "$sl_severity" \
|
|
371
|
+
'
|
|
372
|
+
[.scars // [] | .[] |
|
|
373
|
+
if $active_only then select(.active == true) else . end |
|
|
374
|
+
if ($severity | length) > 0 then select(.severity == $severity) else . end
|
|
375
|
+
] |
|
|
376
|
+
. as $filtered |
|
|
377
|
+
{
|
|
378
|
+
total: ($filtered | length),
|
|
379
|
+
active: ($filtered | map(select(.active == true)) | length),
|
|
380
|
+
scars: $filtered
|
|
381
|
+
}
|
|
382
|
+
' "$sl_scars_file" 2>/dev/null)
|
|
383
|
+
|
|
384
|
+
if [[ -z "$sl_result" ]]; then
|
|
385
|
+
json_ok '{"total":0,"active":0,"scars":[]}'
|
|
386
|
+
return 0
|
|
387
|
+
fi
|
|
388
|
+
|
|
389
|
+
json_ok "$sl_result"
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
# ---------------------------------------------------------------------------
|
|
393
|
+
# _scar_check
|
|
394
|
+
# Usage: scar-check --task <desc>
|
|
395
|
+
# ---------------------------------------------------------------------------
|
|
396
|
+
_scar_check() {
|
|
397
|
+
local sc_task=""
|
|
398
|
+
|
|
399
|
+
while [[ $# -gt 0 ]]; do
|
|
400
|
+
case "$1" in
|
|
401
|
+
--task) sc_task="${2:-}"; shift 2 ;;
|
|
402
|
+
*) shift ;;
|
|
403
|
+
esac
|
|
404
|
+
done
|
|
405
|
+
|
|
406
|
+
if [[ -z "$sc_task" ]]; then
|
|
407
|
+
json_err "$E_VALIDATION_FAILED" "scar-check requires --task"
|
|
408
|
+
return
|
|
409
|
+
fi
|
|
410
|
+
|
|
411
|
+
local sc_scars_file
|
|
412
|
+
sc_scars_file="$(_immune_scars_file)"
|
|
413
|
+
|
|
414
|
+
if [[ ! -f "$sc_scars_file" ]]; then
|
|
415
|
+
json_ok '{"matches":0,"scars":[]}'
|
|
416
|
+
return 0
|
|
417
|
+
fi
|
|
418
|
+
|
|
419
|
+
local sc_result
|
|
420
|
+
sc_result=$(jq \
|
|
421
|
+
--arg task "$sc_task" \
|
|
422
|
+
'
|
|
423
|
+
[.scars // [] | .[] |
|
|
424
|
+
select(.active == true) |
|
|
425
|
+
# Split pattern into words, check if any word from pattern appears in task
|
|
426
|
+
select(
|
|
427
|
+
(.pattern | ascii_downcase) as $pat |
|
|
428
|
+
($pat | split(" ") | .[] | select(length >= 3)) as $word |
|
|
429
|
+
($task | ascii_downcase) | contains($word)
|
|
430
|
+
)
|
|
431
|
+
] |
|
|
432
|
+
. as $matches |
|
|
433
|
+
{
|
|
434
|
+
matches: ($matches | length),
|
|
435
|
+
scars: $matches
|
|
436
|
+
}
|
|
437
|
+
' "$sc_scars_file" 2>/dev/null)
|
|
438
|
+
|
|
439
|
+
if [[ -z "$sc_result" ]]; then
|
|
440
|
+
json_ok '{"matches":0,"scars":[]}'
|
|
441
|
+
return 0
|
|
442
|
+
fi
|
|
443
|
+
|
|
444
|
+
json_ok "$sc_result"
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
# ---------------------------------------------------------------------------
|
|
448
|
+
# _immune_auto_scar
|
|
449
|
+
# Usage: immune-auto-scar --task-id <id>
|
|
450
|
+
# ---------------------------------------------------------------------------
|
|
451
|
+
_immune_auto_scar() {
|
|
452
|
+
local ias_task_id=""
|
|
453
|
+
|
|
454
|
+
while [[ $# -gt 0 ]]; do
|
|
455
|
+
case "$1" in
|
|
456
|
+
--task-id) ias_task_id="${2:-}"; shift 2 ;;
|
|
457
|
+
*) shift ;;
|
|
458
|
+
esac
|
|
459
|
+
done
|
|
460
|
+
|
|
461
|
+
if [[ -z "$ias_task_id" ]]; then
|
|
462
|
+
json_err "$E_VALIDATION_FAILED" "immune-auto-scar requires --task-id"
|
|
463
|
+
return
|
|
464
|
+
fi
|
|
465
|
+
|
|
466
|
+
local ias_log_file
|
|
467
|
+
ias_log_file="$(_immune_retry_log_file)"
|
|
468
|
+
|
|
469
|
+
if [[ ! -f "$ias_log_file" ]]; then
|
|
470
|
+
json_ok '{"auto_scarred":false,"retry_count":0}'
|
|
471
|
+
return 0
|
|
472
|
+
fi
|
|
473
|
+
|
|
474
|
+
local ias_retry_count
|
|
475
|
+
ias_retry_count=$(jq -r --arg tid "$ias_task_id" \
|
|
476
|
+
'.tasks[$tid].retry_count // 0' "$ias_log_file" 2>/dev/null || echo "0")
|
|
477
|
+
|
|
478
|
+
if [[ "$ias_retry_count" -lt 3 ]]; then
|
|
479
|
+
json_ok "$(jq -n \
|
|
480
|
+
--argjson retry_count "$ias_retry_count" \
|
|
481
|
+
'{auto_scarred: false, retry_count: $retry_count}')"
|
|
482
|
+
return 0
|
|
483
|
+
fi
|
|
484
|
+
|
|
485
|
+
# Auto-create a scar for this task
|
|
486
|
+
local ias_last_diagnosis
|
|
487
|
+
ias_last_diagnosis=$(jq -r --arg tid "$ias_task_id" \
|
|
488
|
+
'.tasks[$tid].last_diagnosis.failure // ""' "$ias_log_file" 2>/dev/null || echo "")
|
|
489
|
+
|
|
490
|
+
local ias_pattern
|
|
491
|
+
if [[ -n "$ias_last_diagnosis" ]]; then
|
|
492
|
+
ias_pattern="$ias_last_diagnosis"
|
|
493
|
+
else
|
|
494
|
+
ias_pattern="task $ias_task_id failed persistently (auto-scarred after $ias_retry_count retries)"
|
|
495
|
+
fi
|
|
496
|
+
|
|
497
|
+
# Determine severity based on retry count
|
|
498
|
+
local ias_severity="medium"
|
|
499
|
+
if [[ "$ias_retry_count" -ge 5 ]]; then
|
|
500
|
+
ias_severity="high"
|
|
501
|
+
fi
|
|
502
|
+
|
|
503
|
+
_scar_add --pattern "$ias_pattern" --severity "$ias_severity" --source "immune-auto-scar" >/dev/null
|
|
504
|
+
|
|
505
|
+
json_ok "$(jq -n \
|
|
506
|
+
--argjson retry_count "$ias_retry_count" \
|
|
507
|
+
'{auto_scarred: true, retry_count: $retry_count}')"
|
|
508
|
+
}
|