@essentialai/cogent-bridge 3.20.6 → 3.21.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/CHANGELOG.md CHANGED
@@ -1,5 +1,77 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.21.0 — 2026-08-31
4
+
5
+ ### Fixed — auto-wake refused on machines whose agent state is not in the default place
6
+
7
+ A developer's Claude Code peer refused every wake with `no candidate sessions found for cwd`,
8
+ from its very first register. Codex→Claude failed while Claude→Codex worked — the asymmetry was
9
+ the clue: **only the Claude Code rail derived the transcript location, and it derived it twice
10
+ over.**
11
+
12
+ ```
13
+ <config root> / projects / <cwd with non-alphanumerics turned into dashes>
14
+ ```
15
+
16
+ Both halves were guesses. The root was `CLAUDE_CONFIG_DIR` **or** a hardcoded `~/.claude` — one
17
+ guess, never verified. The cwd half ran a raw `String.replace` on the path string the agent
18
+ passed to `cogent_register_peer`, so every other spelling of the same directory encoded to a
19
+ directory that does not exist: a trailing slash, a `.` segment, or a symlinked path (macOS
20
+ `/tmp` → `/private/tmp`, `/var` → `/private/var`). Both misses were swallowed by
21
+ `catch { return [] }`, indistinguishable from an empty machine. The Codex rail had already been
22
+ hardened against exactly this (`cwdCanonicals`); the Claude rail never was.
23
+
24
+ **Session discovery is now layered, and only the last layer guesses:**
25
+
26
+ 1. **Reported (authoritative).** The host hands every hook `cwd`, `session_id` and
27
+ `transcript_path`. A new `SessionStart` hook (`record-session.mjs`) and the existing Stop hook
28
+ persist that trio to `~/.cogent/agent-sessions/`. The resolver prefers it, so there is nothing
29
+ to derive — this works with **any** relocated config dir, with no configuration at all.
30
+ 2. **Discovery.** No record yet (e.g. Team agents, which run without the plugin) → roots are
31
+ enumerated instead of guessed: `CLAUDE_CONFIG_DIR`, then roots **learned** from transcript
32
+ paths agents reported, then `~/.claude` and `~/.config/claude` — each crossed with the
33
+ canonical forms of the cwd (`path.resolve` **and** `fs.realpath`).
34
+ 3. **Fail loud.** Nothing matched → the refusal now **names every path it scanned**, and a
35
+ zero-candidate result at register time is a WARN plus a `warning`/`scannedPaths` field in the
36
+ tool result. Previously registration silently pinned the *cloud* session id, which `--resume`
37
+ can never open, guaranteeing that every later wake was refused.
38
+
39
+ One recorded session teaches the machine its root, so other projects under the same root resolve
40
+ with no record of their own.
41
+
42
+ ### Fixed — "clean uninstall" removed nothing for users with a relocated config dir
43
+
44
+ `scripts/uninstall-cogent.sh` and the hosted `uninstall.sh` hardcoded `$HOME/.claude` and
45
+ `$HOME/.codex`, so a custom-dir user got a success report while every plugin file stayed on
46
+ disk — which then makes a "fresh install test" silently measure the old install. Both scripts now
47
+ enumerate the same roots the bridge does (env → learned → conventions) and clean each one, and
48
+ the new `~/.cogent/agent-sessions` state directory is purged.
49
+
50
+ ### Guarded
51
+
52
+ - The hook↔bridge record path and `rootFromTranscriptPath` are asserted identical by
53
+ `scripts/wake-race-test.mjs` (a mismatch would make the authoritative layer silently inert),
54
+ and `record-session.mjs` joins the byte-identical plugin-parity check.
55
+ - New tests: representation tolerance (trailing slash / `.` segment / symlink / dedupe), the
56
+ learned-record store, and an end-to-end proof against a config root no heuristic could guess.
57
+ Verified by mutation — each layer was disabled in turn and the relevant tests went red.
58
+
59
+ ## 3.20.7 — 2026-08-31
60
+
61
+ ### Fixed — `cogent-codex` did nothing when installed from npm (silent exit)
62
+
63
+ Running `cogent-codex` printed nothing and returned straight to the prompt. npm installs the
64
+ command as a **symlink**, so `process.argv[1]` is the link while `import.meta.url` is the real
65
+ file; the CLI guard compared them directly, which is always false through a symlink, so
66
+ `main()` never ran. **The entire codex real-time-wake feature was dark for every npm-installed
67
+ user** since the launcher shipped.
68
+
69
+ Running the built file directly — the only way it had ever been tested — worked fine, which is
70
+ exactly why this reached users. The guard now compares **realpaths**, and a new regression test
71
+ invokes the command *through a symlink*, the way npm installs it (mutation-proven: reverting the
72
+ fix turns it red).
73
+
74
+
3
75
  ## 3.20.6 — 2026-08-28
4
76
 
5
77
  ### Fixed — the check-on-stop hook no longer fires inside the auto-relay's capture window (COG-20 root cause)
package/README.md CHANGED
@@ -69,6 +69,16 @@ turn. **One command installs everything** — the plugin **and** the `cogent-cod
69
69
  curl -fsSL https://cogent.tools/install.sh | sh
70
70
  ```
71
71
 
72
+ **Then reload your shell** so `cogent-codex` is on your PATH — the installer runs in a subshell
73
+ and cannot do this for you:
74
+
75
+ ```bash
76
+ exec $SHELL -l
77
+ ```
78
+
79
+ > Skip this and `cogent-codex` reports `command not found` in the terminal you installed from.
80
+ > Opening a brand-new terminal works too.
81
+
72
82
  Then start Codex with **`cogent-codex`** (instead of `codex`) and `/cogent:register`. `cogent-codex`
73
83
  runs Codex under a shared app-server daemon so a peer's message reaches you **mid-session** — the
74
84
  bridge auto-detects the rail, **no env var or config needed** (since 3.20.2).
@@ -103,6 +113,85 @@ codex mcp add cogent \
103
113
 
104
114
  …or, on Codex CLI 0.133.0+, the plugin: `codex plugin marketplace add eaisdevelopment/cogent && codex plugin add cogent@cogent`. Then use `cogent_register_peer` (or `/cogent:register`).
105
115
 
116
+ ### Gemini
117
+
118
+ Gemini joins a channel as a **standalone poll-agent**, not a plugin — it polls the relay and
119
+ answers on its own. Nothing to install as an MCP server, and nothing to `plugin update`.
120
+
121
+ ```bash
122
+ export GEMINI_API_KEY=<your-key>
123
+ COGENT_GEMINI_CHANNEL=<channel> COGENT_GEMINI_SECRET=<secret> COGENT_GEMINI_PEER=<name> \
124
+ node scripts/cogent-gemini-agent.mjs
125
+ ```
126
+
127
+ It registers itself and answers directed messages and human broadcasts like any other agent.
128
+ A systemd unit is provided at `scripts/cogent-gemini-agent.service`.
129
+
130
+ <!-- COGENT:COMMANDS:START -->
131
+ <!-- Generated by scripts/sync-docs.mjs from server/src/install/commands.ts.
132
+ Do NOT edit inside these markers — run `node scripts/sync-docs.mjs`. -->
133
+
134
+ ## Install
135
+
136
+ ### Claude Code
137
+
138
+ ```bash
139
+ claude plugin marketplace add https://cogent.tools/marketplace.json
140
+ claude plugin install cogent@cogent
141
+ ```
142
+
143
+ ### OpenAI Codex
144
+
145
+ ```bash
146
+ curl -fsSL https://cogent.tools/install.sh | sh
147
+ ```
148
+
149
+ **Then reload your shell so cogent-codex is on your PATH — without it the command reports 'command not found' in the terminal you installed from:**
150
+
151
+ ```bash
152
+ exec $SHELL -l
153
+ ```
154
+
155
+ ### Gemini
156
+
157
+ ```bash
158
+ export GEMINI_API_KEY=<your-key>
159
+ COGENT_GEMINI_CHANNEL=<channel> COGENT_GEMINI_SECRET=<secret> COGENT_GEMINI_PEER=<name> node scripts/cogent-gemini-agent.mjs
160
+ ```
161
+
162
+ _Standalone poll-agent — no plugin to install or update._
163
+
164
+ ## Updating
165
+
166
+ **Update from the CLI, then restart.** A restart alone changes nothing — the version
167
+ lives on disk and only moves when you update it.
168
+
169
+ | Agent | Update | Then |
170
+ |---|---|---|
171
+ | **Claude Code** | `claude plugin update cogent@cogent` | exit and restart the session |
172
+ | **OpenAI Codex** | `codex plugin marketplace upgrade` then `codex plugin add cogent@cogent` | restart cogent-codex |
173
+ | **Gemini** | _(no plugin)_ | restart the agent process (it is a standalone poll-agent, not a plugin) |
174
+
175
+ Verify it landed:
176
+
177
+ ```bash
178
+ claude plugin list | grep -A2 cogent
179
+ ```
180
+
181
+ ## Uninstalling
182
+
183
+ One command removes Cogent completely — both plugins, the launcher, caches and all
184
+ Cogent state — so you can verify a clean install. macOS, Linux, WSL and Git Bash:
185
+
186
+ ```bash
187
+ curl -fsSL https://cogent.tools/uninstall.sh | sh
188
+ ```
189
+
190
+ > **Never run `rm -rf ~/.cogent` — it also holds credentials Cogent never created and cannot recreate.** Your `.env` files and backups there are always preserved —
191
+ > the script lists everything it kept.
192
+
193
+ <!-- COGENT:COMMANDS:END -->
194
+
106
195
  ## Local vs Cloud mode
107
196
 
108
197
  Cogent runs in one of two modes. **Cloud is the default — you don't have to configure anything.**
@@ -1 +1 @@
1
- {"version":3,"file":"cogent-codex.d.ts","sourceRoot":"","sources":["../../src/bin/cogent-codex.ts"],"names":[],"mappings":";AAqEA,iFAAiF;AACjF,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAE3D;AAoDD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAO9D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ1F"}
1
+ {"version":3,"file":"cogent-codex.d.ts","sourceRoot":"","sources":["../../src/bin/cogent-codex.ts"],"names":[],"mappings":";AAsEA,iFAAiF;AACjF,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAE3D;AAoDD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAO9D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ1F"}
@@ -30,6 +30,7 @@
30
30
  * macOS + Linux. Windows (loopback `ws://…`) is not yet wired here.
31
31
  */
32
32
  import { spawn, spawnSync } from "node:child_process";
33
+ import { realpathSync } from "node:fs";
33
34
  import { readFile } from "node:fs/promises";
34
35
  import { createInterface } from "node:readline";
35
36
  import { pathToFileURL } from "node:url";
@@ -221,8 +222,28 @@ async function main() {
221
222
  handOff(codexBin, passthrough);
222
223
  }
223
224
  }
224
- // Run only when invoked as a CLI — importing this module (tests) must NOT launch codex.
225
- if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
225
+ /**
226
+ * Is this module being run as a CLI (rather than imported by a test)?
227
+ *
228
+ * 🔴 MUST compare REALPATHS. npm installs `cogent-codex` as a SYMLINK in its bin dir, so when a
229
+ * user runs it `process.argv[1]` is the link (…/bin/cogent-codex) while `import.meta.url` is the
230
+ * real file (…/dist/bin/cogent-codex.js). Comparing them directly is always false through a
231
+ * symlink, so `main()` never ran: the command printed nothing, exited 0, and returned the user
232
+ * straight to a fresh prompt — the entire codex real-time-wake feature was dark for every
233
+ * npm-installed user while running the file directly (how it was always tested) worked fine.
234
+ */
235
+ function invokedAsCli() {
236
+ const argv1 = process.argv[1];
237
+ if (!argv1)
238
+ return false;
239
+ try {
240
+ return import.meta.url === pathToFileURL(realpathSync(argv1)).href;
241
+ }
242
+ catch {
243
+ return import.meta.url === pathToFileURL(argv1).href; // unreadable path → best effort
244
+ }
245
+ }
246
+ if (invokedAsCli()) {
226
247
  main().catch((err) => {
227
248
  log(`fatal: ${err?.message ?? err}`);
228
249
  process.exit(1);
@@ -1 +1 @@
1
- {"version":3,"file":"cogent-codex.js","sourceRoot":"","sources":["../../src/bin/cogent-codex.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cogent-codex.js","sourceRoot":"","sources":["../../src/bin/cogent-codex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * LEARNED AGENT SESSION RECORDS — "the agent told us where it lives".
3
+ *
4
+ * 🔴 WHY THIS EXISTS. Everything downstream of the wake rails used to DERIVE the
5
+ * location of an agent's session transcript:
6
+ *
7
+ * <config root> / projects / <cwd with non-alphanumerics turned into dashes>
8
+ *
9
+ * Both halves of that are guesses. The config root was `CLAUDE_CONFIG_DIR` or a
10
+ * hardcoded `~/.claude` — one guess, never verified. The cwd half assumed the
11
+ * caller passed the exact canonical spelling of the directory. Either guess being
12
+ * wrong produced the same dead end: zero candidates, wake refused, and a log line
13
+ * that never named the path it looked in.
14
+ *
15
+ * The agents already publish the truth. Claude Code hands every hook a payload
16
+ * containing `cwd`, `session_id` and `transcript_path` — an ABSOLUTE path to the
17
+ * live transcript, with no encoding to reverse and no root to guess. This module
18
+ * is where that fact is persisted so the resolver can prefer it over inference.
19
+ *
20
+ * Layering (see docs + session-resolver):
21
+ * 1. this record — authoritative, works with ANY relocated config dir
22
+ * 2. root discovery — inference, for agents running without our plugin
23
+ * 3. fail loud — name every path probed
24
+ *
25
+ * Storage mirrors the existing per-cwd convention exactly (credential-store.ts,
26
+ * wake-inflight.ts): `~/.cogent/<kind>/<sha256(path.resolve(cwd))[..16]>.json`,
27
+ * homedir-based on purpose so the bridge and the hook — two processes with
28
+ * different environments — always agree on the path.
29
+ */
30
+ /** Platforms that keep a per-cwd session transcript we can learn. */
31
+ export type AgentPlatform = "cc" | "codex";
32
+ export interface AgentSessionRecord {
33
+ /** The cwd as the agent reported it (already resolved when written). */
34
+ cwd: string;
35
+ /** The agent's own session id — what `--resume` / `resume` takes. */
36
+ sessionId: string;
37
+ /** Absolute path to the transcript. The whole point: no derivation. */
38
+ transcriptPath: string;
39
+ /** Config root implied by transcriptPath, when it could be recovered. */
40
+ root?: string;
41
+ platform: AgentPlatform;
42
+ /** ISO timestamp of the last write. */
43
+ updatedAt: string;
44
+ }
45
+ /** MUST equal credential-store's hash and check-on-stop.lib.mjs credHashForCwd. */
46
+ export declare function hashCwd(cwd: string): string;
47
+ /** `~/.cogent/agent-sessions/` — the learned-record directory. */
48
+ export declare function agentSessionsDir(): string;
49
+ /**
50
+ * `~/.cogent/agent-sessions/<hash(cwd)>.<platform>.json`.
51
+ *
52
+ * Keyed by platform as well as cwd because one directory can host both a Claude
53
+ * Code and a Codex agent (that is the normal two-agent Cogent setup) and their
54
+ * transcripts live in completely different stores.
55
+ */
56
+ export declare function agentSessionPath(cwd: string, platform: AgentPlatform): string;
57
+ /**
58
+ * Recover the config ROOT from an absolute transcript path.
59
+ *
60
+ * Claude Code lays transcripts out as `<root>/projects/<encoded-cwd>/<id>.jsonl`,
61
+ * so the root is whatever sits above the `projects` segment — recovered by
62
+ * structure, never by matching a known prefix, which is what lets a completely
63
+ * unknown custom location teach us its root.
64
+ *
65
+ * Returns null when the shape does not match (a Codex rollout, a temp file, an
66
+ * agent that changes its layout) — callers must treat the root as optional.
67
+ */
68
+ export declare function rootFromTranscriptPath(transcriptPath: string): string | null;
69
+ /** Read the learned record for a cwd, or null. Never throws. */
70
+ export declare function readAgentSession(cwd: string, platform: AgentPlatform): Promise<AgentSessionRecord | null>;
71
+ /**
72
+ * Persist a learned record. Atomic (temp + rename) so a hook and the bridge
73
+ * writing concurrently can never leave a half-written file for the other to
74
+ * read — the same discipline peer-registry uses for shared state.
75
+ * Never throws: learning is an optimisation, never a reason to fail a wake.
76
+ */
77
+ export declare function writeAgentSession(rec: Omit<AgentSessionRecord, "updatedAt" | "root"> & {
78
+ root?: string;
79
+ }): Promise<boolean>;
80
+ /**
81
+ * Every distinct config root this machine has ever taught us, newest first.
82
+ *
83
+ * This is what turns one lucky resolution into permanent knowledge: a user with
84
+ * `CLAUDE_CONFIG_DIR=/data/claude` teaches us that root once, and afterwards
85
+ * EVERY project on the machine resolves against it — including ones opened in a
86
+ * shell where the variable was never exported. Bounded work: one readdir plus a
87
+ * small number of tiny JSON reads.
88
+ */
89
+ export declare function learnedRoots(platform: AgentPlatform): Promise<string[]>;
90
+ //# sourceMappingURL=agent-sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-sessions.d.ts","sourceRoot":"","sources":["../../src/services/agent-sessions.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,qEAAqE;AACrE,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,OAAO,CAAC;AAE3C,MAAM,WAAW,kBAAkB;IACjC,wEAAwE;IACxE,GAAG,EAAE,MAAM,CAAC;IACZ,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,cAAc,EAAE,MAAM,CAAC;IACvB,yEAAyE;IACzE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,aAAa,CAAC;IACxB,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,mFAAmF;AACnF,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAM3C;AAED,kEAAkE;AAClE,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,aAAa,GACtB,MAAM,CAER;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ5E;AAED,gEAAgE;AAChE,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAUpC;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,IAAI,CAAC,kBAAkB,EAAE,WAAW,GAAG,MAAM,CAAC,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GACtE,OAAO,CAAC,OAAO,CAAC,CAiBlB;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA4B7E"}
@@ -0,0 +1,120 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ /** MUST equal credential-store's hash and check-on-stop.lib.mjs credHashForCwd. */
6
+ export function hashCwd(cwd) {
7
+ return crypto
8
+ .createHash("sha256")
9
+ .update(path.resolve(cwd))
10
+ .digest("hex")
11
+ .slice(0, 16);
12
+ }
13
+ /** `~/.cogent/agent-sessions/` — the learned-record directory. */
14
+ export function agentSessionsDir() {
15
+ return path.join(os.homedir(), ".cogent", "agent-sessions");
16
+ }
17
+ /**
18
+ * `~/.cogent/agent-sessions/<hash(cwd)>.<platform>.json`.
19
+ *
20
+ * Keyed by platform as well as cwd because one directory can host both a Claude
21
+ * Code and a Codex agent (that is the normal two-agent Cogent setup) and their
22
+ * transcripts live in completely different stores.
23
+ */
24
+ export function agentSessionPath(cwd, platform) {
25
+ return path.join(agentSessionsDir(), `${hashCwd(cwd)}.${platform}.json`);
26
+ }
27
+ /**
28
+ * Recover the config ROOT from an absolute transcript path.
29
+ *
30
+ * Claude Code lays transcripts out as `<root>/projects/<encoded-cwd>/<id>.jsonl`,
31
+ * so the root is whatever sits above the `projects` segment — recovered by
32
+ * structure, never by matching a known prefix, which is what lets a completely
33
+ * unknown custom location teach us its root.
34
+ *
35
+ * Returns null when the shape does not match (a Codex rollout, a temp file, an
36
+ * agent that changes its layout) — callers must treat the root as optional.
37
+ */
38
+ export function rootFromTranscriptPath(transcriptPath) {
39
+ if (!transcriptPath)
40
+ return null;
41
+ const parts = path.resolve(transcriptPath).split(path.sep);
42
+ // …/<root>/projects/<encoded>/<id>.jsonl → need "projects" with a parent.
43
+ const i = parts.lastIndexOf("projects");
44
+ if (i <= 0)
45
+ return null;
46
+ const root = parts.slice(0, i).join(path.sep);
47
+ return root || path.sep;
48
+ }
49
+ /** Read the learned record for a cwd, or null. Never throws. */
50
+ export async function readAgentSession(cwd, platform) {
51
+ try {
52
+ const raw = await fs.readFile(agentSessionPath(cwd, platform), "utf-8");
53
+ const rec = JSON.parse(raw);
54
+ // A record without the two fields that make it useful is not a record.
55
+ if (!rec?.sessionId || !rec?.transcriptPath)
56
+ return null;
57
+ return rec;
58
+ }
59
+ catch {
60
+ return null;
61
+ }
62
+ }
63
+ /**
64
+ * Persist a learned record. Atomic (temp + rename) so a hook and the bridge
65
+ * writing concurrently can never leave a half-written file for the other to
66
+ * read — the same discipline peer-registry uses for shared state.
67
+ * Never throws: learning is an optimisation, never a reason to fail a wake.
68
+ */
69
+ export async function writeAgentSession(rec) {
70
+ try {
71
+ const full = {
72
+ ...rec,
73
+ cwd: path.resolve(rec.cwd),
74
+ root: rec.root ?? rootFromTranscriptPath(rec.transcriptPath) ?? undefined,
75
+ updatedAt: new Date().toISOString(),
76
+ };
77
+ const target = agentSessionPath(full.cwd, full.platform);
78
+ await fs.mkdir(path.dirname(target), { recursive: true });
79
+ const tmp = `${target}.${process.pid}.tmp`;
80
+ await fs.writeFile(tmp, JSON.stringify(full, null, 2), "utf-8");
81
+ await fs.rename(tmp, target);
82
+ return true;
83
+ }
84
+ catch {
85
+ return false;
86
+ }
87
+ }
88
+ /**
89
+ * Every distinct config root this machine has ever taught us, newest first.
90
+ *
91
+ * This is what turns one lucky resolution into permanent knowledge: a user with
92
+ * `CLAUDE_CONFIG_DIR=/data/claude` teaches us that root once, and afterwards
93
+ * EVERY project on the machine resolves against it — including ones opened in a
94
+ * shell where the variable was never exported. Bounded work: one readdir plus a
95
+ * small number of tiny JSON reads.
96
+ */
97
+ export async function learnedRoots(platform) {
98
+ try {
99
+ const dir = agentSessionsDir();
100
+ const files = (await fs.readdir(dir)).filter((f) => f.endsWith(`.${platform}.json`));
101
+ const recs = await Promise.all(files.map(async (f) => {
102
+ try {
103
+ return JSON.parse(await fs.readFile(path.join(dir, f), "utf-8"));
104
+ }
105
+ catch {
106
+ return null;
107
+ }
108
+ }));
109
+ return [
110
+ ...new Set(recs
111
+ .filter((r) => Boolean(r?.root))
112
+ .sort((a, b) => (a.updatedAt < b.updatedAt ? 1 : -1))
113
+ .map((r) => r.root)),
114
+ ];
115
+ }
116
+ catch {
117
+ return [];
118
+ }
119
+ }
120
+ //# sourceMappingURL=agent-sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-sessions.js","sourceRoot":"","sources":["../../src/services/agent-sessions.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,79 @@
1
1
  import { CliExecResult } from "../types.js";
2
+ /**
3
+ * Every transcript directory that could hold this cwd's sessions.
4
+ *
5
+ * 🔴 WHY THIS IS NOT ONE PATH. Claude Code names a project dir by replacing each
6
+ * non-alphanumeric char of the cwd with "-", so EVERY representation of the same
7
+ * directory encodes to a DIFFERENT name: a trailing slash, a "." segment, or a
8
+ * symlinked path (macOS `/tmp` -> `/private/tmp`, `/var` -> `/private/var`) each
9
+ * produce a dir that does not exist. The cwd here is a string the AGENT supplied
10
+ * to cogent_register_peer — it is not guaranteed to be the canonical form.
11
+ *
12
+ * That mismatch is how a fresh dev machine got ZERO candidates from its very
13
+ * first register (2026-08-31) and refused every wake thereafter. The Codex rail
14
+ * had already canonicalised for this reason (codex-cli.ts `cwdCanonicals`); this
15
+ * is the Claude Code rail reaching parity.
16
+ *
17
+ * Exported so callers can LOG what was probed — a miss used to be indistinguishable
18
+ * from an empty dir, which is what made the failure undiagnosable from the logs.
19
+ */
20
+ export declare function projectDirsFor(cwd: string): Promise<string[]>;
21
+ /**
22
+ * Every config root that could hold this machine's Claude Code transcripts,
23
+ * best-first.
24
+ *
25
+ * 🔴 WHY THIS IS A LIST. `claudeConfigDir()` returns ONE guess — the env var if
26
+ * this process happens to see it, otherwise `~/.claude`. A single guess has no
27
+ * way to be wrong loudly: it just scans a directory that does not exist and
28
+ * reports "no sessions". Users relocate their agent state (small system disks,
29
+ * synced or encrypted home dirs, multi-account machines, containers), and the
30
+ * env var does not always reach the process that needs it.
31
+ *
32
+ * Order is deliberate:
33
+ * 1. `CLAUDE_CONFIG_DIR` — an explicit instruction always wins.
34
+ * 2. LEARNED roots — recovered from transcript paths the agent itself reported
35
+ * (agent-sessions.ts). These are the only entries PROVEN to have held a real
36
+ * transcript, which is why they outrank the conventional defaults.
37
+ * 3. `~/.claude`, then `~/.config/claude` — the conventional locations.
38
+ *
39
+ * Probing a few extra directories costs one failed `readdir` each; missing the
40
+ * user's actual directory costs them the entire auto-wake feature.
41
+ */
42
+ export declare function claudeConfigRoots(): Promise<string[]>;
43
+ /**
44
+ * The transcript this cwd's agent REPORTED for itself, if the record is still
45
+ * valid on disk. This is layer 1 — the authoritative path — and it bypasses both
46
+ * the root guess and the cwd-encoding guess entirely.
47
+ *
48
+ * Returns null when nothing was ever recorded (an agent running without our
49
+ * plugin) or when the recorded transcript has since been removed, in which case
50
+ * the caller falls back to discovery.
51
+ */
52
+ export declare function recordedCandidate(cwd: string): Promise<{
53
+ sessionId: string;
54
+ mtimeMs: number;
55
+ } | null>;
56
+ /**
57
+ * One-line description of the transcript BASE dir and how many project dirs it
58
+ * holds. Used only when a resolve finds zero candidates, because it separates the
59
+ * two causes that look identical in the logs:
60
+ * • base absent / 0 project dirs → the bridge is looking at the WRONG config dir
61
+ * entirely (Claude Code's environment lives elsewhere and CLAUDE_CONFIG_DIR did
62
+ * not reach this process).
63
+ * • base holds N project dirs but none match → the CWD is the wrong one (or a
64
+ * representation this build cannot map — see {@link projectDirsFor}).
65
+ * Never throws.
66
+ */
67
+ export declare function transcriptBaseSummary(): Promise<string>;
2
68
  /**
3
69
  * List all Claude Code session candidates for a cwd as {sessionId, mtimeMs}.
4
- * Scans <claudeConfigDir()>/projects/<escapedCwd>/*.jsonl — honoring
5
- * CLAUDE_CONFIG_DIR (default ~/.claude). Returns [] on any error or an
6
- * empty/absent dir (the resolver treats [] as "no candidates"). Never throws —
7
- * Vault: Returning-null/Option error pattern (typescript-master-vault
8
- * concepts/Error_Handling). Stats run in parallel (Vault: Parallelism).
70
+ * Scans every {@link projectDirsFor} dir for *.jsonl — honoring CLAUDE_CONFIG_DIR
71
+ * (default ~/.claude). Returns [] on any error or an empty/absent dir (the
72
+ * resolver treats [] as "no candidates"). Never throws — Vault: Returning-null/
73
+ * Option error pattern (typescript-master-vault concepts/Error_Handling). Dirs
74
+ * and stats are probed in parallel (Vault: Parallelism); results are deduped by
75
+ * sessionId so two cwd forms resolving to one dir cannot inflate the count (a
76
+ * false ">1" would make the resolver call it "ambiguous" and refuse).
9
77
  */
10
78
  export declare function listCandidates(cwd: string): Promise<{
11
79
  sessionId: string;
@@ -20,6 +88,11 @@ export declare function detectCurrentSession(cwd: string): Promise<string | null
20
88
  /**
21
89
  * Check whether a Claude Code session file exists on disk.
22
90
  * Returns false if the file is missing (session ended or ID is wrong).
91
+ *
92
+ * Probes every {@link projectDirsFor} form — a pin validated under the canonical
93
+ * cwd must still validate when the agent registered a symlinked/trailing-slash
94
+ * representation of the same directory, or the resolver silently drops the pin
95
+ * and falls back to guessing by mtime.
23
96
  */
24
97
  export declare function validateSession(sessionId: string, cwd: string): Promise<boolean>;
25
98
  export declare function execClaude(sessionId: string, message: string, cwd: string, timeoutMs?: number): Promise<CliExecResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"cc-cli.d.ts","sourceRoot":"","sources":["../../src/services/cc-cli.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAK5C;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAenD;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAKxB;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,OAAO,CAAC,CAelB;AAED,wBAAgB,UAAU,CACxB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,CAAC,CAiLxB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,GACV;IAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAYpD"}
1
+ {"version":3,"file":"cc-cli.d.ts","sourceRoot":"","sources":["../../src/services/cc-cli.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAM5C;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAWnE;AAcD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAQ3D;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CASxD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,MAAM,CAAC,CAa7D;AAED;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAiCnD;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAKxB;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,OAAO,CAAC,CAkBlB;AAED,wBAAgB,UAAU,CACxB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,CAAC,CAiLxB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,GACV;IAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAYpD"}