aether-colony 5.3.2 → 5.3.3
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 +181 -5
- package/.aether/commands/build.yaml +35 -0
- package/.aether/commands/entomb.yaml +1 -1
- package/.aether/commands/init.yaml +29 -12
- package/.aether/commands/oracle.yaml +70 -0
- package/.aether/commands/patrol.yaml +2 -2
- package/.aether/commands/run.yaml +3 -3
- package/.aether/commands/swarm.yaml +1 -1
- package/.aether/docs/command-playbooks/build-complete.md +41 -8
- package/.aether/docs/command-playbooks/build-full.md +7 -7
- package/.aether/docs/command-playbooks/build-prep.md +1 -1
- package/.aether/docs/command-playbooks/continue-advance.md +33 -0
- package/.aether/docs/command-playbooks/continue-finalize.md +15 -1
- package/.aether/docs/command-playbooks/continue-full.md +15 -1
- package/.aether/docs/source-of-truth-map.md +10 -10
- package/.aether/docs/structural-learning-stack.md +283 -0
- package/.aether/utils/consolidation-seal.sh +196 -0
- package/.aether/utils/consolidation.sh +127 -0
- package/.aether/utils/curation-ants/archivist.sh +97 -0
- package/.aether/utils/curation-ants/critic.sh +214 -0
- package/.aether/utils/curation-ants/herald.sh +102 -0
- package/.aether/utils/curation-ants/janitor.sh +121 -0
- package/.aether/utils/curation-ants/librarian.sh +99 -0
- package/.aether/utils/curation-ants/nurse.sh +153 -0
- package/.aether/utils/curation-ants/orchestrator.sh +181 -0
- package/.aether/utils/curation-ants/scribe.sh +164 -0
- package/.aether/utils/curation-ants/sentinel.sh +119 -0
- package/.aether/utils/event-bus.sh +301 -0
- package/.aether/utils/graph.sh +559 -0
- package/.aether/utils/instinct-store.sh +401 -0
- package/.aether/utils/learning.sh +79 -7
- package/.aether/utils/session.sh +13 -0
- package/.aether/utils/state-api.sh +1 -1
- package/.aether/utils/trust-scoring.sh +347 -0
- package/.aether/utils/worktree.sh +97 -0
- package/.claude/commands/ant/entomb.md +1 -1
- package/.claude/commands/ant/init.md +29 -12
- package/.claude/commands/ant/oracle.md +35 -0
- package/.claude/commands/ant/patrol.md +2 -2
- package/.claude/commands/ant/run.md +3 -3
- package/.claude/commands/ant/swarm.md +1 -1
- package/.opencode/commands/ant/build.md +35 -0
- package/.opencode/commands/ant/init.md +29 -12
- package/.opencode/commands/ant/oracle.md +35 -0
- package/.opencode/commands/ant/patrol.md +2 -2
- package/.opencode/commands/ant/run.md +3 -3
- package/CHANGELOG.md +83 -0
- package/README.md +22 -9
- package/bin/lib/update-transaction.js +8 -3
- package/bin/npx-entry.js +0 -0
- package/package.json +1 -1
- package/.aether/agents/aether-ambassador.md +0 -140
- package/.aether/agents/aether-archaeologist.md +0 -108
- package/.aether/agents/aether-architect.md +0 -133
- package/.aether/agents/aether-auditor.md +0 -144
- package/.aether/agents/aether-builder.md +0 -184
- package/.aether/agents/aether-chaos.md +0 -115
- package/.aether/agents/aether-chronicler.md +0 -122
- package/.aether/agents/aether-gatekeeper.md +0 -116
- package/.aether/agents/aether-includer.md +0 -117
- package/.aether/agents/aether-keeper.md +0 -177
- package/.aether/agents/aether-measurer.md +0 -128
- package/.aether/agents/aether-oracle.md +0 -137
- package/.aether/agents/aether-probe.md +0 -133
- package/.aether/agents/aether-queen.md +0 -286
- package/.aether/agents/aether-route-setter.md +0 -130
- package/.aether/agents/aether-sage.md +0 -106
- package/.aether/agents/aether-scout.md +0 -101
- package/.aether/agents/aether-surveyor-disciplines.md +0 -391
- package/.aether/agents/aether-surveyor-nest.md +0 -329
- package/.aether/agents/aether-surveyor-pathogens.md +0 -264
- package/.aether/agents/aether-surveyor-provisions.md +0 -334
- package/.aether/agents/aether-tracker.md +0 -137
- package/.aether/agents/aether-watcher.md +0 -174
- package/.aether/agents/aether-weaver.md +0 -130
- package/.aether/commands/claude/archaeology.md +0 -334
- package/.aether/commands/claude/build.md +0 -65
- package/.aether/commands/claude/chaos.md +0 -336
- package/.aether/commands/claude/colonize.md +0 -259
- package/.aether/commands/claude/continue.md +0 -60
- package/.aether/commands/claude/council.md +0 -507
- package/.aether/commands/claude/data-clean.md +0 -81
- package/.aether/commands/claude/dream.md +0 -268
- package/.aether/commands/claude/entomb.md +0 -498
- package/.aether/commands/claude/export-signals.md +0 -57
- package/.aether/commands/claude/feedback.md +0 -96
- package/.aether/commands/claude/flag.md +0 -151
- package/.aether/commands/claude/flags.md +0 -169
- package/.aether/commands/claude/focus.md +0 -76
- package/.aether/commands/claude/help.md +0 -154
- package/.aether/commands/claude/history.md +0 -140
- package/.aether/commands/claude/import-signals.md +0 -71
- package/.aether/commands/claude/init.md +0 -505
- package/.aether/commands/claude/insert-phase.md +0 -105
- package/.aether/commands/claude/interpret.md +0 -278
- package/.aether/commands/claude/lay-eggs.md +0 -210
- package/.aether/commands/claude/maturity.md +0 -113
- package/.aether/commands/claude/memory-details.md +0 -77
- package/.aether/commands/claude/migrate-state.md +0 -171
- package/.aether/commands/claude/oracle.md +0 -642
- package/.aether/commands/claude/organize.md +0 -232
- package/.aether/commands/claude/patrol.md +0 -620
- package/.aether/commands/claude/pause-colony.md +0 -233
- package/.aether/commands/claude/phase.md +0 -115
- package/.aether/commands/claude/pheromones.md +0 -156
- package/.aether/commands/claude/plan.md +0 -693
- package/.aether/commands/claude/preferences.md +0 -65
- package/.aether/commands/claude/quick.md +0 -100
- package/.aether/commands/claude/redirect.md +0 -76
- package/.aether/commands/claude/resume-colony.md +0 -197
- package/.aether/commands/claude/resume.md +0 -388
- package/.aether/commands/claude/run.md +0 -231
- package/.aether/commands/claude/seal.md +0 -774
- package/.aether/commands/claude/skill-create.md +0 -286
- package/.aether/commands/claude/status.md +0 -410
- package/.aether/commands/claude/swarm.md +0 -349
- package/.aether/commands/claude/tunnels.md +0 -426
- package/.aether/commands/claude/update.md +0 -132
- package/.aether/commands/claude/verify-castes.md +0 -143
- package/.aether/commands/claude/watch.md +0 -239
- package/.aether/commands/opencode/archaeology.md +0 -331
- package/.aether/commands/opencode/build.md +0 -1168
- package/.aether/commands/opencode/chaos.md +0 -329
- package/.aether/commands/opencode/colonize.md +0 -195
- package/.aether/commands/opencode/continue.md +0 -1436
- package/.aether/commands/opencode/council.md +0 -437
- package/.aether/commands/opencode/data-clean.md +0 -77
- package/.aether/commands/opencode/dream.md +0 -260
- package/.aether/commands/opencode/entomb.md +0 -377
- package/.aether/commands/opencode/export-signals.md +0 -54
- package/.aether/commands/opencode/feedback.md +0 -99
- package/.aether/commands/opencode/flag.md +0 -149
- package/.aether/commands/opencode/flags.md +0 -167
- package/.aether/commands/opencode/focus.md +0 -73
- package/.aether/commands/opencode/help.md +0 -157
- package/.aether/commands/opencode/history.md +0 -136
- package/.aether/commands/opencode/import-signals.md +0 -68
- package/.aether/commands/opencode/init.md +0 -518
- package/.aether/commands/opencode/insert-phase.md +0 -111
- package/.aether/commands/opencode/interpret.md +0 -272
- package/.aether/commands/opencode/lay-eggs.md +0 -213
- package/.aether/commands/opencode/maturity.md +0 -108
- package/.aether/commands/opencode/memory-details.md +0 -83
- package/.aether/commands/opencode/migrate-state.md +0 -165
- package/.aether/commands/opencode/oracle.md +0 -593
- package/.aether/commands/opencode/organize.md +0 -226
- package/.aether/commands/opencode/patrol.md +0 -626
- package/.aether/commands/opencode/pause-colony.md +0 -203
- package/.aether/commands/opencode/phase.md +0 -113
- package/.aether/commands/opencode/pheromones.md +0 -162
- package/.aether/commands/opencode/plan.md +0 -684
- package/.aether/commands/opencode/preferences.md +0 -71
- package/.aether/commands/opencode/quick.md +0 -91
- package/.aether/commands/opencode/redirect.md +0 -84
- package/.aether/commands/opencode/resume-colony.md +0 -190
- package/.aether/commands/opencode/resume.md +0 -394
- package/.aether/commands/opencode/run.md +0 -237
- package/.aether/commands/opencode/seal.md +0 -452
- package/.aether/commands/opencode/skill-create.md +0 -63
- package/.aether/commands/opencode/status.md +0 -307
- package/.aether/commands/opencode/swarm.md +0 -15
- package/.aether/commands/opencode/tunnels.md +0 -400
- package/.aether/commands/opencode/update.md +0 -127
- package/.aether/commands/opencode/verify-castes.md +0 -139
- package/.aether/commands/opencode/watch.md +0 -227
|
@@ -328,6 +328,39 @@ bash .aether/aether-utils.sh state-mutate \
|
|
|
328
328
|
Validate the state file:
|
|
329
329
|
Run using the Bash tool with description "Validating colony state...": `bash .aether/aether-utils.sh validate-state colony`
|
|
330
330
|
|
|
331
|
+
### Step 2.0.4: Worktree Merge-Back (NON-BLOCKING)
|
|
332
|
+
|
|
333
|
+
After state update, check for any completed worktree branches from the build wave and merge them back to the target branch.
|
|
334
|
+
|
|
335
|
+
Run using the Bash tool with description "Checking for worktree branches to merge...":
|
|
336
|
+
```bash
|
|
337
|
+
# List worktree branches created during this build
|
|
338
|
+
branches=$(git -C "$AETHER_ROOT" worktree list --porcelain 2>/dev/null \
|
|
339
|
+
| grep "worktree-agent-\|worktree-" \
|
|
340
|
+
| awk '{print $NF}' || echo "")
|
|
341
|
+
|
|
342
|
+
last_merged_branch=""
|
|
343
|
+
last_merge_sha=""
|
|
344
|
+
merged_count=0
|
|
345
|
+
|
|
346
|
+
for branch in $branches; do
|
|
347
|
+
[[ -z "$branch" ]] && continue
|
|
348
|
+
result=$(bash "$AETHER_UTILS" worktree-merge --branch "$branch" 2>/dev/null || echo '{"ok":false}')
|
|
349
|
+
ok=$(echo "$result" | jq -r '.ok // false')
|
|
350
|
+
if [[ "$ok" == "true" ]]; then
|
|
351
|
+
last_merged_branch="$branch"
|
|
352
|
+
last_merge_sha=$(echo "$result" | jq -r '.result.sha // ""')
|
|
353
|
+
merged_count=$((merged_count + 1))
|
|
354
|
+
fi
|
|
355
|
+
done
|
|
356
|
+
|
|
357
|
+
if [[ "$merged_count" -gt 0 ]]; then
|
|
358
|
+
echo "Merged $merged_count worktree branch(es). Last: $last_merged_branch ($last_merge_sha)"
|
|
359
|
+
fi
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
This step sets `$last_merged_branch` and `$last_merge_sha` which activates the existing dead code paths in Steps 2.0.5 and 2.0.6.
|
|
363
|
+
|
|
331
364
|
### Step 2.0.5: Pheromone Merge-Back (SILENT, NON-BLOCKING)
|
|
332
365
|
|
|
333
366
|
If a `pheromone-branch-export.json` exists in `.aether/exchange/` (written by seal ceremony on a PR branch and merged to main), run merge-back to collect branch-discovered signals into main's pheromone store. This entire step is silent and non-blocking -- continue proceeds even if merge-back fails.
|
|
@@ -394,7 +394,7 @@ Output:
|
|
|
394
394
|
|
|
395
395
|
```
|
|
396
396
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
397
|
-
|
|
397
|
+
➡️ P H A S E A D V A N C E M E N T
|
|
398
398
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
399
399
|
|
|
400
400
|
✅ Phase {prev_id}: {prev_name} -- COMPLETED
|
|
@@ -445,3 +445,17 @@ bash .aether/aether-utils.sh session-update "/ant:continue" "/ant:build {next_id
|
|
|
445
445
|
```
|
|
446
446
|
|
|
447
447
|
Run using the Bash tool with description "Saving session state...": `bash .aether/aether-utils.sh session-update "/ant:continue" "/ant:build {next_id}" "Phase {prev_id} completed, advanced to Phase {next_id}"`
|
|
448
|
+
|
|
449
|
+
### Step 4.5: Housekeeping (Non-Blocking)
|
|
450
|
+
|
|
451
|
+
Prune stale backups and temp files. This runs automatically — failures never affect phase advancement.
|
|
452
|
+
|
|
453
|
+
Run using the Bash tool with description "Pruning stale backups...":
|
|
454
|
+
```bash
|
|
455
|
+
bash .aether/aether-utils.sh backup-prune-global 2>/dev/null || true
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
Run using the Bash tool with description "Cleaning temp files...":
|
|
459
|
+
```bash
|
|
460
|
+
bash .aether/aether-utils.sh temp-clean 2>/dev/null || true
|
|
461
|
+
```
|
|
@@ -1676,7 +1676,7 @@ Output:
|
|
|
1676
1676
|
|
|
1677
1677
|
```
|
|
1678
1678
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1679
|
-
|
|
1679
|
+
➡️ P H A S E A D V A N C E M E N T
|
|
1680
1680
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1681
1681
|
|
|
1682
1682
|
✅ Phase {prev_id}: {prev_name} -- COMPLETED
|
|
@@ -1723,3 +1723,17 @@ bash .aether/aether-utils.sh session-update "/ant:continue" "/ant:build {next_id
|
|
|
1723
1723
|
```
|
|
1724
1724
|
|
|
1725
1725
|
Run using the Bash tool with description "Saving session state...": `bash .aether/aether-utils.sh session-update "/ant:continue" "/ant:build {next_id}" "Phase {prev_id} completed, advanced to Phase {next_id}"`
|
|
1726
|
+
|
|
1727
|
+
### Step 4.5: Housekeeping (Non-Blocking)
|
|
1728
|
+
|
|
1729
|
+
Prune stale backups and temp files. This runs automatically — failures never affect phase advancement.
|
|
1730
|
+
|
|
1731
|
+
Run using the Bash tool with description "Pruning stale backups...":
|
|
1732
|
+
```bash
|
|
1733
|
+
bash .aether/aether-utils.sh backup-prune-global 2>/dev/null || true
|
|
1734
|
+
```
|
|
1735
|
+
|
|
1736
|
+
Run using the Bash tool with description "Cleaning temp files...":
|
|
1737
|
+
```bash
|
|
1738
|
+
bash .aether/aether-utils.sh temp-clean 2>/dev/null || true
|
|
1739
|
+
```
|
|
@@ -36,10 +36,10 @@ Define which files are authoritative for system behavior, which files are derive
|
|
|
36
36
|
|---|---|---|
|
|
37
37
|
| Core deterministic operations | `.aether/aether-utils.sh` | Dispatcher that loads domain modules on demand (~5,200 lines) |
|
|
38
38
|
| Slash command orchestration | `.claude/commands/ant/*.md` | Includes build/continue orchestrators |
|
|
39
|
-
| Worker behavior specs | `.claude/agents/ant/*.md` |
|
|
39
|
+
| Worker behavior specs | `.claude/agents/ant/*.md` | 24 Claude agent definitions (Builder, Watcher, etc.) |
|
|
40
40
|
| Packaged Claude agent mirror | `.aether/agents-claude/*.md` | Distribution mirror; must stay byte-identical with `.claude/agents/ant/*.md` |
|
|
41
|
-
| OpenCode command surface | `.opencode/commands/ant/*.md` |
|
|
42
|
-
| OpenCode worker behavior specs | `.opencode/agents/*.md` |
|
|
41
|
+
| OpenCode command surface | `.opencode/commands/ant/*.md` | 45 OpenCode command files; structure parity with Claude commands |
|
|
42
|
+
| OpenCode worker behavior specs | `.opencode/agents/*.md` | 24 OpenCode agent definitions |
|
|
43
43
|
| Domain modules | `.aether/utils/{flag,spawn,session,suggest,queen,swarm,learning,pheromone,state-api}.sh` | Extracted from aether-utils.sh in Phase 13; sourced on demand |
|
|
44
44
|
| Build/continue split stages | `.aether/docs/command-playbooks/*.md` | Loaded by orchestrators; executable instruction docs |
|
|
45
45
|
| Output templates | `.aether/templates/*` | Templates for generated state/handoff/wisdom/session artifacts |
|
|
@@ -66,8 +66,8 @@ Define which files are authoritative for system behavior, which files are derive
|
|
|
66
66
|
- `build.md` and `continue.md` are now orchestrators that load split playbooks under `.aether/docs/command-playbooks/`.
|
|
67
67
|
- Orchestrators run playbooks as staged instruction sets (Read-tool execution model), not as bash subcommand wrappers.
|
|
68
68
|
- Cross-platform surfaces are present:
|
|
69
|
-
-
|
|
70
|
-
-
|
|
69
|
+
- 45 Claude commands and 45 OpenCode commands
|
|
70
|
+
- 24 Claude agents and 24 OpenCode agents
|
|
71
71
|
- Autopilot subcommands (`autopilot-init`, `autopilot-update`, `autopilot-status`, `autopilot-stop`, `autopilot-check-replan`) manage autonomous build/continue cycles via `/ant:run`.
|
|
72
72
|
- `registry-list` lists all registered repos with metadata including domain tags.
|
|
73
73
|
- `.aether/agents-claude/*.md` mirrors `.claude/agents/ant/*.md` for packaging/distribution.
|
|
@@ -84,11 +84,11 @@ Define which files are authoritative for system behavior, which files are derive
|
|
|
84
84
|
| Core utility entrypoint | `.aether/aether-utils.sh` | 1 | Active |
|
|
85
85
|
| Sourced shell utilities | `.aether/utils/*.sh` | ~29 | Active (9 domain modules + infrastructure + XML) |
|
|
86
86
|
| XML utility scripts | `.aether/utils/xml-*.sh` | 5 | Active (see drift note) |
|
|
87
|
-
| Slash commands (Claude) | `.claude/commands/ant/*.md` |
|
|
88
|
-
| Slash commands (OpenCode) | `.opencode/commands/ant/*.md` |
|
|
89
|
-
| Agent definitions (Claude) | `.claude/agents/ant/*.md` |
|
|
90
|
-
| Agent mirror (packaging) | `.aether/agents-claude/*.md` |
|
|
91
|
-
| Agent definitions (OpenCode) | `.opencode/agents/*.md` |
|
|
87
|
+
| Slash commands (Claude) | `.claude/commands/ant/*.md` | 45 | Active |
|
|
88
|
+
| Slash commands (OpenCode) | `.opencode/commands/ant/*.md` | 45 | Active (content differs from Claude variants) |
|
|
89
|
+
| Agent definitions (Claude) | `.claude/agents/ant/*.md` | 24 | Active |
|
|
90
|
+
| Agent mirror (packaging) | `.aether/agents-claude/*.md` | 24 | Active mirror (must match Claude agent files exactly) |
|
|
91
|
+
| Agent definitions (OpenCode) | `.opencode/agents/*.md` | 24 | Active (content differs from Claude variants) |
|
|
92
92
|
| Command playbooks | `.aether/docs/command-playbooks/*.md` | 9 | Active (5 build + 4 continue; excludes full/README) |
|
|
93
93
|
| Templates (all types) | `.aether/templates/*` | 12 | Active |
|
|
94
94
|
| Disciplines | `.aether/docs/disciplines/*.md` | 7 | Active |
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
# Structural Learning Stack
|
|
2
|
+
|
|
3
|
+
> Memory consolidation pipeline: from raw observations to trusted wisdom.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
The Structural Learning Stack is how Aether converts raw, repeated observations into
|
|
10
|
+
colony wisdom that workers can act on. Each stage adds structure: trust scores quantify
|
|
11
|
+
reliability, the graph records relationships between instincts, curation ants clean and
|
|
12
|
+
promote, and the event bus connects everything loosely.
|
|
13
|
+
|
|
14
|
+
The stack runs automatically at phase-end and seal — workers never call it directly.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Architecture Diagram
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
learning-observe
|
|
22
|
+
│
|
|
23
|
+
[learning-observations.json]
|
|
24
|
+
│
|
|
25
|
+
trust-calculate
|
|
26
|
+
│
|
|
27
|
+
▼
|
|
28
|
+
[instinct-store] ──────────► [instinct-graph.json]
|
|
29
|
+
│ (graph-link edges)
|
|
30
|
+
│
|
|
31
|
+
┌──────────▼──────────┐
|
|
32
|
+
│ Curation Ants │
|
|
33
|
+
│ (phase-end / seal) │
|
|
34
|
+
└──────────┬──────────┘
|
|
35
|
+
│
|
|
36
|
+
┌───────────────┼───────────────┐
|
|
37
|
+
▼ ▼ ▼
|
|
38
|
+
[QUEEN.md] [event-bus.jsonl] [archived]
|
|
39
|
+
(via herald) (consolidation (low-trust
|
|
40
|
+
events) instincts)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Pipeline Stages
|
|
46
|
+
|
|
47
|
+
### 1. Observation (learning.sh — `_learning_observe`)
|
|
48
|
+
|
|
49
|
+
Records an observation of a learning pattern into `.aether/data/learning-observations.json`.
|
|
50
|
+
|
|
51
|
+
- **Deduplication:** A SHA-256 hash of the content is used as the key. If an identical observation already exists, `observation_count` is incremented and `last_seen` is updated rather than creating a duplicate entry.
|
|
52
|
+
- **Trust score on write:** For new observations, `trust-calculate` is called immediately using the provided `source_type` and `evidence_type` (defaults: `observation` / `anecdotal`). The computed score is stored as `trust_score`.
|
|
53
|
+
- **Backup rotation:** A 3-file rotating backup (`*.bak.1`, `*.bak.2`, `*.bak.3`) is maintained on every write. On read, if the file is corrupt, the most recent valid backup is restored automatically.
|
|
54
|
+
- **Valid wisdom types:** `philosophy`, `pattern`, `redirect`, `stack`, `decree`, `failure`
|
|
55
|
+
|
|
56
|
+
Observation schema fields: `content_hash`, `content`, `wisdom_type`, `observation_count`, `first_seen`, `last_seen`, `colonies`, `trust_score`, `source_type`, `evidence_type`, `compression_level`.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
### 2. Trust Scoring Engine (trust-scoring.sh)
|
|
61
|
+
|
|
62
|
+
A pure calculation module. No state is read or written. All functions accept `--flag value` arguments and return JSON.
|
|
63
|
+
|
|
64
|
+
**Weighted formula:**
|
|
65
|
+
```
|
|
66
|
+
score = 0.40 × source_score + 0.35 × evidence_score + 0.25 × activity_score
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Source types (40% weight):**
|
|
70
|
+
|
|
71
|
+
| Type | Score |
|
|
72
|
+
|------|-------|
|
|
73
|
+
| user_feedback | 1.0 |
|
|
74
|
+
| error_resolution | 0.9 |
|
|
75
|
+
| success_pattern | 0.8 |
|
|
76
|
+
| observation | 0.6 |
|
|
77
|
+
| heuristic | 0.4 |
|
|
78
|
+
|
|
79
|
+
**Evidence types (35% weight):**
|
|
80
|
+
|
|
81
|
+
| Type | Score |
|
|
82
|
+
|------|-------|
|
|
83
|
+
| test_verified | 1.0 |
|
|
84
|
+
| multi_phase | 0.9 |
|
|
85
|
+
| single_phase | 0.7 |
|
|
86
|
+
| anecdotal | 0.4 |
|
|
87
|
+
|
|
88
|
+
**Activity score (25% weight):** `0.5 ^ (days_since_last_use / 60)` — a 60-day half-life decay from the last observed use.
|
|
89
|
+
|
|
90
|
+
**Floor:** Score is never below `0.2`.
|
|
91
|
+
|
|
92
|
+
**Trust tiers:**
|
|
93
|
+
|
|
94
|
+
| Score range | Tier | Index |
|
|
95
|
+
|-------------|------|-------|
|
|
96
|
+
| 0.90 – 1.00 | canonical | 0 |
|
|
97
|
+
| 0.80 – 0.89 | trusted | 1 |
|
|
98
|
+
| 0.70 – 0.79 | established | 2 |
|
|
99
|
+
| 0.60 – 0.69 | emerging | 3 |
|
|
100
|
+
| 0.45 – 0.59 | provisional | 4 |
|
|
101
|
+
| 0.30 – 0.44 | suspect | 5 |
|
|
102
|
+
| 0.20 – 0.29 | dormant | 6 |
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
### 3. Event Bus (event-bus.sh)
|
|
107
|
+
|
|
108
|
+
A JSONL append-log at `.aether/data/event-bus.jsonl`. Each line is one JSON event object.
|
|
109
|
+
|
|
110
|
+
**Event fields:** `id`, `topic`, `payload`, `source`, `timestamp`, `ttl_days`, `expires_at`
|
|
111
|
+
|
|
112
|
+
- **Pub/sub pattern:** Publish to a topic with `event-publish`; subscribe by topic pattern with `event-subscribe`. Patterns support exact match or prefix wildcard (e.g., `"consolidation.*"`).
|
|
113
|
+
- **TTL:** Default 30 days per event. Events with `expires_at` in the past are excluded from subscriptions and removed by cleanup.
|
|
114
|
+
- **Concurrency:** File locking via `acquire_lock`/`release_lock` on every append and cleanup rewrite.
|
|
115
|
+
- **Replay:** `event-replay` returns events for a topic from a given ISO-8601 timestamp, sorted chronologically.
|
|
116
|
+
- **Cleanup:** `event-cleanup` atomically rewrites the JSONL file, keeping only non-expired events. Supports `--dry-run`.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
### 4. Instinct Storage (instinct-store.sh)
|
|
121
|
+
|
|
122
|
+
Persistent trust-scored instincts at `.aether/data/instincts.json` (schema version 1.0).
|
|
123
|
+
|
|
124
|
+
**Instinct schema:**
|
|
125
|
+
```json
|
|
126
|
+
{
|
|
127
|
+
"id": "inst_<timestamp>_<hex>",
|
|
128
|
+
"trigger": "...",
|
|
129
|
+
"action": "...",
|
|
130
|
+
"domain": "...",
|
|
131
|
+
"trust_score": 0.75,
|
|
132
|
+
"trust_tier": "established",
|
|
133
|
+
"confidence": 0.8,
|
|
134
|
+
"provenance": {
|
|
135
|
+
"source": "...",
|
|
136
|
+
"source_type": "observation",
|
|
137
|
+
"evidence": "...",
|
|
138
|
+
"created_at": "<ISO8601>",
|
|
139
|
+
"last_applied": null,
|
|
140
|
+
"application_count": 0
|
|
141
|
+
},
|
|
142
|
+
"application_history": [],
|
|
143
|
+
"related_instincts": [],
|
|
144
|
+
"archived": false
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
- **Deduplication:** First 50 characters of `trigger` are matched against existing active entries. On match, confidence is boosted to `max(existing, new)` and the trust score is recomputed.
|
|
149
|
+
- **50-instinct cap:** When active count exceeds 50 after insert, the entry with the lowest `trust_score` is soft-deleted (`archived: true`).
|
|
150
|
+
- **Decay:** `instinct-decay-all` applies the same 60-day half-life decay to all active entries. Entries whose decayed score falls below `0.25` are automatically archived.
|
|
151
|
+
- **Read:** `instinct-read-trusted` returns active entries filtered by `min-score` (default 0.5), optionally by domain, sorted by `trust_score` descending.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
### 5. Graph Layer (graph.sh)
|
|
156
|
+
|
|
157
|
+
Tracks directed relationships between instincts at `.aether/data/instinct-graph.json`.
|
|
158
|
+
|
|
159
|
+
**Edge schema:** `edge_id`, `source`, `target`, `relationship`, `weight`, `created_at`
|
|
160
|
+
|
|
161
|
+
**Relationship types:** `reinforces`, `contradicts`, `extends`, `supersedes`, `related`
|
|
162
|
+
|
|
163
|
+
**Operations:**
|
|
164
|
+
|
|
165
|
+
| Function | Description |
|
|
166
|
+
|----------|-------------|
|
|
167
|
+
| `graph-link` | Create or update a directed edge. Duplicate `source+target+relationship` updates the weight. Default weight: 0.5. |
|
|
168
|
+
| `graph-neighbors` | 1-hop lookup. Direction: `out`, `in`, or `both`. Optional relationship filter. |
|
|
169
|
+
| `graph-reach` | BFS traversal up to N hops (max 3). Returns `{id, hop, path}` for each reachable node. Optional `--min-weight` filter. Early exit when no new nodes are found. |
|
|
170
|
+
| `graph-cluster` | Finds clusters of strongly connected instincts using greedy union-find over qualifying edges. Defaults: `min-edges=2`, `min-weight=0.3`. Returns `{nodes, edge_count, avg_weight}` per cluster. |
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
### 6. Curation Ants
|
|
175
|
+
|
|
176
|
+
Eight specialized ants that maintain memory quality. The orchestrator (`curation-run`) runs all eight in sequence. Sentinel can abort the run early if critical corruption is detected.
|
|
177
|
+
|
|
178
|
+
**Execution order:**
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
sentinel → nurse → critic → herald → janitor → archivist → librarian → scribe
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Ant responsibilities:**
|
|
185
|
+
|
|
186
|
+
| Ant | Responsibility |
|
|
187
|
+
|-----|---------------|
|
|
188
|
+
| sentinel | Health check on all memory stores. Aborts subsequent steps if critical corruption is found. |
|
|
189
|
+
| nurse | Recalculates trust scores for observations and instincts using current elapsed days. |
|
|
190
|
+
| critic | Detects contradictions between instincts (overlapping triggers with conflicting actions). |
|
|
191
|
+
| herald | Promotes high-trust instincts to QUEEN.md Patterns/Philosophies section. |
|
|
192
|
+
| janitor | Removes expired events from the event bus; prunes old archived instincts. |
|
|
193
|
+
| archivist | Archives active instincts whose trust score has fallen below a configurable threshold (default: 0.3 at seal). |
|
|
194
|
+
| librarian | Collects inventory statistics across all memory stores. |
|
|
195
|
+
| scribe | Generates a markdown consolidation report. |
|
|
196
|
+
|
|
197
|
+
All steps are non-blocking — a failure in one step is logged and execution continues.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
### 7. Consolidation Pipeline
|
|
202
|
+
|
|
203
|
+
Two consolidation modes, each calling into the curation ants.
|
|
204
|
+
|
|
205
|
+
**Phase-end (lightweight) — `consolidation-phase-end`:**
|
|
206
|
+
|
|
207
|
+
Runs at the end of every phase (`/ant:continue`). Executes three ants only: `nurse → herald → janitor`. Publishes a `consolidation.phase_end` event on the event bus. All three steps are non-blocking.
|
|
208
|
+
|
|
209
|
+
**Seal (full) — `consolidation-seal`:**
|
|
210
|
+
|
|
211
|
+
Runs once during `/ant:seal`. Executes five steps:
|
|
212
|
+
|
|
213
|
+
1. `curation-run` — full 8-ant orchestration
|
|
214
|
+
2. `instinct-decay-all` — final trust decay pass across all active instincts
|
|
215
|
+
3. `curation-archivist --threshold 0.3` — archive borderline instincts
|
|
216
|
+
4. `event-publish` — publish `consolidation.seal` event
|
|
217
|
+
5. `curation-scribe` — generate final consolidation report
|
|
218
|
+
|
|
219
|
+
All steps are non-blocking. The seal report path is returned in the output.
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Integration Points
|
|
224
|
+
|
|
225
|
+
| Trigger | Stack call | Effect |
|
|
226
|
+
|---------|-----------|--------|
|
|
227
|
+
| `/ant:continue` | `consolidation-phase-end` | nurse + herald + janitor; phase_end event |
|
|
228
|
+
| `/ant:seal` | `consolidation-seal` | full 8-ant curation + decay + archive + seal event + report |
|
|
229
|
+
| `/ant:build` (pattern capture) | `learning-observe` | Records observation with trust score |
|
|
230
|
+
| `colony-prime` | `instinct-read-trusted` | Injects trusted instincts into worker prompts |
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Subcommand Reference
|
|
235
|
+
|
|
236
|
+
| Subcommand | Module | Usage |
|
|
237
|
+
|-----------|--------|-------|
|
|
238
|
+
| `trust-calculate` | trust-scoring.sh | `--source <type> --evidence <type> --days-since <N>` |
|
|
239
|
+
| `trust-decay` | trust-scoring.sh | `--score <float> --days <N>` |
|
|
240
|
+
| `trust-tier` | trust-scoring.sh | `--score <float>` |
|
|
241
|
+
| `event-publish` | event-bus.sh | `--topic <topic> --payload <json> [--source <src>] [--ttl <days>]` |
|
|
242
|
+
| `event-subscribe` | event-bus.sh | `--topic <pattern> [--since <ISO>] [--limit <N>]` |
|
|
243
|
+
| `event-cleanup` | event-bus.sh | `[--dry-run]` |
|
|
244
|
+
| `event-replay` | event-bus.sh | `--topic <topic> --since <ISO> [--limit <N>]` |
|
|
245
|
+
| `instinct-store` | instinct-store.sh | `--trigger <t> --action <a> --domain <d> --confidence <f> --source <s> --evidence <e> [--source-type <type>]` |
|
|
246
|
+
| `instinct-read-trusted` | instinct-store.sh | `[--min-score <f>] [--domain <d>] [--limit <N>]` |
|
|
247
|
+
| `instinct-decay-all` | instinct-store.sh | `[--days <N>] [--dry-run]` |
|
|
248
|
+
| `instinct-archive` | instinct-store.sh | `--id <id>` |
|
|
249
|
+
| `graph-link` | graph.sh | `--source <id> --target <id> --relationship <type> [--weight <float>]` |
|
|
250
|
+
| `graph-neighbors` | graph.sh | `--id <id> [--direction out\|in\|both] [--relationship <type>]` |
|
|
251
|
+
| `graph-reach` | graph.sh | `--id <id> --hops <N> [--min-weight <float>]` |
|
|
252
|
+
| `graph-cluster` | graph.sh | `[--min-edges <N>] [--min-weight <float>]` |
|
|
253
|
+
| `curation-sentinel` | curation-ants/sentinel.sh | `[--dry-run]` |
|
|
254
|
+
| `curation-nurse` | curation-ants/nurse.sh | `[--dry-run]` |
|
|
255
|
+
| `curation-critic` | curation-ants/critic.sh | `[--dry-run]` |
|
|
256
|
+
| `curation-herald` | curation-ants/herald.sh | `[--dry-run]` |
|
|
257
|
+
| `curation-janitor` | curation-ants/janitor.sh | `[--dry-run]` |
|
|
258
|
+
| `curation-archivist` | curation-ants/archivist.sh | `[--threshold <f>] [--dry-run]` |
|
|
259
|
+
| `curation-librarian` | curation-ants/librarian.sh | `[--dry-run]` |
|
|
260
|
+
| `curation-scribe` | curation-ants/scribe.sh | `[--dry-run]` |
|
|
261
|
+
| `curation-run` | curation-ants/orchestrator.sh | `[--dry-run] [--verbose]` |
|
|
262
|
+
| `consolidation-phase-end` | consolidation.sh | `[--dry-run]` |
|
|
263
|
+
| `consolidation-seal` | consolidation-seal.sh | `[--dry-run]` |
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Test Coverage
|
|
268
|
+
|
|
269
|
+
| Test file | What it covers |
|
|
270
|
+
|-----------|---------------|
|
|
271
|
+
| `tests/bash/test-trust-scoring.sh` | `trust-calculate`, `trust-decay`, `trust-tier`; formula weights, floor, tiers |
|
|
272
|
+
| `tests/bash/test-event-bus.sh` | `event-publish`, `event-subscribe`, `event-cleanup`, `event-replay`; TTL, locking, wildcard patterns |
|
|
273
|
+
| `tests/bash/test-instinct-store.sh` | `instinct-store`, `instinct-read-trusted`, `instinct-decay-all`, `instinct-archive`; 50-cap, dedup, decay archival |
|
|
274
|
+
| `tests/bash/test-instinct-apply.sh` | Instinct application and provenance tracking |
|
|
275
|
+
| `tests/bash/test-graph.sh` | `graph-link`, `graph-neighbors`, `graph-reach`, `graph-cluster`; BFS traversal, cluster detection |
|
|
276
|
+
| `tests/bash/test-curation-core.sh` | Core curation ant behavior (sentinel, nurse, critic) |
|
|
277
|
+
| `tests/bash/test-curation-ops.sh` | Operational curation ants (herald, janitor, archivist, librarian, scribe) |
|
|
278
|
+
| `tests/bash/test-curation-orchestrator.sh` | `curation-run` full sequence, sentinel abort path |
|
|
279
|
+
| `tests/bash/test-consolidation.sh` | `consolidation-phase-end`; phase-end step sequence, event publishing |
|
|
280
|
+
| `tests/bash/test-consolidation-seal.sh` | `consolidation-seal`; full seal sequence, dry-run mode |
|
|
281
|
+
| `tests/bash/test-learning-module.sh` | `learning-observe`; trust score on write, deduplication, observation_count increment |
|
|
282
|
+
| `tests/bash/test-learning-recovery.sh` | Backup rotation and corrupt-file recovery logic |
|
|
283
|
+
| `tests/bash/test-oracle-trust.sh` | Trust scoring integration with oracle/research paths |
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Consolidation Seal — Full seal-ceremony consolidation
|
|
3
|
+
# Provides: _consolidation_seal
|
|
4
|
+
#
|
|
5
|
+
# Runs once during /ant:seal. Orchestrates curation-run, instinct-decay-all,
|
|
6
|
+
# curation-archivist, event publish, and curation-scribe in sequence.
|
|
7
|
+
# Each step is non-blocking: failures are logged but do not stop the seal.
|
|
8
|
+
#
|
|
9
|
+
# These functions are sourced by aether-utils.sh at startup.
|
|
10
|
+
# All shared infrastructure (json_ok, json_err, COLONY_DATA_DIR, DATA_DIR,
|
|
11
|
+
# error constants) is available when sourced.
|
|
12
|
+
|
|
13
|
+
# ============================================================================
|
|
14
|
+
# _consolidation_seal
|
|
15
|
+
# Full consolidation for the seal ceremony.
|
|
16
|
+
#
|
|
17
|
+
# Usage: consolidation-seal [--dry-run]
|
|
18
|
+
#
|
|
19
|
+
# Steps:
|
|
20
|
+
# 1. curation-run — full 8-ant orchestration
|
|
21
|
+
# 2. instinct-decay-all — final trust decay pass
|
|
22
|
+
# 3. curation-archivist — archive borderline instincts (threshold 0.3)
|
|
23
|
+
# 4. event-publish — publish consolidation.seal event
|
|
24
|
+
# 5. curation-scribe — generate final report
|
|
25
|
+
#
|
|
26
|
+
# Output: json_ok with {type, steps, event_published, dry_run}
|
|
27
|
+
# ============================================================================
|
|
28
|
+
_consolidation_seal() {
|
|
29
|
+
local dry_run="false"
|
|
30
|
+
|
|
31
|
+
while [[ $# -gt 0 ]]; do
|
|
32
|
+
case "$1" in
|
|
33
|
+
--dry-run) dry_run="true"; shift ;;
|
|
34
|
+
*) shift ;;
|
|
35
|
+
esac
|
|
36
|
+
done
|
|
37
|
+
|
|
38
|
+
local steps_json="[]"
|
|
39
|
+
local event_published="false"
|
|
40
|
+
|
|
41
|
+
# _cs_step <name> <subcommand> [extra_args...]
|
|
42
|
+
# Runs the subcommand non-blocking (failures logged, not fatal).
|
|
43
|
+
# Appends a step entry to steps_json.
|
|
44
|
+
_cs_step() {
|
|
45
|
+
local step_name="$1"
|
|
46
|
+
shift
|
|
47
|
+
local subcmd="$1"
|
|
48
|
+
shift
|
|
49
|
+
# Remaining positional args are passed to the subcommand
|
|
50
|
+
|
|
51
|
+
local step_result step_status step_summary step_report_path="null"
|
|
52
|
+
|
|
53
|
+
# Build argument array respecting dry_run
|
|
54
|
+
local -a args=("$subcmd")
|
|
55
|
+
if [[ "$dry_run" == "true" ]]; then
|
|
56
|
+
args+=("--dry-run")
|
|
57
|
+
fi
|
|
58
|
+
# Append any extra args
|
|
59
|
+
while [[ $# -gt 0 ]]; do
|
|
60
|
+
args+=("$1")
|
|
61
|
+
shift
|
|
62
|
+
done
|
|
63
|
+
|
|
64
|
+
step_result=$(bash "$0" "${args[@]}" 2>/dev/null) || true
|
|
65
|
+
|
|
66
|
+
if echo "$step_result" | jq -e '.ok == true' >/dev/null 2>&1; then
|
|
67
|
+
step_status="ok"
|
|
68
|
+
step_summary=$(echo "$step_result" | jq -r '
|
|
69
|
+
.result |
|
|
70
|
+
if type == "object" then
|
|
71
|
+
[ to_entries[] | "\(.key) \(.value)" ] | join(", ")
|
|
72
|
+
else
|
|
73
|
+
tostring
|
|
74
|
+
end
|
|
75
|
+
' 2>/dev/null | head -c 120 || echo "ok")
|
|
76
|
+
[[ -z "$step_summary" ]] && step_summary="ok"
|
|
77
|
+
|
|
78
|
+
# Extract report_path if present (scribe step)
|
|
79
|
+
step_report_path=$(echo "$step_result" | jq -r '.result.report_path // "null"' 2>/dev/null || echo "null")
|
|
80
|
+
else
|
|
81
|
+
step_status="failed"
|
|
82
|
+
local err_msg
|
|
83
|
+
err_msg=$(echo "$step_result" | jq -r '.error // "unknown error"' 2>/dev/null || echo "unknown error")
|
|
84
|
+
step_summary="$err_msg"
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
steps_json=$(echo "$steps_json" | jq \
|
|
88
|
+
--arg name "$step_name" \
|
|
89
|
+
--arg status "$step_status" \
|
|
90
|
+
--arg summary "$step_summary" \
|
|
91
|
+
--arg rp "$step_report_path" \
|
|
92
|
+
'. += [{
|
|
93
|
+
"name": $name,
|
|
94
|
+
"status": $status,
|
|
95
|
+
"summary": $summary,
|
|
96
|
+
"report_path": (if $rp == "null" then null else $rp end)
|
|
97
|
+
}]')
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
# ── Step 1: Full 8-ant curation run ────────────────────────────────────────
|
|
101
|
+
_cs_step "curation-run" "curation-run"
|
|
102
|
+
|
|
103
|
+
# ── Step 2: Final trust decay pass ─────────────────────────────────────────
|
|
104
|
+
_cs_step "instinct-decay-all" "instinct-decay-all"
|
|
105
|
+
|
|
106
|
+
# ── Step 3: Archive borderline instincts (threshold 0.3) ───────────────────
|
|
107
|
+
# Note: --dry-run is injected by _cs_step; but archivist also takes --threshold
|
|
108
|
+
# We cannot let _cs_step inject --dry-run before --threshold so we handle manually
|
|
109
|
+
local arch_result arch_status arch_summary
|
|
110
|
+
local -a arch_args=("curation-archivist" "--threshold" "0.3")
|
|
111
|
+
if [[ "$dry_run" == "true" ]]; then
|
|
112
|
+
arch_args+=("--dry-run")
|
|
113
|
+
fi
|
|
114
|
+
arch_result=$(bash "$0" "${arch_args[@]}" 2>/dev/null) || true
|
|
115
|
+
if echo "$arch_result" | jq -e '.ok == true' >/dev/null 2>&1; then
|
|
116
|
+
arch_status="ok"
|
|
117
|
+
arch_summary=$(echo "$arch_result" | jq -r '
|
|
118
|
+
.result |
|
|
119
|
+
if type == "object" then
|
|
120
|
+
[ to_entries[] | "\(.key) \(.value)" ] | join(", ")
|
|
121
|
+
else tostring end
|
|
122
|
+
' 2>/dev/null | head -c 120 || echo "ok")
|
|
123
|
+
[[ -z "$arch_summary" ]] && arch_summary="ok"
|
|
124
|
+
else
|
|
125
|
+
arch_status="failed"
|
|
126
|
+
arch_summary=$(echo "$arch_result" | jq -r '.error // "unknown error"' 2>/dev/null || echo "unknown error")
|
|
127
|
+
fi
|
|
128
|
+
steps_json=$(echo "$steps_json" | jq \
|
|
129
|
+
--arg status "$arch_status" \
|
|
130
|
+
--arg summary "$arch_summary" \
|
|
131
|
+
'. += [{"name":"archivist","status":$status,"summary":$summary,"report_path":null}]')
|
|
132
|
+
|
|
133
|
+
# ── Step 4: Publish consolidation.seal event ───────────────────────────────
|
|
134
|
+
if [[ "$dry_run" != "true" ]]; then
|
|
135
|
+
local payload
|
|
136
|
+
payload=$(jq -nc \
|
|
137
|
+
--arg ts "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
|
|
138
|
+
--argjson steps "$steps_json" \
|
|
139
|
+
'{"timestamp":$ts,"steps":$steps}')
|
|
140
|
+
local ep_result
|
|
141
|
+
ep_result=$(bash "$0" event-publish \
|
|
142
|
+
--topic "consolidation.seal" \
|
|
143
|
+
--payload "$payload" \
|
|
144
|
+
--source "consolidation-seal" 2>/dev/null) || true
|
|
145
|
+
if echo "$ep_result" | jq -e '.ok == true' >/dev/null 2>&1; then
|
|
146
|
+
event_published="true"
|
|
147
|
+
fi
|
|
148
|
+
else
|
|
149
|
+
# In dry-run mode, report event as published (no side effects)
|
|
150
|
+
event_published="true"
|
|
151
|
+
fi
|
|
152
|
+
|
|
153
|
+
# ── Step 5: Generate final scribe report ───────────────────────────────────
|
|
154
|
+
local scribe_result scribe_status scribe_summary scribe_report_path="null"
|
|
155
|
+
local -a scribe_args=("curation-scribe")
|
|
156
|
+
if [[ "$dry_run" == "true" ]]; then
|
|
157
|
+
scribe_args+=("--dry-run")
|
|
158
|
+
fi
|
|
159
|
+
scribe_result=$(bash "$0" "${scribe_args[@]}" 2>/dev/null) || true
|
|
160
|
+
if echo "$scribe_result" | jq -e '.ok == true' >/dev/null 2>&1; then
|
|
161
|
+
scribe_status="ok"
|
|
162
|
+
scribe_summary=$(echo "$scribe_result" | jq -r '
|
|
163
|
+
.result |
|
|
164
|
+
if type == "object" then
|
|
165
|
+
[ to_entries[] | "\(.key) \(.value)" ] | join(", ")
|
|
166
|
+
else tostring end
|
|
167
|
+
' 2>/dev/null | head -c 120 || echo "ok")
|
|
168
|
+
[[ -z "$scribe_summary" ]] && scribe_summary="ok"
|
|
169
|
+
scribe_report_path=$(echo "$scribe_result" | jq -r '.result.report_path // "null"' 2>/dev/null || echo "null")
|
|
170
|
+
else
|
|
171
|
+
scribe_status="failed"
|
|
172
|
+
scribe_summary=$(echo "$scribe_result" | jq -r '.error // "unknown error"' 2>/dev/null || echo "unknown error")
|
|
173
|
+
fi
|
|
174
|
+
steps_json=$(echo "$steps_json" | jq \
|
|
175
|
+
--arg status "$scribe_status" \
|
|
176
|
+
--arg summary "$scribe_summary" \
|
|
177
|
+
--arg rp "$scribe_report_path" \
|
|
178
|
+
'. += [{
|
|
179
|
+
"name": "scribe",
|
|
180
|
+
"status": $status,
|
|
181
|
+
"summary": $summary,
|
|
182
|
+
"report_path": (if $rp == "null" then null else $rp end)
|
|
183
|
+
}]')
|
|
184
|
+
|
|
185
|
+
# ── Output ─────────────────────────────────────────────────────────────────
|
|
186
|
+
json_ok "$(jq -n \
|
|
187
|
+
--argjson steps "$steps_json" \
|
|
188
|
+
--argjson event_published "$([ "$event_published" == "true" ] && echo true || echo false)" \
|
|
189
|
+
--argjson dry "$([ "$dry_run" == "true" ] && echo true || echo false)" \
|
|
190
|
+
'{
|
|
191
|
+
"type": "seal",
|
|
192
|
+
"steps": $steps,
|
|
193
|
+
"event_published": $event_published,
|
|
194
|
+
"dry_run": $dry
|
|
195
|
+
}')"
|
|
196
|
+
}
|