@wjarka/cezarion 0.14.2-pr404.619 → 0.14.2-pr406.632

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
@@ -599,7 +599,7 @@ Useful environment variables:
599
599
  | `GITHUB_TOKEN` | Fallback for GitHub reads/PRs when `gh` isn't authenticated. |
600
600
  | `CEZ_ENV_PASSTHROUGH=A,B` | Forward these extra host env vars to spawned agents. By default agents get a least-privilege env (safe shell/toolchain vars + the backend's own auth + `GITHUB_TOKEN` + `CEZ_*`), not your full environment — use this to add a var an agent needs. |
601
601
  | `CEZ_AGENT_ENV_FULL=1` | Escape hatch: give spawned agents the full host environment (pre-hardening behavior). Off by default; only set it if you understand that this hands every host secret to the agent process. |
602
- | `CEZ_AGENT_TMPDIR=0` | Stop giving each task its own temp directory and hand agents the host `TMPDIR` again (pre-#785 behavior). On by default: every run gets `TMPDIR`/`TEMP`/`TMP` pointing at `.ai/cezar/tmp/<task-id>`, created and write-probed before the agent spawns and reaped when the run ends, so concurrent tasks stop sharing one directory and a task refuses to start rather than run against a temp directory that silently swallows its shell output (see Troubleshooting below). Only an exact `0` disables it, and it disables the whole thing — the pre-spawn check included, so this stays an escape hatch you can actually take. |
602
+ | `CEZ_AGENT_TMPDIR=0` | Stop giving each task its own temp directory and hand agents the host `TMPDIR` again (pre-#785 behavior). On by default: every run gets `TMPDIR`/`TEMP`/`TMP` pointing at `.ai/cezar/tmp/<task-id>`, created and write-probed before the agent spawns and reaped when the run ends — and kept short enough for unix-socket paths: a checkout so deep that `.ai/cezar/tmp/<task-id>` would cross the kernel's socket-path limit resolves it to a `cez-agent-…` directory under the system temp dir instead (#387). So concurrent tasks stop sharing one directory and a task refuses to start rather than run against a temp directory that silently swallows its shell output (see Troubleshooting below). Only an exact `0` disables it, and it disables the whole thing — the pre-spawn check included, so this stays an escape hatch you can actually take. |
603
603
  | `CEZ_REDACT_SECRETS=0` | Disable scrubbing of credential values/token shapes from the on-disk state (the NDJSON transcript and the free-text fields of `runs.json`). On by default; leave it on. Controller-generated delegation tokens are always scrubbed. Best-effort defense-in-depth, not a guarantee: it catches known token shapes and the values of your own secret-named env vars, so a credential in neither category can still get through. |
604
604
  | `CEZ_TITLE_UPDATES=0` | Turn off the live task-title refresh (namer re-runs on each turn end). The Settings → Agents toggle overrides this default. |
605
605
  | `CEZ_AUTONAME=0` | Disable ALL LLM task naming (creation + live) — titles stay heuristic (`437: /om-auto-review-pr`). Under `CEZ_DRY_RUN=1` naming is already off unless forced with `CEZ_AUTONAME=1`. |
@@ -636,6 +636,22 @@ per-task directory and pre-spawn check alike — and hands agents the host
636
636
  `TMPDIR` again, which is the way out if the check itself is wrong on your
637
637
  platform.
638
638
 
639
+ ### Troubleshooting: tools inside a task fail with a socket-path error
640
+
641
+ **Symptom.** Inside a task, `npm install`, `npm run typecheck`, or another tool
642
+ dies with `listen EINVAL` or a "socket path too long" / `ENAMETOOLONG` error —
643
+ with `TMPDIR=/tmp` set by hand, the same commands succeed. Tools like `tsx` bind
644
+ *named* unix sockets under `TMPDIR` (its IPC server builds
645
+ `<tmpdir>/tsx-<uid>/<pid>.pipe`), and the kernel caps a socket path at 104–108
646
+ bytes — a temp directory near that length leaves no room for the name.
647
+
648
+ **Fix.** Since #387 cezar keeps each task's temp directory at most 78 bytes. A
649
+ checkout deep enough to push `.ai/cezar/tmp/<task-id>` past that limit gets a
650
+ short `cez-agent-…` directory under the system temp directory instead — still
651
+ per-task, still write-probed before the agent spawns, still reaped when the run
652
+ ends. Checkouts whose path already fits keep the repo-local directory.
653
+ `CEZ_AGENT_TMPDIR=0` reverts the whole mechanism to the host `TMPDIR`.
654
+
639
655
  ---
640
656
 
641
657
  ## Coding agent backends
@@ -300,18 +300,6 @@ export declare function createDelegationRoutes(service: DelegationService, crede
300
300
  } & {
301
301
  "/:workerId": {
302
302
  $get: {
303
- output: {
304
- error: string;
305
- code?: "invalid_input" | undefined;
306
- };
307
- outputFormat: "json";
308
- status: 400;
309
- input: {
310
- param: {
311
- workerId: string;
312
- };
313
- };
314
- } | {
315
303
  output: {
316
304
  workerId: string;
317
305
  parentRunId: string;
@@ -388,11 +376,7 @@ export declare function createDelegationRoutes(service: DelegationService, crede
388
376
  workerId: string;
389
377
  };
390
378
  };
391
- };
392
- };
393
- } & {
394
- "/:workerId/collect": {
395
- $post: {
379
+ } | {
396
380
  output: {
397
381
  error: string;
398
382
  code?: "invalid_input" | undefined;
@@ -403,10 +387,12 @@ export declare function createDelegationRoutes(service: DelegationService, crede
403
387
  param: {
404
388
  workerId: string;
405
389
  };
406
- } & {
407
- json: Record<string, never>;
408
390
  };
409
- } | {
391
+ };
392
+ };
393
+ } & {
394
+ "/:workerId/collect": {
395
+ $post: {
410
396
  output: {
411
397
  workerId: string;
412
398
  parentRunId: string;
@@ -508,11 +494,7 @@ export declare function createDelegationRoutes(service: DelegationService, crede
508
494
  } & {
509
495
  json: Record<string, never>;
510
496
  };
511
- };
512
- };
513
- } & {
514
- "/:workerId/steer": {
515
- $post: {
497
+ } | {
516
498
  output: {
517
499
  error: string;
518
500
  code?: "invalid_input" | undefined;
@@ -524,11 +506,13 @@ export declare function createDelegationRoutes(service: DelegationService, crede
524
506
  workerId: string;
525
507
  };
526
508
  } & {
527
- json: {
528
- text: string;
529
- };
509
+ json: Record<string, never>;
530
510
  };
531
- } | {
511
+ };
512
+ };
513
+ } & {
514
+ "/:workerId/steer": {
515
+ $post: {
532
516
  output: {
533
517
  workerId: string;
534
518
  state: "delivered" | "queued";
@@ -544,11 +528,7 @@ export declare function createDelegationRoutes(service: DelegationService, crede
544
528
  text: string;
545
529
  };
546
530
  };
547
- };
548
- };
549
- } & {
550
- "/:workerId/stop": {
551
- $post: {
531
+ } | {
552
532
  output: {
553
533
  error: string;
554
534
  code?: "invalid_input" | undefined;
@@ -560,9 +540,15 @@ export declare function createDelegationRoutes(service: DelegationService, crede
560
540
  workerId: string;
561
541
  };
562
542
  } & {
563
- json: Record<string, never>;
543
+ json: {
544
+ text: string;
545
+ };
564
546
  };
565
- } | {
547
+ };
548
+ };
549
+ } & {
550
+ "/:workerId/stop": {
551
+ $post: {
566
552
  output: {
567
553
  workerId: string;
568
554
  state: "stopping" | "terminated";
@@ -576,11 +562,7 @@ export declare function createDelegationRoutes(service: DelegationService, crede
576
562
  } & {
577
563
  json: Record<string, never>;
578
564
  };
579
- };
580
- };
581
- } & {
582
- "/:workerId/destroy": {
583
- $post: {
565
+ } | {
584
566
  output: {
585
567
  error: string;
586
568
  code?: "invalid_input" | undefined;
@@ -594,7 +576,11 @@ export declare function createDelegationRoutes(service: DelegationService, crede
594
576
  } & {
595
577
  json: Record<string, never>;
596
578
  };
597
- } | {
579
+ };
580
+ };
581
+ } & {
582
+ "/:workerId/destroy": {
583
+ $post: {
598
584
  output: {
599
585
  workerId: string;
600
586
  state: "complete" | "incomplete";
@@ -617,6 +603,20 @@ export declare function createDelegationRoutes(service: DelegationService, crede
617
603
  } & {
618
604
  json: Record<string, never>;
619
605
  };
606
+ } | {
607
+ output: {
608
+ error: string;
609
+ code?: "invalid_input" | undefined;
610
+ };
611
+ outputFormat: "json";
612
+ status: 400;
613
+ input: {
614
+ param: {
615
+ workerId: string;
616
+ };
617
+ } & {
618
+ json: Record<string, never>;
619
+ };
620
620
  } | {
621
621
  output: {
622
622
  workerId: string;
@@ -646,11 +646,13 @@ export declare function createDelegationRoutes(service: DelegationService, crede
646
646
  "/:workerId/diff": {
647
647
  $get: {
648
648
  output: {
649
- error: string;
650
- code?: "invalid_input" | undefined;
649
+ workerId: string;
650
+ baselineSha: string;
651
+ diff: string;
652
+ truncated: boolean;
651
653
  };
652
654
  outputFormat: "json";
653
- status: 400;
655
+ status: 200;
654
656
  input: {
655
657
  param: {
656
658
  workerId: string;
@@ -658,13 +660,11 @@ export declare function createDelegationRoutes(service: DelegationService, crede
658
660
  };
659
661
  } | {
660
662
  output: {
661
- workerId: string;
662
- baselineSha: string;
663
- diff: string;
664
- truncated: boolean;
663
+ error: string;
664
+ code?: "invalid_input" | undefined;
665
665
  };
666
666
  outputFormat: "json";
667
- status: 200;
667
+ status: 400;
668
668
  input: {
669
669
  param: {
670
670
  workerId: string;
@@ -1,5 +1,25 @@
1
1
  /** Where a run's agent-scoped temp directory lives. */
2
2
  export declare function agentTmpDir(dataDir: string, runId: string): string;
3
+ /**
4
+ * The longest a per-run temp directory may be so that tools binding named
5
+ * unix sockets under it still work (#387), measured in UTF-8 bytes — the
6
+ * kernel bounds the encoded path, not the JavaScript character count.
7
+ * `sockaddr_un.sun_path` holds 108 bytes on Linux and 104 on macOS, NUL
8
+ * included; the longest name a known tool lays down under TMPDIR is tsx's IPC
9
+ * socket, `<tmpdir>/tsx-<uid>/<pid>.pipe`, ~22 bytes (Chrome's
10
+ * `SingletonSocket` is 16). A 78-byte ceiling leaves ≥25 bytes of headroom on
11
+ * the tighter platform — past anything these tools generate — while keeping
12
+ * ordinary checkouts on their repo-local scratch: only a genuinely deep path,
13
+ * like the 100-character directories #387 reports, moves to the fallback.
14
+ */
15
+ export declare const MAX_SOCKET_SAFE_DIR_LENGTH = 78;
16
+ /**
17
+ * The temp directory this run should use: the repo-local per-run directory
18
+ * when it is short enough for unix-socket paths, and a short directory under
19
+ * the OS temp root when it is not (#387). Pure resolution — nothing is
20
+ * created, nothing is probed; `agentTmpEnv` owns the side effects.
21
+ */
22
+ export declare function resolveAgentTmpDir(dataDir: string, runId: string): string;
3
23
  /**
4
24
  * The preflight's failure. Named so the spawn path can tell it apart from an
5
25
  * ordinary crash and turn it into the run's `error` — the same treatment
@@ -17,12 +37,19 @@ export declare function agentTmpDirEnabled(env?: NodeJS.ProcessEnv): boolean;
17
37
  * directory actually accepts writes. Throws `AgentTempDirError` when it does
18
38
  * not — callers turn that into the run's error rather than spawning.
19
39
  *
40
+ * The directory is `resolveAgentTmpDir`'s call: repo-local when that path is
41
+ * short enough for unix-socket paths, a digest-named directory under the OS
42
+ * temp root when the checkout is too deep for one (#387). In the shared OS
43
+ * root the directory is created private to this user (0700); repo-local
44
+ * scratch already sits inside the user's own tree and keeps the default mode
45
+ * it always had.
46
+ *
20
47
  * All three spellings are set, on every platform: a tool that reads `TMP` (or
21
48
  * `TEMP`) would otherwise keep following the host value straight back to the
22
49
  * exhausted directory this exists to escape.
23
50
  *
24
- * Returns `{}` under the opt-out, without probing anything: the hatch turns the
25
- * whole feature off, preflight included, so it stays an escape someone can
51
+ * Returns `{}` under the opt-out, without probing anything: the hatch turns
52
+ * the whole feature off, preflight included, so it stays an escape someone can
26
53
  * actually take.
27
54
  */
28
55
  export declare function agentTmpEnv(dataDir: string, runId: string, env?: NodeJS.ProcessEnv): Record<string, string>;
@@ -30,12 +57,25 @@ export declare function agentTmpEnv(dataDir: string, runId: string, env?: NodeJS
30
57
  * Reap one run's directory. Scratch, not an artifact: nothing reads it once the
31
58
  * agent is gone, and a Continue re-creates it through `agentTmpEnv`. Never
32
59
  * throws — reaping must not break a terminal transition.
60
+ *
61
+ * Both locations are tried because the resolution depends on the length of
62
+ * `dataDir`, which a Continue or a re-base can change between mint and reap;
63
+ * removing a name that was never minted is a no-op, so trying both is pure
64
+ * safety.
33
65
  */
34
66
  export declare function removeAgentTmpDir(dataDir: string, runId: string): void;
35
67
  /**
36
68
  * Remove every per-run directory that is not in `keepRunIds` — the startup
37
69
  * sweep, so a crash (which never reaches the terminal-transition reap) cannot
38
- * accumulate them forever. Confined to `<dataDir>/tmp`; sibling run state is
39
- * never enumerated, let alone touched. Returns the ids actually reaped.
70
+ * accumulate them forever. Two confined roots are swept and nothing else:
71
+ *
72
+ * - `<dataDir>/tmp`, where entries ARE the run ids (reports the ids reaped);
73
+ * - the OS temp root's `cez-agent-<12 hex>` directories (#387), where the
74
+ * name digests the dataDir and is not reversible to a run id (reports the
75
+ * directory names reaped). The pattern is exact — prefix, lowercase hex,
76
+ * fixed length, directories only — and a directory is removed only when
77
+ * its `.cez-owner` marker names THIS dataDir and none of this dataDir's
78
+ * kept runs claims it, so another project's scratch in the shared root is
79
+ * never touched.
40
80
  */
41
81
  export declare function sweepAgentTmpDirs(dataDir: string, keepRunIds: Iterable<string>): string[];
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Task-scoped temp directory for spawned agents (#785).
2
+ * Task-scoped temp directory for spawned agents (#785, length-capped by #387).
3
3
  *
4
4
  * Every agent used to inherit the host's `TMPDIR`/`TEMP`/`TMP` verbatim — they
5
5
  * ride in on `buildChildEnv`'s base allowlist — so every run on the machine
@@ -12,7 +12,7 @@
12
12
  * the agent reads back an empty result with a bogus exit status. Nothing in the
13
13
  * cockpit says anything is wrong.
14
14
  *
15
- * Two properties fix that, and this module owns both:
15
+ * Three properties fix that, and this module owns all of them:
16
16
  *
17
17
  * 1. **Isolation** — each run gets `<dataDir>/tmp/<runId>`, on the same disk
18
18
  * as the run's own state rather than a shared tmpfs, reaped when the run
@@ -21,15 +21,28 @@
21
21
  * 2. **Fail loud** — the directory is write-probed before the backend spawns.
22
22
  * A run that cannot get a working temp directory fails immediately with a
23
23
  * named, actionable error instead of spawning an agent that will run blind.
24
+ * 3. **Short enough to bind** (#387) — tools bind *named* unix sockets under
25
+ * `TMPDIR` (tsx's IPC server lays down `<tmpdir>/tsx-<uid>/<pid>.pipe`,
26
+ * Chrome a `SingletonSocket`), and the kernel caps a socket path at
27
+ * `sun_path` — 108 bytes on Linux, 104 on macOS, NUL included. A checkout
28
+ * deep enough (Cezar's own nested task worktrees land past 100 chars)
29
+ * pushed every such bind past the cap and broke `npm install` and
30
+ * typechecking inside the run. A directory that would land too deep
31
+ * resolves instead to a short digest-named directory under the OS temp
32
+ * root — still per-run, still probed, still reaped. A repo whose own path
33
+ * already fits keeps today's directory, byte for byte.
24
34
  *
25
- * `CEZ_AGENT_TMPDIR=0` opts out of BOTH — cezar keeps its hands off the temp
26
- * directory entirely and the pre-#785 behaviour is back, byte for byte. That is
27
- * deliberate: an escape hatch that still imposed the preflight would be a hatch
28
- * you cannot actually escape through, and this repo's graceful-degradation rule
29
- * says a new check must never become the only way to run.
35
+ * `CEZ_AGENT_TMPDIR=0` opts out of ALL THREE — cezar keeps its hands off the
36
+ * temp directory entirely and the pre-#785 behaviour is back, byte for byte.
37
+ * That is deliberate: an escape hatch that still imposed the preflight would be
38
+ * a hatch you cannot actually escape through, and this repo's
39
+ * graceful-degradation rule says a new check must never become the only way to
40
+ * run.
30
41
  */
31
- import { existsSync, mkdirSync, readdirSync, rmSync, writeFileSync } from 'node:fs';
32
- import { join } from 'node:path';
42
+ import { createHash } from 'node:crypto';
43
+ import { existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, rmSync, writeFileSync } from 'node:fs';
44
+ import { tmpdir } from 'node:os';
45
+ import { basename, join } from 'node:path';
33
46
  /** Run ids are uuids; anything else must never reach a recursive `rmSync`.
34
47
  *
35
48
  * `.` and `..` are excluded explicitly, not as pedantry: they match the
@@ -48,6 +61,70 @@ export function agentTmpDir(dataDir, runId) {
48
61
  function agentTmpRoot(dataDir) {
49
62
  return join(dataDir, 'tmp');
50
63
  }
64
+ /**
65
+ * The longest a per-run temp directory may be so that tools binding named
66
+ * unix sockets under it still work (#387), measured in UTF-8 bytes — the
67
+ * kernel bounds the encoded path, not the JavaScript character count.
68
+ * `sockaddr_un.sun_path` holds 108 bytes on Linux and 104 on macOS, NUL
69
+ * included; the longest name a known tool lays down under TMPDIR is tsx's IPC
70
+ * socket, `<tmpdir>/tsx-<uid>/<pid>.pipe`, ~22 bytes (Chrome's
71
+ * `SingletonSocket` is 16). A 78-byte ceiling leaves ≥25 bytes of headroom on
72
+ * the tighter platform — past anything these tools generate — while keeping
73
+ * ordinary checkouts on their repo-local scratch: only a genuinely deep path,
74
+ * like the 100-character directories #387 reports, moves to the fallback.
75
+ */
76
+ export const MAX_SOCKET_SAFE_DIR_LENGTH = 78;
77
+ /** The OS temp root, symlink-resolved: `bind(2)` bounds the path the kernel
78
+ * walks, so the check must measure what the path resolves to, not what it
79
+ * says (macOS hands out `/var/folders/...` through a `/private/var` symlink). */
80
+ function osTempRoot() {
81
+ try {
82
+ return realpathSync(tmpdir());
83
+ }
84
+ catch {
85
+ return tmpdir();
86
+ }
87
+ }
88
+ const FALLBACK_PREFIX = 'cez-agent-';
89
+ const FALLBACK_NAME_LENGTH = 12;
90
+ /** The marker file inside a fallback directory naming the dataDir that minted
91
+ * it. The directory name digests `dataDir:runId` and is not reversible, so
92
+ * without this marker a sweep could not tell its own stale directories from
93
+ * another project's live ones in the shared root — and would delete them. */
94
+ const OWNER_FILE = '.cez-owner';
95
+ function dataDirOwner(dataDir) {
96
+ return createHash('sha256').update(`cez-agent-owner:${dataDir}`).digest('hex').slice(0, 16);
97
+ }
98
+ /**
99
+ * Where the fallback lives for this dataDir+run pair. The name digests the
100
+ * dataDir in, because the OS temp root is SHARED: a name derived from the run
101
+ * id alone would let one repo's reap delete another repo's live scratch when
102
+ * two run ids happen to share their leading characters. The name alone cannot
103
+ * make the sweep safe — a digest is not reversible, so a sweep could not tell
104
+ * its own stale directories from another project's live ones — which is why
105
+ * every fallback directory also carries the `.cez-owner` marker.
106
+ */
107
+ function fallbackTmpDir(dataDir, runId) {
108
+ const digest = createHash('sha256').update(`${dataDir}:${runId}`).digest('hex');
109
+ return join(osTempRoot(), FALLBACK_PREFIX + digest.slice(0, FALLBACK_NAME_LENGTH));
110
+ }
111
+ /**
112
+ * The temp directory this run should use: the repo-local per-run directory
113
+ * when it is short enough for unix-socket paths, and a short directory under
114
+ * the OS temp root when it is not (#387). Pure resolution — nothing is
115
+ * created, nothing is probed; `agentTmpEnv` owns the side effects.
116
+ */
117
+ export function resolveAgentTmpDir(dataDir, runId) {
118
+ const local = agentTmpDir(dataDir, runId);
119
+ if (Buffer.byteLength(local, 'utf8') <= MAX_SOCKET_SAFE_DIR_LENGTH)
120
+ return local;
121
+ const fallback = fallbackTmpDir(dataDir, runId);
122
+ if (Buffer.byteLength(fallback, 'utf8') <= MAX_SOCKET_SAFE_DIR_LENGTH)
123
+ return fallback;
124
+ // No candidate fits (a pathological host TMPDIR over a pathological repo
125
+ // path together): keep whichever leaves socket names the most room.
126
+ return Buffer.byteLength(fallback) < Buffer.byteLength(local) ? fallback : local;
127
+ }
51
128
  /** `errno` → the phrasing a human recognises from their shell. */
52
129
  const REASONS = {
53
130
  EDQUOT: 'Disk quota exceeded',
@@ -110,20 +187,33 @@ function probeWritable(dir) {
110
187
  * directory actually accepts writes. Throws `AgentTempDirError` when it does
111
188
  * not — callers turn that into the run's error rather than spawning.
112
189
  *
190
+ * The directory is `resolveAgentTmpDir`'s call: repo-local when that path is
191
+ * short enough for unix-socket paths, a digest-named directory under the OS
192
+ * temp root when the checkout is too deep for one (#387). In the shared OS
193
+ * root the directory is created private to this user (0700); repo-local
194
+ * scratch already sits inside the user's own tree and keeps the default mode
195
+ * it always had.
196
+ *
113
197
  * All three spellings are set, on every platform: a tool that reads `TMP` (or
114
198
  * `TEMP`) would otherwise keep following the host value straight back to the
115
199
  * exhausted directory this exists to escape.
116
200
  *
117
- * Returns `{}` under the opt-out, without probing anything: the hatch turns the
118
- * whole feature off, preflight included, so it stays an escape someone can
201
+ * Returns `{}` under the opt-out, without probing anything: the hatch turns
202
+ * the whole feature off, preflight included, so it stays an escape someone can
119
203
  * actually take.
120
204
  */
121
205
  export function agentTmpEnv(dataDir, runId, env = process.env) {
122
206
  if (!agentTmpDirEnabled(env))
123
207
  return {};
124
- const dir = agentTmpDir(dataDir, runId);
208
+ const local = agentTmpDir(dataDir, runId);
209
+ const dir = resolveAgentTmpDir(dataDir, runId);
125
210
  try {
126
- mkdirSync(dir, { recursive: true });
211
+ mkdirSync(dir, dir === local ? { recursive: true } : { recursive: true, mode: 0o700 });
212
+ // In the shared OS root the directory carries its ownership marker, so a
213
+ // startup sweep from another project can tell it apart from stale
214
+ // scratch (the sweep skips anything whose marker is missing or foreign).
215
+ if (dir !== local)
216
+ writeFileSync(join(dir, OWNER_FILE), dataDirOwner(dataDir), 'utf8');
127
217
  }
128
218
  catch (err) {
129
219
  throw new AgentTempDirError(dir, err);
@@ -135,44 +225,99 @@ export function agentTmpEnv(dataDir, runId, env = process.env) {
135
225
  * Reap one run's directory. Scratch, not an artifact: nothing reads it once the
136
226
  * agent is gone, and a Continue re-creates it through `agentTmpEnv`. Never
137
227
  * throws — reaping must not break a terminal transition.
228
+ *
229
+ * Both locations are tried because the resolution depends on the length of
230
+ * `dataDir`, which a Continue or a re-base can change between mint and reap;
231
+ * removing a name that was never minted is a no-op, so trying both is pure
232
+ * safety.
138
233
  */
139
234
  export function removeAgentTmpDir(dataDir, runId) {
140
235
  if (!safeRunId(runId))
141
236
  return;
142
- try {
143
- rmSync(agentTmpDir(dataDir, runId), { recursive: true, force: true });
144
- }
145
- catch {
146
- // best-effort; the startup sweep picks up whatever survives.
237
+ for (const dir of [agentTmpDir(dataDir, runId), fallbackTmpDir(dataDir, runId)]) {
238
+ try {
239
+ rmSync(dir, { recursive: true, force: true });
240
+ }
241
+ catch {
242
+ // best-effort; the startup sweep picks up whatever survives.
243
+ }
147
244
  }
148
245
  }
149
246
  /**
150
247
  * Remove every per-run directory that is not in `keepRunIds` — the startup
151
248
  * sweep, so a crash (which never reaches the terminal-transition reap) cannot
152
- * accumulate them forever. Confined to `<dataDir>/tmp`; sibling run state is
153
- * never enumerated, let alone touched. Returns the ids actually reaped.
249
+ * accumulate them forever. Two confined roots are swept and nothing else:
250
+ *
251
+ * - `<dataDir>/tmp`, where entries ARE the run ids (reports the ids reaped);
252
+ * - the OS temp root's `cez-agent-<12 hex>` directories (#387), where the
253
+ * name digests the dataDir and is not reversible to a run id (reports the
254
+ * directory names reaped). The pattern is exact — prefix, lowercase hex,
255
+ * fixed length, directories only — and a directory is removed only when
256
+ * its `.cez-owner` marker names THIS dataDir and none of this dataDir's
257
+ * kept runs claims it, so another project's scratch in the shared root is
258
+ * never touched.
154
259
  */
155
260
  export function sweepAgentTmpDirs(dataDir, keepRunIds) {
156
- const root = agentTmpRoot(dataDir);
157
- if (!existsSync(root))
158
- return [];
159
261
  const keep = new Set(keepRunIds);
160
262
  const reaped = [];
161
263
  let entries;
264
+ const root = agentTmpRoot(dataDir);
265
+ if (existsSync(root)) {
266
+ try {
267
+ entries = readdirSync(root, { withFileTypes: true })
268
+ .filter((e) => e.isDirectory())
269
+ .map((e) => e.name);
270
+ }
271
+ catch {
272
+ entries = [];
273
+ }
274
+ for (const name of entries) {
275
+ if (keep.has(name) || !safeRunId(name))
276
+ continue;
277
+ try {
278
+ rmSync(join(root, name), { recursive: true, force: true });
279
+ reaped.push(name);
280
+ }
281
+ catch {
282
+ // best-effort: a locked directory is retried on the next boot.
283
+ }
284
+ }
285
+ }
286
+ // The #387 fallback location, in the shared OS temp root. Kept narrow on
287
+ // purpose: exact prefix, 12 lowercase-hex name, directories only, and
288
+ // ownership — a directory is removed only when its `.cez-owner` marker
289
+ // names THIS dataDir (a marker that is missing or foreign is another
290
+ // project's, or unknown, and is never ours to remove) and none of this
291
+ // dataDir's kept runs claims it.
292
+ const owner = dataDirOwner(dataDir);
293
+ const claimed = new Set([...keep].filter(safeRunId).map((id) => basename(fallbackTmpDir(dataDir, id))));
294
+ const osRoot = osTempRoot();
295
+ let fallbackEntries;
162
296
  try {
163
- entries = readdirSync(root, { withFileTypes: true })
164
- .filter((e) => e.isDirectory())
165
- .map((e) => e.name);
297
+ fallbackEntries = readdirSync(osRoot, { withFileTypes: true });
166
298
  }
167
299
  catch {
168
- return [];
300
+ return reaped;
169
301
  }
170
- for (const name of entries) {
171
- if (keep.has(name) || !safeRunId(name))
302
+ for (const entry of fallbackEntries) {
303
+ if (!entry.isDirectory() || !entry.name.startsWith(FALLBACK_PREFIX))
304
+ continue;
305
+ if (!/^[0-9a-f]{12}$/.test(entry.name.slice(FALLBACK_PREFIX.length)))
306
+ continue;
307
+ let entryOwner;
308
+ try {
309
+ entryOwner = readFileSync(join(osRoot, entry.name, OWNER_FILE), 'utf8').trim();
310
+ }
311
+ catch {
312
+ continue; // no readable marker: unknown ownership is never ours to remove.
313
+ }
314
+ if (entryOwner !== owner)
315
+ continue;
316
+ if (claimed.has(entry.name))
172
317
  continue;
173
318
  try {
174
- rmSync(join(root, name), { recursive: true, force: true });
175
- reaped.push(name);
319
+ rmSync(join(osRoot, entry.name), { recursive: true, force: true });
320
+ reaped.push(entry.name);
176
321
  }
177
322
  catch {
178
323
  // best-effort: a locked directory is retried on the next boot.
@@ -1 +1 @@
1
- {"version":3,"file":"agent-tmpdir.js","sourceRoot":"","sources":["../../src/runs/agent-tmpdir.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-tmpdir.js","sourceRoot":"","sources":["../../src/runs/agent-tmpdir.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wjarka/cezarion",
3
- "version": "0.14.2-pr404.619",
3
+ "version": "0.14.2-pr406.632",
4
4
  "description": "Local cockpit for running and tracking AI agent tasks in your repo. Uses your logged-in `claude` CLI and `gh` — zero config, zero database.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -50,8 +50,8 @@
50
50
  "zod": "^4.4.3"
51
51
  },
52
52
  "devDependencies": {
53
- "@open-mercato/cezar-api-client": "0.14.2-pr404.619",
54
- "@open-mercato/cezar-contract": "0.14.2-pr404.619",
53
+ "@open-mercato/cezar-api-client": "0.14.2-pr406.632",
54
+ "@open-mercato/cezar-contract": "0.14.2-pr406.632",
55
55
  "@types/node": "^20.14.0",
56
56
  "@types/ws": "^8.18.1",
57
57
  "esbuild": "^0.28.1",