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 CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  **Context that survives `/compact`.**
11
11
 
12
- **v4.7.0 adds first-class Codex support and enforced anti-regression checks.**
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 rewrites noisy Bash commands to pipe through `head -N` via `updatedInput`. Rules are learned by the curator from real usage, not hardcoded.
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 Claude Code memories |
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 Claude Code memories
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 Claude Code memories and plans |
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
- | `claude_memories` | Mirror of Claude Code auto-memories |
193
- | `claude_plans` | Mirror of Claude Code plans |
194
- | `claude_tasks` | Mirror of Claude Code tasks |
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
- Supported providers: Ollama (auto-detected), Anthropic, OpenAI. Eagle Mem works fully without a provider — LLM features gracefully degrade to heuristic fallbacks.
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 = '';
@@ -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 claude_tasks (project, source_session_id, source_task_id, file_path, subject, description, status, origin_agent)
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,
@@ -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 ───
@@ -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
- eagle_capture_claude_task "$task_file" "$session_id" "$project" "$agent"
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