eagle-mem 4.7.0 → 4.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -12
- package/bin/eagle-mem +1 -0
- package/db/028_agent_artifact_tables.sql +124 -0
- package/db/029_orchestration_lanes.sql +45 -0
- package/db/030_orchestration_lane_scope.sql +88 -0
- package/db/031_orchestration_workers.sql +20 -0
- package/db/032_orchestration_run_keys.sql +9 -0
- package/hooks/post-tool-use.sh +2 -1
- package/hooks/pre-tool-use.sh +25 -1
- package/hooks/session-end.sh +2 -1
- package/hooks/session-start.sh +103 -13
- package/hooks/stop.sh +15 -13
- package/hooks/user-prompt-submit.sh +71 -12
- package/lib/common.sh +173 -2
- package/lib/db-backfill.sh +3 -3
- package/lib/db-mirrors.sh +59 -32
- package/lib/db-observations.sh +7 -0
- package/lib/db-sessions.sh +12 -6
- package/lib/db-summaries.sh +9 -5
- package/lib/hooks-posttool.sh +4 -4
- package/lib/provider.sh +224 -4
- package/package.json +3 -1
- package/scripts/config.sh +32 -0
- package/scripts/health.sh +71 -1
- package/scripts/help.sh +18 -7
- package/scripts/install.sh +12 -0
- package/scripts/memories.sh +50 -27
- package/scripts/orchestrate.sh +1268 -0
- package/scripts/refresh.sh +3 -3
- package/scripts/search.sh +21 -19
- package/scripts/statusline-em.sh +1 -1
- package/scripts/tasks.sh +186 -15
- package/scripts/update.sh +20 -1
- package/skills/eagle-mem-memories/SKILL.md +13 -13
- package/skills/eagle-mem-orchestrate/SKILL.md +149 -0
- package/skills/eagle-mem-tasks/SKILL.md +23 -15
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
**Context that survives `/compact`.**
|
|
11
11
|
|
|
12
|
-
**v4.
|
|
12
|
+
**v4.8.0 ships first-class cross-agent orchestration, compact Codex hook recall, enforced anti-regression checks, and configurable RTK token guardrails.**
|
|
13
13
|
Claude Code and Codex can now share the same local Eagle Mem database, while every captured row records which agent created it.
|
|
14
14
|
|
|
15
15
|
## The Problem
|
|
@@ -48,7 +48,7 @@ That's it. Open Claude Code or Codex in any project directory. Eagle Mem activat
|
|
|
48
48
|
|
|
49
49
|
Everything is automatic from here. Eagle Mem scans your codebase, indexes source files, captures session summaries, mirrors Claude's memories and tasks, learns which commands are noisy, and prunes stale data — all in the background via hooks.
|
|
50
50
|
|
|
51
|
-
For Codex, the installer enables `codex_hooks` in `~/.codex/config.toml`, registers hooks in `~/.codex/hooks.json`, and patches `~/.codex/AGENTS.md` with the Eagle Mem summary contract. For Claude Code, it keeps using `~/.claude/settings.json`, `CLAUDE.md`, and the existing Claude memory/task locations.
|
|
51
|
+
For Codex, the installer enables `codex_hooks` in `~/.codex/config.toml`, registers hooks in `~/.codex/hooks.json`, symlinks Eagle Mem skills into `~/.codex/skills`, and patches `~/.codex/AGENTS.md` with the Eagle Mem summary contract. For Claude Code, it keeps using `~/.claude/settings.json`, `CLAUDE.md`, `~/.claude/skills`, and the existing Claude memory/task locations.
|
|
52
52
|
|
|
53
53
|
### Prerequisites
|
|
54
54
|
|
|
@@ -70,6 +70,7 @@ Hooks fire automatically at different points in the agent lifecycle:
|
|
|
70
70
|
| **SessionEnd** | session closes | Re-syncs tasks, marks session completed |
|
|
71
71
|
|
|
72
72
|
Codex shell hooks are registered for `Bash`, `exec_command`, `shell_command`, and `unified_exec` tool names so release-boundary protection works across current Codex shell paths.
|
|
73
|
+
Codex recall is emitted as compact hook JSON, so local Codex sessions get shared memory without the multi-screen hook dumps.
|
|
73
74
|
|
|
74
75
|
### Background Automation
|
|
75
76
|
|
|
@@ -85,13 +86,14 @@ These run automatically via SessionStart — no commands needed:
|
|
|
85
86
|
Eagle Mem actively reduces token consumption:
|
|
86
87
|
|
|
87
88
|
- **Injection compression** — zero-value stats are elided from the banner, overview is capped, compact reloads get 1 recent session instead of 3
|
|
88
|
-
- **Command rewriting** — PreToolUse
|
|
89
|
+
- **Command rewriting** — PreToolUse routes noisy shell output through RTK when available and blocks known raw-output commands in enforce mode when RTK is missing.
|
|
89
90
|
- **Read-after-modify detection** — detects when you read a file that was just edited or written, nudges that the diff is already in context
|
|
90
91
|
- **Read dedup tracking** — files read 3+ times in a session get a soft nudge
|
|
91
92
|
- **Co-edit nudges** — learned from observation data: when you edit file X, PreToolUse reminds you that you usually also touch file Y
|
|
92
93
|
- **Hot file awareness** — curator identifies files read in 50%+ of sessions; SessionStart flags them as "likely in context" to reduce re-reads
|
|
93
94
|
- **Working set recovery** — on compact, SessionStart injects the files you were actively editing so you resume without re-reading everything
|
|
94
95
|
- **Stuck loop detection** — if the same file is edited 5+ times in one session, PreToolUse nudges to reconsider the approach
|
|
96
|
+
- **RTK token guard** — optional `rtk` integration can rewrite or block noisy shell commands before raw output enters Claude Code or Codex context. Configure with `eagle-mem config set token_guard.rtk auto|off|enforce`.
|
|
95
97
|
|
|
96
98
|
### Anti-Regression
|
|
97
99
|
|
|
@@ -103,6 +105,7 @@ Eagle Mem prevents Claude from repeating past mistakes:
|
|
|
103
105
|
- **Gotcha surfacing** — past surprises and gotchas are surfaced when editing related files
|
|
104
106
|
- **Stale memory detection** — warns when edits may contradict stored memories
|
|
105
107
|
- **Token guard** — when `rtk` is installed, raw shell output commands are rewritten or blocked with an RTK equivalent so large output is compacted before it enters agent context
|
|
108
|
+
- **Orchestration lanes** — long-running work can be split into durable worker lanes with owners, validation commands, worktree paths, status notes, and handoff output shared by Claude Code and Codex
|
|
106
109
|
|
|
107
110
|
## Commands
|
|
108
111
|
|
|
@@ -113,11 +116,12 @@ Eagle Mem prevents Claude from repeating past mistakes:
|
|
|
113
116
|
| `eagle-mem uninstall` | Remove hooks and optionally delete data |
|
|
114
117
|
| `eagle-mem search` | Search past sessions, memories, and code |
|
|
115
118
|
| `eagle-mem health` | Diagnose pipeline health and background automation |
|
|
116
|
-
| `eagle-mem config` | View or change LLM provider settings |
|
|
119
|
+
| `eagle-mem config` | View or change LLM provider and token-guard settings |
|
|
117
120
|
| `eagle-mem guard` | Manage regression guardrails for files |
|
|
118
121
|
| `eagle-mem overview` | Build or view project overview |
|
|
119
|
-
| `eagle-mem memories` | View/sync
|
|
122
|
+
| `eagle-mem memories` | View/sync agent memories |
|
|
120
123
|
| `eagle-mem tasks` | View mirrored tasks |
|
|
124
|
+
| `eagle-mem orchestrate` | Coordinate durable worker lanes across agents |
|
|
121
125
|
| `eagle-mem curate` | Run curator (co-edits, hot files, guardrails) |
|
|
122
126
|
| `eagle-mem feature` | Track and verify features |
|
|
123
127
|
| `eagle-mem prune` | Clean old sessions and stale data |
|
|
@@ -130,7 +134,7 @@ Eagle Mem prevents Claude from repeating past mistakes:
|
|
|
130
134
|
eagle-mem search "auth bug" # keyword search across summaries
|
|
131
135
|
eagle-mem search --timeline # recent sessions in chronological order
|
|
132
136
|
eagle-mem search --overview # project overview
|
|
133
|
-
eagle-mem search --memories # mirrored
|
|
137
|
+
eagle-mem search --memories # mirrored agent memories
|
|
134
138
|
eagle-mem search --tasks # in-flight tasks (pending/in-progress)
|
|
135
139
|
eagle-mem search --files # most frequently modified files
|
|
136
140
|
eagle-mem search --stats # project statistics
|
|
@@ -149,6 +153,32 @@ Verification is tied to the current git diff fingerprint. If the same diff was a
|
|
|
149
153
|
|
|
150
154
|
Dry-run validation stays unblocked. For example, `gh pr create --dry-run` and `npm publish --dry-run` are treated as validation. Explicit real commands such as `npm publish --dry-run=false` are treated as release boundaries and will enforce pending feature verification.
|
|
151
155
|
|
|
156
|
+
### Orchestrator/Worker Lanes
|
|
157
|
+
|
|
158
|
+
Use orchestration when a broad task is split across Claude Code, Codex, subagents, or separate worktrees. These are **agent-run commands**: Eagle Mem injects the protocol into Claude Code/Codex, and the active agent runs the lane/status/spawn commands itself. Users should not have to operate this manually.
|
|
159
|
+
|
|
160
|
+
By default Eagle Mem uses the opposite-agent worker model:
|
|
161
|
+
|
|
162
|
+
- Codex coordinator -> Claude Code worker using `claude-opus-4-7` at `xhigh`
|
|
163
|
+
- Claude Code coordinator -> Codex worker using `gpt-5.5` at `xhigh`
|
|
164
|
+
|
|
165
|
+
Worker models, effort, route, and worktree behavior are configurable in `~/.eagle-mem/config.toml` under `[orchestration]`.
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
eagle-mem orchestrate init "Ship auth cleanup"
|
|
169
|
+
eagle-mem orchestrate lane add api --agent codex --desc "API fixes + tests" --validate "npm test"
|
|
170
|
+
eagle-mem orchestrate lane add docs --agent claude-code --desc "README and release notes"
|
|
171
|
+
eagle-mem orchestrate spawn api
|
|
172
|
+
eagle-mem orchestrate sync
|
|
173
|
+
eagle-mem orchestrate complete
|
|
174
|
+
eagle-mem orchestrate handoff --write docs/handoff-context.md
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
`spawn` creates a git worktree, writes a self-contained worker prompt, launches the selected worker CLI, captures its log/exit status under `~/.eagle-mem/orchestrations/`, and updates lane/task state when the worker finishes. Worker hooks export the original Eagle Mem project name, so observations and summaries created inside worktrees still attach to the main project memory.
|
|
178
|
+
Use `lane complete` or `lane block` manually only when work happened outside the wrapper or the worker needs an explicit correction.
|
|
179
|
+
|
|
180
|
+
Each lane is stored in `orchestration_lanes` and mirrored into `agent_tasks`, so the next Claude Code or Codex session sees what is pending, who owns it, which worktree/log belongs to it, and how to validate it.
|
|
181
|
+
|
|
152
182
|
### Shared Claude Code + Codex Memory
|
|
153
183
|
|
|
154
184
|
Both agents write to `~/.eagle-mem/memory.db`:
|
|
@@ -160,14 +190,15 @@ Both agents write to `~/.eagle-mem/memory.db`:
|
|
|
160
190
|
|
|
161
191
|
That means opening the same project in Claude Code and Codex does not create two isolated memory worlds. They recall the same project history while preserving the source of each memory.
|
|
162
192
|
|
|
163
|
-
## Skills (Inside Claude Code)
|
|
193
|
+
## Skills (Inside Claude Code and Codex)
|
|
164
194
|
|
|
165
195
|
| Skill | What It Does |
|
|
166
196
|
|-------|-------------|
|
|
167
197
|
| `/eagle-mem-search` | Search memory and past sessions — Claude interprets results in context |
|
|
168
198
|
| `/eagle-mem-overview` | Build a rich project briefing from README, entry points, and git history |
|
|
169
|
-
| `/eagle-mem-memories` | View and search mirrored
|
|
199
|
+
| `/eagle-mem-memories` | View and search mirrored agent memories and plans |
|
|
170
200
|
| `/eagle-mem-tasks` | TaskAware Compact Loop — break complex work into tasks that survive `/compact` |
|
|
201
|
+
| `/eagle-mem-orchestrate` | Orchestrator/worker lane handoffs across Claude Code and Codex |
|
|
171
202
|
|
|
172
203
|
## Data
|
|
173
204
|
|
|
@@ -188,10 +219,12 @@ Single SQLite database at `~/.eagle-mem/memory.db` (WAL mode, FTS5 full-text sea
|
|
|
188
219
|
| `feature_dependencies` | Inter-feature dependency relationships |
|
|
189
220
|
| `feature_smoke_tests` | Smoke test definitions for feature verification |
|
|
190
221
|
| `pending_feature_verifications` | Release blockers created when files tied to features change |
|
|
222
|
+
| `orchestrations` | Durable multi-agent work plans per project |
|
|
223
|
+
| `orchestration_lanes` | Worker lane ownership, status, validation, worktree, and notes |
|
|
191
224
|
| `eagle_meta` | Internal metadata (last scan, last curate, etc.) |
|
|
192
|
-
| `
|
|
193
|
-
| `
|
|
194
|
-
| `
|
|
225
|
+
| `agent_memories` | Mirror of agent memory files, with source attribution |
|
|
226
|
+
| `agent_plans` | Mirror of agent plan files, with source attribution |
|
|
227
|
+
| `agent_tasks` | Mirror of agent task records, with source attribution |
|
|
195
228
|
|
|
196
229
|
### Project Identity
|
|
197
230
|
|
|
@@ -207,9 +240,20 @@ Some features (curator auto-enrichment, overview generation) can use an LLM for
|
|
|
207
240
|
|
|
208
241
|
```bash
|
|
209
242
|
eagle-mem config
|
|
243
|
+
eagle-mem config set provider.type agent_cli
|
|
244
|
+
eagle-mem config set agent_cli.preferred current
|
|
210
245
|
```
|
|
211
246
|
|
|
212
|
-
|
|
247
|
+
Provider preference is local-first: Ollama is auto-detected when running, then Eagle Mem can use the installed Codex/Claude CLI via `agent_cli` before falling back to explicit Anthropic/OpenAI API providers. Eagle Mem works fully without a provider — LLM features gracefully degrade to heuristic fallbacks.
|
|
248
|
+
|
|
249
|
+
RTK is configured separately from the LLM provider:
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
eagle-mem config set token_guard.rtk auto # default: use RTK when available
|
|
253
|
+
eagle-mem config set token_guard.rtk enforce # block known raw-output commands if RTK is missing
|
|
254
|
+
eagle-mem config set token_guard.rtk off # disable RTK behavior
|
|
255
|
+
eagle-mem config set token_guard.raw_bash block
|
|
256
|
+
```
|
|
213
257
|
|
|
214
258
|
## License
|
|
215
259
|
|
package/bin/eagle-mem
CHANGED
|
@@ -26,6 +26,7 @@ case "$command" in
|
|
|
26
26
|
overview) bash "$SCRIPTS_DIR/overview.sh" "$@" ;;
|
|
27
27
|
memories) bash "$SCRIPTS_DIR/memories.sh" "$@" ;;
|
|
28
28
|
tasks) bash "$SCRIPTS_DIR/tasks.sh" "$@" ;;
|
|
29
|
+
orchestrate) bash "$SCRIPTS_DIR/orchestrate.sh" "$@" ;;
|
|
29
30
|
curate) bash "$SCRIPTS_DIR/curate.sh" "$@" ;;
|
|
30
31
|
feature) bash "$SCRIPTS_DIR/feature.sh" "$@" ;;
|
|
31
32
|
prune) bash "$SCRIPTS_DIR/prune.sh" "$@" ;;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
-- Migration 028: Promote mirrored artifact tables from Claude-specific names
|
|
2
|
+
-- to agent-generic names. The original names were correct when Eagle Mem only
|
|
3
|
+
-- mirrored Claude Code artifacts; Codex support made the stored data model
|
|
4
|
+
-- multi-agent. Keep read-only legacy views so older ad-hoc SELECT queries do
|
|
5
|
+
-- not break immediately.
|
|
6
|
+
|
|
7
|
+
DROP TRIGGER IF EXISTS claude_memories_ai;
|
|
8
|
+
DROP TRIGGER IF EXISTS claude_memories_ad;
|
|
9
|
+
DROP TRIGGER IF EXISTS claude_memories_au;
|
|
10
|
+
DROP TRIGGER IF EXISTS claude_plans_ai;
|
|
11
|
+
DROP TRIGGER IF EXISTS claude_plans_ad;
|
|
12
|
+
DROP TRIGGER IF EXISTS claude_plans_au;
|
|
13
|
+
DROP TRIGGER IF EXISTS claude_tasks_ai;
|
|
14
|
+
DROP TRIGGER IF EXISTS claude_tasks_ad;
|
|
15
|
+
DROP TRIGGER IF EXISTS claude_tasks_au;
|
|
16
|
+
|
|
17
|
+
DROP TABLE IF EXISTS claude_memories_fts;
|
|
18
|
+
DROP TABLE IF EXISTS claude_plans_fts;
|
|
19
|
+
DROP TABLE IF EXISTS claude_tasks_fts;
|
|
20
|
+
|
|
21
|
+
ALTER TABLE claude_memories RENAME TO agent_memories;
|
|
22
|
+
ALTER TABLE claude_plans RENAME TO agent_plans;
|
|
23
|
+
ALTER TABLE claude_tasks RENAME TO agent_tasks;
|
|
24
|
+
|
|
25
|
+
DROP INDEX IF EXISTS idx_claude_memories_project;
|
|
26
|
+
DROP INDEX IF EXISTS idx_claude_memories_type;
|
|
27
|
+
DROP INDEX IF EXISTS idx_claude_memories_origin_agent;
|
|
28
|
+
DROP INDEX IF EXISTS idx_claude_plans_project;
|
|
29
|
+
DROP INDEX IF EXISTS idx_claude_plans_origin_agent;
|
|
30
|
+
DROP INDEX IF EXISTS idx_claude_tasks_project;
|
|
31
|
+
DROP INDEX IF EXISTS idx_claude_tasks_session;
|
|
32
|
+
DROP INDEX IF EXISTS idx_claude_tasks_status;
|
|
33
|
+
DROP INDEX IF EXISTS idx_claude_tasks_origin_agent;
|
|
34
|
+
|
|
35
|
+
CREATE INDEX IF NOT EXISTS idx_agent_memories_project ON agent_memories(project);
|
|
36
|
+
CREATE INDEX IF NOT EXISTS idx_agent_memories_type ON agent_memories(memory_type);
|
|
37
|
+
CREATE INDEX IF NOT EXISTS idx_agent_memories_origin_agent ON agent_memories(origin_agent);
|
|
38
|
+
CREATE INDEX IF NOT EXISTS idx_agent_plans_project ON agent_plans(project);
|
|
39
|
+
CREATE INDEX IF NOT EXISTS idx_agent_plans_origin_agent ON agent_plans(origin_agent);
|
|
40
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_project ON agent_tasks(project);
|
|
41
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_session ON agent_tasks(source_session_id);
|
|
42
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_status ON agent_tasks(status);
|
|
43
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_origin_agent ON agent_tasks(origin_agent);
|
|
44
|
+
|
|
45
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS agent_memories_fts USING fts5(
|
|
46
|
+
memory_name,
|
|
47
|
+
description,
|
|
48
|
+
content,
|
|
49
|
+
content='agent_memories',
|
|
50
|
+
content_rowid='id'
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS agent_plans_fts USING fts5(
|
|
54
|
+
title,
|
|
55
|
+
content,
|
|
56
|
+
content='agent_plans',
|
|
57
|
+
content_rowid='id'
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS agent_tasks_fts USING fts5(
|
|
61
|
+
subject,
|
|
62
|
+
description,
|
|
63
|
+
content='agent_tasks',
|
|
64
|
+
content_rowid='id'
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
INSERT INTO agent_memories_fts(agent_memories_fts) VALUES('rebuild');
|
|
68
|
+
INSERT INTO agent_plans_fts(agent_plans_fts) VALUES('rebuild');
|
|
69
|
+
INSERT INTO agent_tasks_fts(agent_tasks_fts) VALUES('rebuild');
|
|
70
|
+
|
|
71
|
+
CREATE TRIGGER IF NOT EXISTS agent_memories_ai AFTER INSERT ON agent_memories BEGIN
|
|
72
|
+
INSERT INTO agent_memories_fts(rowid, memory_name, description, content)
|
|
73
|
+
VALUES (new.id, new.memory_name, new.description, new.content);
|
|
74
|
+
END;
|
|
75
|
+
|
|
76
|
+
CREATE TRIGGER IF NOT EXISTS agent_memories_ad AFTER DELETE ON agent_memories BEGIN
|
|
77
|
+
INSERT INTO agent_memories_fts(agent_memories_fts, rowid, memory_name, description, content)
|
|
78
|
+
VALUES ('delete', old.id, old.memory_name, old.description, old.content);
|
|
79
|
+
END;
|
|
80
|
+
|
|
81
|
+
CREATE TRIGGER IF NOT EXISTS agent_memories_au AFTER UPDATE ON agent_memories BEGIN
|
|
82
|
+
INSERT INTO agent_memories_fts(agent_memories_fts, rowid, memory_name, description, content)
|
|
83
|
+
VALUES ('delete', old.id, old.memory_name, old.description, old.content);
|
|
84
|
+
INSERT INTO agent_memories_fts(rowid, memory_name, description, content)
|
|
85
|
+
VALUES (new.id, new.memory_name, new.description, new.content);
|
|
86
|
+
END;
|
|
87
|
+
|
|
88
|
+
CREATE TRIGGER IF NOT EXISTS agent_plans_ai AFTER INSERT ON agent_plans BEGIN
|
|
89
|
+
INSERT INTO agent_plans_fts(rowid, title, content)
|
|
90
|
+
VALUES (new.id, new.title, new.content);
|
|
91
|
+
END;
|
|
92
|
+
|
|
93
|
+
CREATE TRIGGER IF NOT EXISTS agent_plans_ad AFTER DELETE ON agent_plans BEGIN
|
|
94
|
+
INSERT INTO agent_plans_fts(agent_plans_fts, rowid, title, content)
|
|
95
|
+
VALUES ('delete', old.id, old.title, old.content);
|
|
96
|
+
END;
|
|
97
|
+
|
|
98
|
+
CREATE TRIGGER IF NOT EXISTS agent_plans_au AFTER UPDATE ON agent_plans BEGIN
|
|
99
|
+
INSERT INTO agent_plans_fts(agent_plans_fts, rowid, title, content)
|
|
100
|
+
VALUES ('delete', old.id, old.title, old.content);
|
|
101
|
+
INSERT INTO agent_plans_fts(rowid, title, content)
|
|
102
|
+
VALUES (new.id, new.title, new.content);
|
|
103
|
+
END;
|
|
104
|
+
|
|
105
|
+
CREATE TRIGGER IF NOT EXISTS agent_tasks_ai AFTER INSERT ON agent_tasks BEGIN
|
|
106
|
+
INSERT INTO agent_tasks_fts(rowid, subject, description)
|
|
107
|
+
VALUES (new.id, new.subject, new.description);
|
|
108
|
+
END;
|
|
109
|
+
|
|
110
|
+
CREATE TRIGGER IF NOT EXISTS agent_tasks_ad AFTER DELETE ON agent_tasks BEGIN
|
|
111
|
+
INSERT INTO agent_tasks_fts(agent_tasks_fts, rowid, subject, description)
|
|
112
|
+
VALUES ('delete', old.id, old.subject, old.description);
|
|
113
|
+
END;
|
|
114
|
+
|
|
115
|
+
CREATE TRIGGER IF NOT EXISTS agent_tasks_au AFTER UPDATE ON agent_tasks BEGIN
|
|
116
|
+
INSERT INTO agent_tasks_fts(agent_tasks_fts, rowid, subject, description)
|
|
117
|
+
VALUES ('delete', old.id, old.subject, old.description);
|
|
118
|
+
INSERT INTO agent_tasks_fts(rowid, subject, description)
|
|
119
|
+
VALUES (new.id, new.subject, new.description);
|
|
120
|
+
END;
|
|
121
|
+
|
|
122
|
+
CREATE VIEW IF NOT EXISTS claude_memories AS SELECT * FROM agent_memories;
|
|
123
|
+
CREATE VIEW IF NOT EXISTS claude_plans AS SELECT * FROM agent_plans;
|
|
124
|
+
CREATE VIEW IF NOT EXISTS claude_tasks AS SELECT * FROM agent_tasks;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
-- Migration 029: Orchestrator/worker lane tracking.
|
|
2
|
+
-- Stores durable multi-agent work plans so Claude Code and Codex can share
|
|
3
|
+
-- lane ownership, status, validation commands, and handoff context.
|
|
4
|
+
|
|
5
|
+
CREATE TABLE IF NOT EXISTS orchestrations (
|
|
6
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
7
|
+
project TEXT NOT NULL,
|
|
8
|
+
name TEXT NOT NULL,
|
|
9
|
+
goal TEXT,
|
|
10
|
+
status TEXT NOT NULL DEFAULT 'active'
|
|
11
|
+
CHECK (status IN ('active', 'completed', 'cancelled')),
|
|
12
|
+
baseline_ref TEXT,
|
|
13
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
14
|
+
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
15
|
+
UNIQUE(project, name)
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
CREATE INDEX IF NOT EXISTS idx_orchestrations_project_status
|
|
19
|
+
ON orchestrations(project, status);
|
|
20
|
+
|
|
21
|
+
CREATE TABLE IF NOT EXISTS orchestration_lanes (
|
|
22
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
23
|
+
orchestration_id INTEGER NOT NULL REFERENCES orchestrations(id) ON DELETE CASCADE,
|
|
24
|
+
project TEXT NOT NULL,
|
|
25
|
+
lane_key TEXT NOT NULL,
|
|
26
|
+
title TEXT NOT NULL,
|
|
27
|
+
description TEXT,
|
|
28
|
+
agent TEXT NOT NULL DEFAULT 'codex',
|
|
29
|
+
worktree_path TEXT,
|
|
30
|
+
validation TEXT,
|
|
31
|
+
status TEXT NOT NULL DEFAULT 'pending'
|
|
32
|
+
CHECK (status IN ('pending', 'in_progress', 'blocked', 'completed', 'cancelled')),
|
|
33
|
+
source_task_id TEXT,
|
|
34
|
+
notes TEXT,
|
|
35
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
36
|
+
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
37
|
+
UNIQUE(orchestration_id, lane_key)
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
CREATE INDEX IF NOT EXISTS idx_orchestration_lanes_orchestration
|
|
41
|
+
ON orchestration_lanes(orchestration_id);
|
|
42
|
+
CREATE INDEX IF NOT EXISTS idx_orchestration_lanes_project_status
|
|
43
|
+
ON orchestration_lanes(project, status);
|
|
44
|
+
CREATE INDEX IF NOT EXISTS idx_orchestration_lanes_agent
|
|
45
|
+
ON orchestration_lanes(agent);
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
-- Migration 030: Scope orchestration lane identity to each orchestration.
|
|
2
|
+
-- Early 029 builds made lane_key unique per project, which allowed a lane
|
|
3
|
+
-- named "api" in one named orchestration to overwrite the same key in another.
|
|
4
|
+
|
|
5
|
+
DROP INDEX IF EXISTS idx_orchestration_lanes_orchestration;
|
|
6
|
+
DROP INDEX IF EXISTS idx_orchestration_lanes_project_status;
|
|
7
|
+
DROP INDEX IF EXISTS idx_orchestration_lanes_agent;
|
|
8
|
+
|
|
9
|
+
CREATE TABLE IF NOT EXISTS orchestration_lanes_new (
|
|
10
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
11
|
+
orchestration_id INTEGER NOT NULL REFERENCES orchestrations(id) ON DELETE CASCADE,
|
|
12
|
+
project TEXT NOT NULL,
|
|
13
|
+
lane_key TEXT NOT NULL,
|
|
14
|
+
title TEXT NOT NULL,
|
|
15
|
+
description TEXT,
|
|
16
|
+
agent TEXT NOT NULL DEFAULT 'codex',
|
|
17
|
+
worktree_path TEXT,
|
|
18
|
+
validation TEXT,
|
|
19
|
+
status TEXT NOT NULL DEFAULT 'pending'
|
|
20
|
+
CHECK (status IN ('pending', 'in_progress', 'blocked', 'completed', 'cancelled')),
|
|
21
|
+
source_task_id TEXT,
|
|
22
|
+
notes TEXT,
|
|
23
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
24
|
+
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
25
|
+
UNIQUE(orchestration_id, lane_key)
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
INSERT OR IGNORE INTO orchestration_lanes_new (
|
|
29
|
+
id, orchestration_id, project, lane_key, title, description, agent,
|
|
30
|
+
worktree_path, validation, status, source_task_id, notes, created_at, updated_at
|
|
31
|
+
)
|
|
32
|
+
SELECT
|
|
33
|
+
id, orchestration_id, project, lane_key, title, description, agent,
|
|
34
|
+
worktree_path, validation, status, source_task_id, notes, created_at, updated_at
|
|
35
|
+
FROM orchestration_lanes;
|
|
36
|
+
|
|
37
|
+
DROP TABLE orchestration_lanes;
|
|
38
|
+
ALTER TABLE orchestration_lanes_new RENAME TO orchestration_lanes;
|
|
39
|
+
|
|
40
|
+
CREATE INDEX IF NOT EXISTS idx_orchestration_lanes_orchestration
|
|
41
|
+
ON orchestration_lanes(orchestration_id);
|
|
42
|
+
CREATE INDEX IF NOT EXISTS idx_orchestration_lanes_project_status
|
|
43
|
+
ON orchestration_lanes(project, status);
|
|
44
|
+
CREATE INDEX IF NOT EXISTS idx_orchestration_lanes_agent
|
|
45
|
+
ON orchestration_lanes(agent);
|
|
46
|
+
|
|
47
|
+
UPDATE orchestration_lanes
|
|
48
|
+
SET source_task_id = 'lane-' || (
|
|
49
|
+
SELECT name FROM orchestrations WHERE orchestrations.id = orchestration_lanes.orchestration_id
|
|
50
|
+
) || '-' || lane_key
|
|
51
|
+
WHERE source_task_id IS NULL
|
|
52
|
+
OR source_task_id = ''
|
|
53
|
+
OR source_task_id = 'lane-' || lane_key;
|
|
54
|
+
|
|
55
|
+
UPDATE agent_tasks
|
|
56
|
+
SET source_task_id = (
|
|
57
|
+
SELECT l.source_task_id
|
|
58
|
+
FROM orchestration_lanes l
|
|
59
|
+
JOIN orchestrations o ON o.id = l.orchestration_id
|
|
60
|
+
WHERE l.project = agent_tasks.project
|
|
61
|
+
AND (
|
|
62
|
+
agent_tasks.file_path = 'orchestration-lane://' || l.project || '/' || l.lane_key
|
|
63
|
+
OR agent_tasks.file_path = 'orchestration-lane://' || l.project || '/' || o.name || '/' || l.lane_key
|
|
64
|
+
)
|
|
65
|
+
LIMIT 1
|
|
66
|
+
),
|
|
67
|
+
file_path = (
|
|
68
|
+
SELECT 'orchestration-lane://' || l.project || '/' || o.name || '/' || l.lane_key
|
|
69
|
+
FROM orchestration_lanes l
|
|
70
|
+
JOIN orchestrations o ON o.id = l.orchestration_id
|
|
71
|
+
WHERE l.project = agent_tasks.project
|
|
72
|
+
AND (
|
|
73
|
+
agent_tasks.file_path = 'orchestration-lane://' || l.project || '/' || l.lane_key
|
|
74
|
+
OR agent_tasks.file_path = 'orchestration-lane://' || l.project || '/' || o.name || '/' || l.lane_key
|
|
75
|
+
)
|
|
76
|
+
LIMIT 1
|
|
77
|
+
)
|
|
78
|
+
WHERE source_session_id = 'orchestration'
|
|
79
|
+
AND EXISTS (
|
|
80
|
+
SELECT 1
|
|
81
|
+
FROM orchestration_lanes l
|
|
82
|
+
JOIN orchestrations o ON o.id = l.orchestration_id
|
|
83
|
+
WHERE l.project = agent_tasks.project
|
|
84
|
+
AND (
|
|
85
|
+
agent_tasks.file_path = 'orchestration-lane://' || l.project || '/' || l.lane_key
|
|
86
|
+
OR agent_tasks.file_path = 'orchestration-lane://' || l.project || '/' || o.name || '/' || l.lane_key
|
|
87
|
+
)
|
|
88
|
+
);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
-- Migration 031: Worker execution metadata for orchestration lanes.
|
|
2
|
+
-- Keeps worker routing, worktree, process, and log state durable so Claude Code
|
|
3
|
+
-- and Codex can hand off lane execution safely.
|
|
4
|
+
|
|
5
|
+
ALTER TABLE orchestration_lanes ADD COLUMN branch_name TEXT;
|
|
6
|
+
ALTER TABLE orchestration_lanes ADD COLUMN worker_agent TEXT;
|
|
7
|
+
ALTER TABLE orchestration_lanes ADD COLUMN worker_model TEXT;
|
|
8
|
+
ALTER TABLE orchestration_lanes ADD COLUMN worker_effort TEXT;
|
|
9
|
+
ALTER TABLE orchestration_lanes ADD COLUMN worker_pid INTEGER;
|
|
10
|
+
ALTER TABLE orchestration_lanes ADD COLUMN worker_log_path TEXT;
|
|
11
|
+
ALTER TABLE orchestration_lanes ADD COLUMN worker_exit_path TEXT;
|
|
12
|
+
ALTER TABLE orchestration_lanes ADD COLUMN worker_prompt_path TEXT;
|
|
13
|
+
ALTER TABLE orchestration_lanes ADD COLUMN worker_command TEXT;
|
|
14
|
+
ALTER TABLE orchestration_lanes ADD COLUMN worker_started_at TEXT;
|
|
15
|
+
ALTER TABLE orchestration_lanes ADD COLUMN worker_finished_at TEXT;
|
|
16
|
+
|
|
17
|
+
CREATE INDEX IF NOT EXISTS idx_orchestration_lanes_worker_pid
|
|
18
|
+
ON orchestration_lanes(worker_pid);
|
|
19
|
+
CREATE INDEX IF NOT EXISTS idx_orchestration_lanes_branch
|
|
20
|
+
ON orchestration_lanes(branch_name);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
-- Migration 032: Stable run identity for reusable orchestration names.
|
|
2
|
+
-- A project may reuse the default orchestration name ("main") for multiple
|
|
3
|
+
-- goals, so worker branches and worktrees need a per-run key.
|
|
4
|
+
|
|
5
|
+
ALTER TABLE orchestrations ADD COLUMN run_key TEXT;
|
|
6
|
+
|
|
7
|
+
UPDATE orchestrations
|
|
8
|
+
SET run_key = 'r' || id
|
|
9
|
+
WHERE run_key IS NULL OR run_key = '';
|
package/hooks/post-tool-use.sh
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
# Captures observations + dispatches to extracted responsibilities
|
|
6
6
|
# ═══════════════════════════════════════════════════════════
|
|
7
7
|
set +e
|
|
8
|
+
[ "${EAGLE_MEM_DISABLE_HOOKS:-}" = "1" ] && exit 0
|
|
8
9
|
|
|
9
10
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
10
11
|
LIB_DIR="$SCRIPT_DIR/../lib"
|
|
@@ -54,7 +55,7 @@ case "$hook_event" in
|
|
|
54
55
|
agent_sql=$(eagle_sql_escape "$agent")
|
|
55
56
|
|
|
56
57
|
eagle_db_pipe <<SQL
|
|
57
|
-
INSERT INTO
|
|
58
|
+
INSERT INTO agent_tasks (project, source_session_id, source_task_id, file_path, subject, description, status, origin_agent)
|
|
58
59
|
VALUES ('$proj_sql', '$sid_sql', '$tid_sql', '$fp_sql', '$subj_sql', '$desc_sql', '$stat_sql', '$agent_sql')
|
|
59
60
|
ON CONFLICT(file_path) DO UPDATE SET
|
|
60
61
|
subject = excluded.subject,
|
package/hooks/pre-tool-use.sh
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
# 6. Stuck loop detection (repeated edits to same file)
|
|
11
11
|
# ═══════════════════════════════════════════════════════════
|
|
12
12
|
set +e
|
|
13
|
+
[ "${EAGLE_MEM_DISABLE_HOOKS:-}" = "1" ] && exit 0
|
|
13
14
|
|
|
14
15
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
15
16
|
LIB_DIR="$SCRIPT_DIR/../lib"
|
|
@@ -90,9 +91,11 @@ Pending checks:"
|
|
|
90
91
|
|
|
91
92
|
# ─── RTK command rewrite / enforcement ─────────────────
|
|
92
93
|
|
|
94
|
+
rtk_mode=$(eagle_token_guard_rtk_mode)
|
|
95
|
+
raw_bash_mode=$(eagle_token_guard_raw_bash_mode)
|
|
93
96
|
rtk_cmd=$(eagle_rtk_rewrite_command "$cmd")
|
|
94
97
|
if [ -n "$rtk_cmd" ]; then
|
|
95
|
-
if [ "$agent" = "codex" ] && ! eagle_raw_bash_unlock_active; then
|
|
98
|
+
if [ "$agent" = "codex" ] && [ "$raw_bash_mode" != "allow" ] && ! eagle_raw_bash_unlock_active; then
|
|
96
99
|
reason="Eagle Mem token guard blocked raw shell output.
|
|
97
100
|
|
|
98
101
|
Use RTK so large output is compact before it enters context:
|
|
@@ -116,6 +119,27 @@ Temporary escape hatch for one-off raw output:
|
|
|
116
119
|
updated_input=$(echo "$input" | jq --arg cmd "$rtk_cmd" '.tool_input + {"command":$cmd}')
|
|
117
120
|
context+="Eagle Mem token guard: rewrote raw shell command through RTK to reduce context load: ${rtk_cmd}. "
|
|
118
121
|
fi
|
|
122
|
+
elif [ "$rtk_mode" = "enforce" ] && ! command -v rtk >/dev/null 2>&1 && eagle_raw_output_command_needs_guard "$cmd" && ! eagle_raw_bash_unlock_active; then
|
|
123
|
+
reason="Eagle Mem token guard is set to enforce, but RTK is not installed or not on PATH.
|
|
124
|
+
|
|
125
|
+
This command can dump raw output into agent context:
|
|
126
|
+
$cmd
|
|
127
|
+
|
|
128
|
+
Install RTK or disable enforcement:
|
|
129
|
+
eagle-mem config set token_guard.rtk auto
|
|
130
|
+
|
|
131
|
+
Temporary escape hatch:
|
|
132
|
+
touch $EAGLE_RAW_BASH_UNLOCK"
|
|
133
|
+
jq -nc --arg reason "$reason" '{
|
|
134
|
+
"decision":"block",
|
|
135
|
+
"reason":$reason,
|
|
136
|
+
"hookSpecificOutput":{
|
|
137
|
+
"hookEventName":"PreToolUse",
|
|
138
|
+
"permissionDecision":"deny",
|
|
139
|
+
"permissionDecisionReason":$reason
|
|
140
|
+
}
|
|
141
|
+
}'
|
|
142
|
+
exit 0
|
|
119
143
|
fi
|
|
120
144
|
|
|
121
145
|
# ─── Feature verification context for non-blocked pushes ───
|
package/hooks/session-end.sh
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
# Marks the session as completed
|
|
6
6
|
# ═══════════════════════════════════════════════════════════
|
|
7
7
|
set +e
|
|
8
|
+
[ "${EAGLE_MEM_DISABLE_HOOKS:-}" = "1" ] && exit 0
|
|
8
9
|
|
|
9
10
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
10
11
|
LIB_DIR="$SCRIPT_DIR/../lib"
|
|
@@ -31,7 +32,7 @@ if eagle_validate_session_id "$session_id"; then
|
|
|
31
32
|
if [ -d "$task_dir" ]; then
|
|
32
33
|
for task_file in "$task_dir"/*.json; do
|
|
33
34
|
[ ! -f "$task_file" ] && continue
|
|
34
|
-
|
|
35
|
+
eagle_capture_agent_task "$task_file" "$session_id" "$project" "$agent"
|
|
35
36
|
done
|
|
36
37
|
eagle_log "INFO" "SessionEnd: re-synced tasks from $task_dir"
|
|
37
38
|
fi
|