zcode-acp-server 0.47.2 → 0.47.4

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
@@ -285,7 +285,7 @@ Thanks to everyone who has contributed (updated automatically from the
285
285
  <a href="https://github.com/william0wang/zcode-acp/graphs/contributors">
286
286
  <!-- release-please re-stamps &v= on every release: the new URL busts the
287
287
  contrib.rocks and GitHub camo image caches. -->
288
- <img src="https://contrib.rocks/image?repo=william0wang/zcode-acp&v=0.47.2" alt="Contributors" /> <!-- x-release-please-version -->
288
+ <img src="https://contrib.rocks/image?repo=william0wang/zcode-acp&v=0.47.4" alt="Contributors" /> <!-- x-release-please-version -->
289
289
  </a>
290
290
 
291
291
  ## Related Projects
@@ -1 +1 @@
1
- {"version":3,"file":"hub.d.ts","sourceRoot":"","sources":["../../src/bin/hub.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;;GAmBG;AAsCH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CA6B1C"}
1
+ {"version":3,"file":"hub.d.ts","sourceRoot":"","sources":["../../src/bin/hub.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;;GAmBG;AAuCH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAgC1C"}
package/dist/bin/hub.js CHANGED
@@ -22,6 +22,7 @@
22
22
  import { spawn } from "node:child_process";
23
23
  import process from "node:process";
24
24
  import { fileURLToPath } from "node:url";
25
+ import { installCrashGuards } from "../crash-guards.js";
25
26
  import { parseHubConfig } from "../remote/config.js";
26
27
  import { sandboxBorn, selfRelaunchOutsideSandbox } from "../remote/hub-sandbox.js";
27
28
  import { startHub } from "../remote/hub-server.js";
@@ -52,6 +53,9 @@ function respawnSelf() {
52
53
  process.exit(0);
53
54
  }
54
55
  export async function main() {
56
+ // Crash guards first — the hub is a long-lived daemon whose death takes
57
+ // every remote connection with it (see src/crash-guards.ts).
58
+ installCrashGuards();
55
59
  const config = parseHubConfig();
56
60
  if (!config)
57
61
  process.exit(1);
@@ -1 +1 @@
1
- {"version":3,"file":"hub.js","sourceRoot":"","sources":["../../src/bin/hub.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hub.js","sourceRoot":"","sources":["../../src/bin/hub.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  {
2
- "fingerprint": "1d4ccc69d49b6762a0c1720d44b342d3287ee9f722a25c86e4cc38145ee27bfd",
3
- "fileCount": 96
2
+ "fingerprint": "65780c0cc382502e72db0607aaaa1fd8545798f0254e1a16e950b88e2cea8308",
3
+ "fileCount": 97
4
4
  }
@@ -38,10 +38,12 @@ export declare function runAutoCompactDetached(server: ZcodeAcpServer, cx: acp.A
38
38
  export declare const AUTO_COMPACT_SETTLE_MS = 330000;
39
39
  /**
40
40
  * Bounded wait until no detached auto-compact is in flight for the session.
41
- * For flows with no user to resend (goal-loop rounds, sandbox continuations):
42
- * prompts are REJECTED during a compaction — their subscribed listener would
43
- * accumulate the compaction's internal-turn stream as residue — whereas a
44
- * caller that waits BEFORE subscribing is residue-free by construction.
41
+ * Callers MUST wait before subscribing their event listener: a subscribed
42
+ * listener would accumulate the compaction's internal-turn stream as residue
43
+ * and dispatch it as the waiting prompt's own output. Waiting before the
44
+ * subscribe is residue-free by construction, so the prompt path (user
45
+ * messages), the goal-loop driver, and sandbox continuations all use this same
46
+ * pre-subscribe hold.
45
47
  * Resolves false on timeout (the compaction may legitimately still run).
46
48
  */
47
49
  export declare function waitForAutoCompactIdle(server: ZcodeAcpServer, zcodeSid: string, timeoutMs?: number): Promise<boolean>;
@@ -1 +1 @@
1
- {"version":3,"file":"auto-compact.d.ts","sourceRoot":"","sources":["../../src/config/auto-compact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,KAAK,KAAK,GAAG,MAAM,0BAA0B,CAAC;AAIrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAGrD,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAEhC;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,cAAc,EACtB,EAAE,EAAE,GAAG,CAAC,YAAY,EACpB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CA8Df;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,cAAc,EACtB,EAAE,EAAE,GAAG,CAAC,YAAY,EACpB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,IAAI,CAQN;AAED,+EAA+E;AAC/E,eAAO,MAAM,sBAAsB,SAAU,CAAC;AAE9C;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,MAAM,EAChB,SAAS,SAAyB,GACjC,OAAO,CAAC,OAAO,CAAC,CAOlB"}
1
+ {"version":3,"file":"auto-compact.d.ts","sourceRoot":"","sources":["../../src/config/auto-compact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,KAAK,KAAK,GAAG,MAAM,0BAA0B,CAAC;AAIrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAGrD,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAEhC;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,cAAc,EACtB,EAAE,EAAE,GAAG,CAAC,YAAY,EACpB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAoFf;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,cAAc,EACtB,EAAE,EAAE,GAAG,CAAC,YAAY,EACpB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,IAAI,CAQN;AA6BD,+EAA+E;AAC/E,eAAO,MAAM,sBAAsB,SAAU,CAAC;AAE9C;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,MAAM,EAChB,SAAS,SAAyB,GACjC,OAAO,CAAC,OAAO,CAAC,CAOlB"}
@@ -34,6 +34,10 @@ export async function maybeAutoCompact(server, cx, acpSid, zcodeSid) {
34
34
  if (threshold <= 0)
35
35
  return; // disabled
36
36
  const msgId = randomUUID();
37
+ // Set only once this run actually reported running:true. The finally below
38
+ // settles the indicator, and an early return (threshold not met, session/read
39
+ // failed) must not emit a settle for an indicator it never raised.
40
+ let reportedBusy = false;
37
41
  try {
38
42
  // Read current context usage via session/read. messageLimit keeps the
39
43
  // backend from serializing the whole message array into a snapshot whose
@@ -54,6 +58,13 @@ export async function maybeAutoCompact(server, cx, acpSid, zcodeSid) {
54
58
  if (used < threshold)
55
59
  return;
56
60
  log(`auto-compact: contextUsed=${used} >= threshold=${threshold}, compacting…`);
61
+ // The session is BUSY from here: report it so clients show the spinner and
62
+ // a Cancel button, and so a prompt the user types during the window queues
63
+ // client-side instead of racing the compaction. The turn that armed us
64
+ // already reported running:false (detached design) — without this the whole
65
+ // compaction window reads as idle on every client.
66
+ await emitCompactTurnState(server, acpSid, true);
67
+ reportedBusy = true;
57
68
  const m = messages();
58
69
  await sendTextChunk(cx, acpSid, m.autoCompactStart(used.toLocaleString(), threshold.toLocaleString()), msgId);
59
70
  // compact() handles: session/compact → waitForTurnIdle → emitInitialUsage.
@@ -76,6 +87,18 @@ export async function maybeAutoCompact(server, cx, acpSid, zcodeSid) {
76
87
  await sendTextChunk(cx, acpSid, messages().autoCompactFailed(e instanceof Error ? e.message : String(e)), msgId);
77
88
  // Best-effort: never break the prompt response.
78
89
  }
90
+ finally {
91
+ // Settle only what this run raised: an early return (threshold not met,
92
+ // session/read failed) must not emit a settle for an indicator it never
93
+ // raised. The settle can land a few ms BEFORE a prompt held at the
94
+ // compaction gate registers — that turn's own running:true follows
95
+ // immediately and clients are last-write-wins, so the pair reads as one
96
+ // continuous busy window (verified: the gap measures ~17ms, well inside a
97
+ // single UI frame).
98
+ if (reportedBusy) {
99
+ await emitCompactTurnState(server, acpSid, false);
100
+ }
101
+ }
79
102
  }
80
103
  /**
81
104
  * Arm maybeAutoCompact as a session-level background task, single-flight per
@@ -94,14 +117,34 @@ export function runAutoCompactDetached(server, cx, acpSid, zcodeSid) {
94
117
  })
95
118
  .finally(() => server.autoCompactInFlight.delete(zcodeSid));
96
119
  }
120
+ /**
121
+ * Out-of-band running indicator for the compaction window, per attached alias
122
+ * (see session.ts's emitTurnState): the compaction owns the backend prompt lock
123
+ * for minutes, so the session IS busy — clients that only track turns would
124
+ * show idle, drop their spinner, and offer a plain Send button where a Cancel
125
+ * belongs. Best-effort: a dead client must never fail the compaction.
126
+ */
127
+ async function emitCompactTurnState(server, acpSid, running) {
128
+ const results = await Promise.allSettled(server.sessionAliases(acpSid).map((sid) => server.clients
129
+ .broadcast()
130
+ .notify("$/zcode/turnState", { sessionId: sid, running })
131
+ .catch(() => undefined)));
132
+ for (const r of results) {
133
+ if (r.status === "rejected") {
134
+ log(`auto-compact: turnState notify failed: ${String(r.reason)}`);
135
+ }
136
+ }
137
+ }
97
138
  /** Worst-case compaction wall time: settle cap 300s + startup + probe gaps. */
98
139
  export const AUTO_COMPACT_SETTLE_MS = 330_000;
99
140
  /**
100
141
  * Bounded wait until no detached auto-compact is in flight for the session.
101
- * For flows with no user to resend (goal-loop rounds, sandbox continuations):
102
- * prompts are REJECTED during a compaction — their subscribed listener would
103
- * accumulate the compaction's internal-turn stream as residue — whereas a
104
- * caller that waits BEFORE subscribing is residue-free by construction.
142
+ * Callers MUST wait before subscribing their event listener: a subscribed
143
+ * listener would accumulate the compaction's internal-turn stream as residue
144
+ * and dispatch it as the waiting prompt's own output. Waiting before the
145
+ * subscribe is residue-free by construction, so the prompt path (user
146
+ * messages), the goal-loop driver, and sandbox continuations all use this same
147
+ * pre-subscribe hold.
105
148
  * Resolves false on timeout (the compaction may legitimately still run).
106
149
  */
107
150
  export async function waitForAutoCompactIdle(server, zcodeSid, timeoutMs = AUTO_COMPACT_SETTLE_MS) {
@@ -1 +1 @@
1
- {"version":3,"file":"auto-compact.js","sourceRoot":"","sources":["../../src/config/auto-compact.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auto-compact.js","sourceRoot":"","sources":["../../src/config/auto-compact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Process-level crash guards + a diagnostic on-disk log for the bridge.
3
+ *
4
+ * The bridge is a LONG-LIVED process hosted inside an editor extension host,
5
+ * a martty TUI, or a hub incubation — when it dies, the whole window dies
6
+ * with it and its stderr vanishes with the terminal (observed 2026-09-23: a
7
+ * bun-hosted bridge died ~25ms after issuing session/create in a fresh
8
+ * workspace; the backend saw its stdin close, shut down, and martty exited —
9
+ * and NOTHING remained to say why the bridge died). Two layers fix both
10
+ * halves:
11
+ *
12
+ * 1. `unhandledRejection` / `uncaughtException` handlers that WARN instead of
13
+ * dying. Node ≥15 and Bun both crash the process on an unhandled rejection
14
+ * by default; the codebase's convention is already "best-effort in event
15
+ * handlers, failures are logged, never thrown into the event loop", but a
16
+ * single missed `.catch` anywhere still took the window down. Swallowing
17
+ * is the right trade for a stateless-per-request bridge: a dropped
18
+ * notification beats a dead session.
19
+ * 2. A daily diary at `~/.zcode/cli/log/zcode-acp-YYYY-MM-DD.log` (next to
20
+ * the backend's own logs) that every `warn()` appends to. The diary is
21
+ * what survives the window: the next crash leaves its reason on disk.
22
+ *
23
+ * EPIPE on stdout is the one deliberate exit: the ACP client is gone, so the
24
+ * process is an orphan holding a hub registration — record and exit cleanly.
25
+ */
26
+ /**
27
+ * Append one line to the daily diary. Best-effort by design: a read-only or
28
+ * unwritable HOME must never turn a warning into a crash (the append runs
29
+ * inside warn() on hot paths). First use creates the directory.
30
+ */
31
+ export declare function appendDiary(line: string): void;
32
+ /** Extract a printable reason (message + stack head) from anything thrown. */
33
+ export declare function describeError(reason: unknown): string;
34
+ /** Is this the "ACP client is gone" pipe break that should end the process? */
35
+ export declare function isStdoutPipeBreak(reason: unknown): boolean;
36
+ /**
37
+ * Install the process-wide guards. Idempotent. Call at the top of every
38
+ * long-lived entry point (the stdio bridge, the serve bridge, the hub) BEFORE
39
+ * any I/O — a rejection racing the install would still kill the process.
40
+ */
41
+ export declare function installCrashGuards(): void;
42
+ /** Test seam: allow re-installing into a fresh listener set. */
43
+ export declare function resetCrashGuardsForTest(): void;
44
+ //# sourceMappingURL=crash-guards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crash-guards.d.ts","sourceRoot":"","sources":["../src/crash-guards.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAgCH;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAS9C;AAED,8EAA8E;AAC9E,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAUrD;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAK1D;AAOD;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CA4BzC;AAED,gEAAgE;AAChE,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Process-level crash guards + a diagnostic on-disk log for the bridge.
3
+ *
4
+ * The bridge is a LONG-LIVED process hosted inside an editor extension host,
5
+ * a martty TUI, or a hub incubation — when it dies, the whole window dies
6
+ * with it and its stderr vanishes with the terminal (observed 2026-09-23: a
7
+ * bun-hosted bridge died ~25ms after issuing session/create in a fresh
8
+ * workspace; the backend saw its stdin close, shut down, and martty exited —
9
+ * and NOTHING remained to say why the bridge died). Two layers fix both
10
+ * halves:
11
+ *
12
+ * 1. `unhandledRejection` / `uncaughtException` handlers that WARN instead of
13
+ * dying. Node ≥15 and Bun both crash the process on an unhandled rejection
14
+ * by default; the codebase's convention is already "best-effort in event
15
+ * handlers, failures are logged, never thrown into the event loop", but a
16
+ * single missed `.catch` anywhere still took the window down. Swallowing
17
+ * is the right trade for a stateless-per-request bridge: a dropped
18
+ * notification beats a dead session.
19
+ * 2. A daily diary at `~/.zcode/cli/log/zcode-acp-YYYY-MM-DD.log` (next to
20
+ * the backend's own logs) that every `warn()` appends to. The diary is
21
+ * what survives the window: the next crash leaves its reason on disk.
22
+ *
23
+ * EPIPE on stdout is the one deliberate exit: the ACP client is gone, so the
24
+ * process is an orphan holding a hub registration — record and exit cleanly.
25
+ */
26
+ import { appendFileSync, mkdirSync } from "node:fs";
27
+ import path from "node:path";
28
+ import process from "node:process";
29
+ /**
30
+ * Root of the ZCode data dir (mirrors utils.zcodeHomeDir — duplicated here so
31
+ * utils can statically import the diary without an import cycle).
32
+ */
33
+ function zcodeHomeDir() {
34
+ const explicit = process.env.ZCODE_HOME;
35
+ if (explicit)
36
+ return explicit;
37
+ return path.join(process.env.HOME || process.env.USERPROFILE || "~", ".zcode");
38
+ }
39
+ /** Diary directory, per ZCODE_HOME. Created lazily on the first append. */
40
+ function diaryDir() {
41
+ return path.join(zcodeHomeDir(), "cli", "log");
42
+ }
43
+ /** Today's diary file name (UTC date, matching the backend's own naming). */
44
+ function diaryFile(now = new Date()) {
45
+ const day = now.toISOString().slice(0, 10);
46
+ return path.join(diaryDir(), `zcode-acp-${day}.log`);
47
+ }
48
+ /** Diary enabled? Tests run under a hermetic HOME; guard via env like TUI. */
49
+ function diaryEnabled() {
50
+ return !process.env.VITEST;
51
+ }
52
+ /**
53
+ * Append one line to the daily diary. Best-effort by design: a read-only or
54
+ * unwritable HOME must never turn a warning into a crash (the append runs
55
+ * inside warn() on hot paths). First use creates the directory.
56
+ */
57
+ export function appendDiary(line) {
58
+ if (!diaryEnabled())
59
+ return;
60
+ try {
61
+ const file = diaryFile();
62
+ mkdirSync(diaryDir(), { recursive: true });
63
+ appendFileSync(file, `${new Date().toISOString()} ${line}\n`, "utf8");
64
+ }
65
+ catch {
66
+ // Unwritable diary (permissions, sandbox) — stderr alone must still work.
67
+ }
68
+ }
69
+ /** Extract a printable reason (message + stack head) from anything thrown. */
70
+ export function describeError(reason) {
71
+ if (reason instanceof Error) {
72
+ const stack = (reason.stack ?? "").split("\n").slice(0, 4).join(" | ");
73
+ return `${reason.name}: ${reason.message}${stack ? ` @ ${stack}` : ""}`;
74
+ }
75
+ try {
76
+ return JSON.stringify(reason);
77
+ }
78
+ catch {
79
+ return String(reason);
80
+ }
81
+ }
82
+ /** Is this the "ACP client is gone" pipe break that should end the process? */
83
+ export function isStdoutPipeBreak(reason) {
84
+ const err = reason;
85
+ const code = err?.code;
86
+ if (code === "EPIPE")
87
+ return true;
88
+ return typeof err?.message === "string" && /\bEPIPE\b/i.test(err.message);
89
+ }
90
+ let installed = false;
91
+ /** Unhandled-rejection flood control: at most one stack per second, counted. */
92
+ let lastRejectLogAt = 0;
93
+ let suppressedRejects = 0;
94
+ /**
95
+ * Install the process-wide guards. Idempotent. Call at the top of every
96
+ * long-lived entry point (the stdio bridge, the serve bridge, the hub) BEFORE
97
+ * any I/O — a rejection racing the install would still kill the process.
98
+ */
99
+ export function installCrashGuards() {
100
+ if (installed)
101
+ return;
102
+ installed = true;
103
+ process.on("unhandledRejection", (reason) => {
104
+ const now = Date.now();
105
+ if (now - lastRejectLogAt < 1000) {
106
+ suppressedRejects++;
107
+ return;
108
+ }
109
+ const skipped = suppressedRejects;
110
+ suppressedRejects = 0;
111
+ lastRejectLogAt = now;
112
+ const line = `unhandled rejection (suppressed ${skipped} earlier): ` + describeError(reason);
113
+ appendDiary(line);
114
+ process.stderr.write(`[zcode-acp] ⚠ ${line}\n`);
115
+ });
116
+ process.on("uncaughtException", (err) => {
117
+ if (isStdoutPipeBreak(err)) {
118
+ // The ACP client is gone (window closed / TUI exited). Staying alive
119
+ // would just leak the process and its hub registration.
120
+ appendDiary(`exiting: stdout pipe closed (${describeError(err)})`);
121
+ process.exit(0);
122
+ }
123
+ appendDiary(`uncaught exception: ${describeError(err)}`);
124
+ process.stderr.write(`[zcode-acp] ⚠ uncaught exception: ${describeError(err)}\n`);
125
+ });
126
+ }
127
+ /** Test seam: allow re-installing into a fresh listener set. */
128
+ export function resetCrashGuardsForTest() {
129
+ installed = false;
130
+ }
131
+ //# sourceMappingURL=crash-guards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crash-guards.js","sourceRoot":"","sources":["../src/crash-guards.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/handlers/session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/handlers/session.ts"],"names":[],"mappings":"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"}
@@ -1497,6 +1497,11 @@ export async function runOneTurn(server, opts) {
1497
1497
  // this turn's listener unregister in the finally, and
1498
1498
  // turn.compactRejected lets the goal-loop driver (no user to resend)
1499
1499
  // wait the compaction out and retry the round.
1500
+ //
1501
+ // This is the RACE fallback, not the normal path: runPrompt holds a
1502
+ // prompt that meets a compaction already running, so reaching here
1503
+ // means the compaction armed between the hold and this send (or
1504
+ // outlived the hold's settle cap).
1500
1505
  if (isBusy && server.autoCompactInFlight.has(zcodeSid)) {
1501
1506
  // Goal rounds get no user-directed notice: the driver retries them
1502
1507
  // automatically — a "resend" instruction would point at an internal
@@ -1755,12 +1760,45 @@ async function runPrompt(server, params, cx, requestId, continuationRound = fals
1755
1760
  // same lock). Slash commands /auto pause|resume|stop|status were
1756
1761
  // intercepted above, so anything reaching here is conversational input.
1757
1762
  let parked;
1758
- // Set when the compaction gate below rejected this prompt.
1763
+ // Set when the compaction wait below outlived its settle cap: the prompt is
1764
+ // rejected rather than held forever (the bounded fallback path).
1759
1765
  let compactBusy = false;
1760
- // A sandbox continuation has no user watching to resend it: wait the
1761
- // compaction out instead of hitting the rejection gate. The wait happens
1762
- // BEFORE any subscribe, so it is residue-free by construction.
1766
+ // Compaction hold. A detached auto-compact holds the backend prompt lock for
1767
+ // minutes; queueing BEHIND the lock is fatal for a subscribed listener (the
1768
+ // compaction's internal-turn stream would be dispatched as THIS prompt's
1769
+ // output, its turn.completed ending the turn before the real reply starts).
1770
+ // So the wait happens HERE — before the turn registers, before the listener
1771
+ // subscribes — where it is residue-free by construction: the prompt then
1772
+ // proceeds through the normal send path, and the send-retry loop absorbs the
1773
+ // tail of the lock window if the compaction is still winding down. This is
1774
+ // the same pre-subscribe shape the goal-loop driver and the sandbox
1775
+ // continuations already use; a user-facing prompt now gets it too instead of
1776
+ // being rejected with "resend after the ✓ line" — the message the user typed
1777
+ // is delivered, the session keeps showing as executing, and there is nothing
1778
+ // to resend. Never wait while holding the preempt lock: a long wait would
1779
+ // block other sessions' register/preempt critical sections.
1780
+ if (server.autoCompactInFlight.has(zcodeSid)) {
1781
+ // Tell the user BEFORE the wait, not after: the wait can run for minutes,
1782
+ // and silence for that long is exactly what made the old rejection read as
1783
+ // "my message vanished". Announced here the client shows the hold notice
1784
+ // while the spinner stays live (the turn is not registered yet, so the
1785
+ // notice is the only feedback during the window).
1786
+ await sendTextChunk(cx, params.sessionId, messages().autoCompactHeld, randomUUID());
1787
+ const { waitForAutoCompactIdle } = await import("../config/auto-compact.js");
1788
+ const settled = await waitForAutoCompactIdle(server, zcodeSid);
1789
+ if (!settled) {
1790
+ // The compaction outlived AUTO_COMPACT_SETTLE_MS. Sending anyway would
1791
+ // hit the busy-reject inside runOneTurn and land in the same trap; reject
1792
+ // so the user can resend against a known-settled session.
1793
+ compactBusy = true;
1794
+ }
1795
+ else {
1796
+ log("session/prompt: held for a detached auto-compact, now sending");
1797
+ }
1798
+ }
1763
1799
  if (continuationRound && server.autoCompactInFlight.has(zcodeSid)) {
1800
+ // A second compaction armed while this continuation waited out the first:
1801
+ // wait again (still pre-subscribe, still residue-free).
1764
1802
  const { waitForAutoCompactIdle } = await import("../config/auto-compact.js");
1765
1803
  await waitForAutoCompactIdle(server, zcodeSid);
1766
1804
  }
@@ -1770,26 +1808,17 @@ async function runPrompt(server, params, cx, requestId, continuationRound = fals
1770
1808
  parked = goalLoop.parkPrompt(sendText);
1771
1809
  return;
1772
1810
  }
1773
- // Compaction gate: a detached auto-compact holds the backend prompt lock
1774
- // for minutes. NEVER queue behind it — this prompt's listener subscribes
1775
- // before the send, so waiting out the compaction would accumulate its
1776
- // whole internal-turn stream in our queue and dispatch it as THIS
1777
- // prompt's output once the lock releases (its turn.completed even ends
1778
- // the turn before the real reply starts). Reject with a resend notice;
1779
- // runOneTurn's busy-reject fallback covers the arm race between this
1780
- // check and the send.
1781
- if (server.autoCompactInFlight.has(zcodeSid)) {
1782
- compactBusy = true;
1783
- return;
1784
- }
1785
1811
  server.pendingTurns.set(requestId, turn);
1786
1812
  preempted = preemptInFlightTurn(server, zcodeSid, requestId);
1787
1813
  });
1788
1814
  if (parked)
1789
1815
  return parked;
1790
1816
  if (compactBusy) {
1817
+ // Only reachable when the compaction outlived AUTO_COMPACT_SETTLE_MS: the
1818
+ // hold above refused to wait indefinitely. The message was never queued, so
1819
+ // the user resends against a session the compaction has (by now) settled.
1791
1820
  await sendTextChunk(cx, params.sessionId, messages().autoCompactBusy, randomUUID());
1792
- log("session/prompt: rejected — a detached auto-compact is in flight");
1821
+ log("session/prompt: rejected — a detached auto-compact outlived its settle cap");
1793
1822
  return { stopReason: "max_turn_requests" };
1794
1823
  }
1795
1824
  // Discovery: the session is live the moment its turn STARTS — mark it active