switchroom 0.19.38 → 0.19.39

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.
@@ -21311,7 +21311,7 @@ function allocateAgentUid(name) {
21311
21311
  }
21312
21312
 
21313
21313
  // src/build-info.ts
21314
- var VERSION = "0.19.38";
21314
+ var VERSION = "0.19.39";
21315
21315
 
21316
21316
  // src/setup/hindsight-recall-tunables.ts
21317
21317
  var RECALL_DEADLINE_HEADROOM_SECONDS = 2;
@@ -21440,8 +21440,8 @@ var HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION = 16 * 1024;
21440
21440
  var HINDSIGHT_PG_APP_ANON_MIB = 2560;
21441
21441
  var HINDSIGHT_PG_PAGE_CACHE_FLOOR_MIB = 2048;
21442
21442
  var HINDSIGHT_PG_SHARED_BUFFERS_BUDGET_MIB = HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION - HINDSIGHT_PG_APP_ANON_MIB - HINDSIGHT_PG_PAGE_CACHE_FLOOR_MIB;
21443
- var HINDSIGHT_PG_DEFAULT_SHARED_BUFFERS_MIB = 3072;
21444
- var HINDSIGHT_PG_DEFAULT_EFFECTIVE_CACHE_SIZE_MIB = 7168;
21443
+ var HINDSIGHT_PG_DEFAULT_SHARED_BUFFERS_MIB = 6144;
21444
+ var HINDSIGHT_PG_DEFAULT_EFFECTIVE_CACHE_SIZE_MIB = 12288;
21445
21445
  function pgMib(mib) {
21446
21446
  return `${mib}MB`;
21447
21447
  }
@@ -21485,7 +21485,7 @@ var HINDSIGHT_DEFAULT_RERANKER_MAX_CANDIDATES = 150;
21485
21485
  var HINDSIGHT_DEFAULT_RERANKER_LOCAL_MAX_CONCURRENT = 4;
21486
21486
  var HINDSIGHT_DEFAULT_RECALL_MAX_CONCURRENT = 8;
21487
21487
  var HINDSIGHT_DEFAULT_REFLECT_WALL_TIMEOUT_S = 600;
21488
- var HINDSIGHT_DEFAULT_CONSOLIDATION_MAX_MEMORIES_PER_ROUND = 500;
21488
+ var HINDSIGHT_DEFAULT_CONSOLIDATION_MAX_MEMORIES_PER_ROUND = 250;
21489
21489
  var HINDSIGHT_DEFAULT_CONSOLIDATION_SLOT_LIMIT = 6;
21490
21490
  var HINDSIGHT_DEFAULT_CONSOLIDATION_MAX_SLOTS = 1;
21491
21491
  var HINDSIGHT_DEFAULT_RECENCY_DECAY_FUNCTION = "exponential";
@@ -19337,8 +19337,8 @@ var HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION = 16 * 1024;
19337
19337
  var HINDSIGHT_PG_APP_ANON_MIB = 2560;
19338
19338
  var HINDSIGHT_PG_PAGE_CACHE_FLOOR_MIB = 2048;
19339
19339
  var HINDSIGHT_PG_SHARED_BUFFERS_BUDGET_MIB = HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION - HINDSIGHT_PG_APP_ANON_MIB - HINDSIGHT_PG_PAGE_CACHE_FLOOR_MIB;
19340
- var HINDSIGHT_PG_DEFAULT_SHARED_BUFFERS_MIB = 3072;
19341
- var HINDSIGHT_PG_DEFAULT_EFFECTIVE_CACHE_SIZE_MIB = 7168;
19340
+ var HINDSIGHT_PG_DEFAULT_SHARED_BUFFERS_MIB = 6144;
19341
+ var HINDSIGHT_PG_DEFAULT_EFFECTIVE_CACHE_SIZE_MIB = 12288;
19342
19342
  function pgMib(mib) {
19343
19343
  return `${mib}MB`;
19344
19344
  }
@@ -19382,7 +19382,7 @@ var HINDSIGHT_DEFAULT_RERANKER_MAX_CANDIDATES = 150;
19382
19382
  var HINDSIGHT_DEFAULT_RERANKER_LOCAL_MAX_CONCURRENT = 4;
19383
19383
  var HINDSIGHT_DEFAULT_RECALL_MAX_CONCURRENT = 8;
19384
19384
  var HINDSIGHT_DEFAULT_REFLECT_WALL_TIMEOUT_S = 600;
19385
- var HINDSIGHT_DEFAULT_CONSOLIDATION_MAX_MEMORIES_PER_ROUND = 500;
19385
+ var HINDSIGHT_DEFAULT_CONSOLIDATION_MAX_MEMORIES_PER_ROUND = 250;
19386
19386
  var HINDSIGHT_DEFAULT_CONSOLIDATION_SLOT_LIMIT = 6;
19387
19387
  var HINDSIGHT_DEFAULT_CONSOLIDATION_MAX_SLOTS = 1;
19388
19388
  var HINDSIGHT_DEFAULT_RECENCY_DECAY_FUNCTION = "exponential";
@@ -19750,8 +19750,8 @@ var HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION = 16 * 1024;
19750
19750
  var HINDSIGHT_PG_APP_ANON_MIB = 2560;
19751
19751
  var HINDSIGHT_PG_PAGE_CACHE_FLOOR_MIB = 2048;
19752
19752
  var HINDSIGHT_PG_SHARED_BUFFERS_BUDGET_MIB = HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION - HINDSIGHT_PG_APP_ANON_MIB - HINDSIGHT_PG_PAGE_CACHE_FLOOR_MIB;
19753
- var HINDSIGHT_PG_DEFAULT_SHARED_BUFFERS_MIB = 3072;
19754
- var HINDSIGHT_PG_DEFAULT_EFFECTIVE_CACHE_SIZE_MIB = 7168;
19753
+ var HINDSIGHT_PG_DEFAULT_SHARED_BUFFERS_MIB = 6144;
19754
+ var HINDSIGHT_PG_DEFAULT_EFFECTIVE_CACHE_SIZE_MIB = 12288;
19755
19755
  function pgMib(mib) {
19756
19756
  return `${mib}MB`;
19757
19757
  }
@@ -19795,7 +19795,7 @@ var HINDSIGHT_DEFAULT_RERANKER_MAX_CANDIDATES = 150;
19795
19795
  var HINDSIGHT_DEFAULT_RERANKER_LOCAL_MAX_CONCURRENT = 4;
19796
19796
  var HINDSIGHT_DEFAULT_RECALL_MAX_CONCURRENT = 8;
19797
19797
  var HINDSIGHT_DEFAULT_REFLECT_WALL_TIMEOUT_S = 600;
19798
- var HINDSIGHT_DEFAULT_CONSOLIDATION_MAX_MEMORIES_PER_ROUND = 500;
19798
+ var HINDSIGHT_DEFAULT_CONSOLIDATION_MAX_MEMORIES_PER_ROUND = 250;
19799
19799
  var HINDSIGHT_DEFAULT_CONSOLIDATION_SLOT_LIMIT = 6;
19800
19800
  var HINDSIGHT_DEFAULT_CONSOLIDATION_MAX_SLOTS = 1;
19801
19801
  var HINDSIGHT_DEFAULT_RECENCY_DECAY_FUNCTION = "exponential";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "switchroom",
3
3
  "//version": "NOT the release version — source of truth is the git tag, resolved by scripts/build.mjs:resolveVersion() (see CLAUDE.md > Standard release process). This field is stale by design and only the Layer-4 dev/non-tag fallback for build.mjs + src/cli/resolve-version.ts; do NOT bump it expecting a release to pick it up. npm-pack tarball naming needs a real version — do that as an UNCOMMITTED pack-time bump (see release step 6), never a committed one.",
4
- "version": "0.19.38",
4
+ "version": "0.19.39",
5
5
  "description": "Run Claude Code 24/7 on your Claude Pro/Max subscription over Telegram. Open-source alternative to OpenClaw and NanoClaw — no API keys.",
6
6
  "type": "module",
7
7
  "bin": {
@@ -47609,6 +47609,23 @@ function computeLabel(toolName, input) {
47609
47609
  }
47610
47610
  return "Working\u2026";
47611
47611
  }
47612
+ function isSubagentToolCall(event) {
47613
+ if (!event || typeof event !== "object")
47614
+ return false;
47615
+ const at = event.agent_type;
47616
+ if (typeof at === "string" && at.length > 0)
47617
+ return at !== "main";
47618
+ const aid = event.agent_id;
47619
+ const sid = event.session_id;
47620
+ return typeof aid === "string" && aid.length > 0 && typeof sid === "string" && sid.length > 0 && aid !== sid;
47621
+ }
47622
+ function hasAttributionSignal(event) {
47623
+ if (!event || typeof event !== "object")
47624
+ return false;
47625
+ const at = event.agent_type;
47626
+ const aid = event.agent_id;
47627
+ return typeof at === "string" && at.length > 0 || typeof aid === "string" && aid.length > 0;
47628
+ }
47612
47629
  function main() {
47613
47630
  const raw = readStdin().trim();
47614
47631
  if (!raw)
@@ -47627,6 +47644,14 @@ function main() {
47627
47644
  const toolName = event.tool_name;
47628
47645
  if (!sessionId || !toolUseId || !toolName)
47629
47646
  process.exit(0);
47647
+ if (!hasAttributionSignal(event)) {
47648
+ try {
47649
+ process.stderr.write(`[tool-label-pretool] WARNING: PreToolUse payload carries neither ` + `agent_type nor agent_id \u2014 the sidechain-attribution invariant may be ` + `broken by a Claude Code schema change; sub-agent labels may be ` + `mis-attributed to the parent session (tool_use_id=${toolUseId}).
47650
+ `);
47651
+ } catch {}
47652
+ }
47653
+ if (isSubagentToolCall(event))
47654
+ process.exit(0);
47630
47655
  let label;
47631
47656
  try {
47632
47657
  label = computeLabel(toolName, event.tool_input);
@@ -53507,6 +53532,13 @@ function createHandbackPreturnSignal(deps) {
53507
53532
  dropEntry(entry);
53508
53533
  return adoption;
53509
53534
  },
53535
+ hasPendingForTurnId(turnId) {
53536
+ for (const e of byKey.values()) {
53537
+ if (e.adoptTurnId === turnId && !e.consumed)
53538
+ return true;
53539
+ }
53540
+ return false;
53541
+ },
53510
53542
  isPreTurnRecord(turnKey2) {
53511
53543
  return turnKey2.startsWith(PRETURN_TURNKEY_PREFIX);
53512
53544
  },
@@ -80104,23 +80136,35 @@ function decideFallbackTeardownNotice2(input) {
80104
80136
  // gateway/stream-render.ts
80105
80137
  var PARKED_TURN_START_MAX = 16;
80106
80138
  var PARKED_TURN_START_TTL_MS = 30 * 60000;
80139
+ var QUEUED_CARD_ENABLED = process.env.SWITCHROOM_QUEUED_CARD !== "0";
80140
+ var QUEUED_CARD_HTML = "\u23f3 Queued \u2014 waiting for the current task to finish\u2026";
80141
+ var QUEUED_CARD_FOLDED_HTML = "\u2705 Folded into the current task.";
80142
+ var QUEUED_CARD_EXPIRED_HTML = "\u26a0\ufe0f This queued message timed out before it could start.";
80107
80143
  var parkedTurnStarts = [];
80108
- function pruneParkedTurnStarts(now) {
80144
+ function pruneParkedTurnStarts(now, onDrop) {
80109
80145
  for (let i = parkedTurnStarts.length - 1;i >= 0; i--) {
80110
80146
  if (now - parkedTurnStarts[i].parkedAt > PARKED_TURN_START_TTL_MS) {
80111
80147
  const [dropped] = parkedTurnStarts.splice(i, 1);
80112
80148
  process.stderr.write(`telegram gateway: parked-turn-start expired chat=${dropped.chatId ?? "-"} ` + `msg=${dropped.messageId ?? "-"} age_ms=${now - dropped.parkedAt}
80113
80149
  `);
80150
+ try {
80151
+ onDrop?.(dropped);
80152
+ } catch {}
80114
80153
  }
80115
80154
  }
80116
80155
  }
80117
- function parkTurnStart(env, now) {
80118
- parkedTurnStarts.push({ ...env, parkedAt: now });
80156
+ function parkTurnStart(env, now, onEvict) {
80157
+ const entry = { ...env, parkedAt: now };
80158
+ parkedTurnStarts.push(entry);
80119
80159
  while (parkedTurnStarts.length > PARKED_TURN_START_MAX) {
80120
80160
  const [dropped] = parkedTurnStarts.splice(0, 1);
80121
80161
  process.stderr.write(`telegram gateway: parked-turn-start evicted (cap ${PARKED_TURN_START_MAX}) ` + `chat=${dropped.chatId ?? "-"} msg=${dropped.messageId ?? "-"}
80122
80162
  `);
80163
+ try {
80164
+ onEvict?.(dropped);
80165
+ } catch {}
80123
80166
  }
80167
+ return entry;
80124
80168
  }
80125
80169
  function takeParkedTurnStart() {
80126
80170
  return parkedTurnStarts.pop() ?? null;
@@ -80128,11 +80172,56 @@ function takeParkedTurnStart() {
80128
80172
  function discardParkedTurnStart(rawContent) {
80129
80173
  for (let i = parkedTurnStarts.length - 1;i >= 0; i--) {
80130
80174
  if (parkedTurnStarts[i].rawContent === rawContent) {
80131
- parkedTurnStarts.splice(i, 1);
80132
- return true;
80175
+ const [dropped] = parkedTurnStarts.splice(i, 1);
80176
+ return dropped;
80133
80177
  }
80134
80178
  }
80135
- return false;
80179
+ return null;
80180
+ }
80181
+ async function openQueuedCard(deps, chatId, threadId, replyToMessageId) {
80182
+ try {
80183
+ const sent = await deps.robustApiCall(() => deps.bot.api.sendRichMessage(chatId, richMessage(QUEUED_CARD_HTML), {
80184
+ ...threadId != null ? { message_thread_id: threadId } : {},
80185
+ ...replyToMessageId != null ? { reply_parameters: { message_id: replyToMessageId, allow_sending_without_reply: true } } : {},
80186
+ disable_notification: true
80187
+ }), {
80188
+ chat_id: chatId,
80189
+ ...threadId != null ? { threadId } : {},
80190
+ verb: "queued-card.send"
80191
+ });
80192
+ return sent?.message_id ?? null;
80193
+ } catch (err) {
80194
+ process.stderr.write(`telegram gateway: queued card send failed: ${err.message}
80195
+ `);
80196
+ return null;
80197
+ }
80198
+ }
80199
+ function finalizeQueuedCard(deps, chatId, threadId, messageId, html) {
80200
+ deps.robustApiCall(() => deps.bot.api.editMessageText(chatId, messageId, richMessage(html), {}), {
80201
+ chat_id: chatId,
80202
+ ...threadId != null ? { threadId } : {},
80203
+ verb: "queued-card.finalize"
80204
+ }).catch(() => {
80205
+ return;
80206
+ });
80207
+ }
80208
+ function deleteQueuedCard(deps, chatId, messageId) {
80209
+ deps.robustApiCall(() => deps.bot.api.deleteMessage(chatId, messageId), { chat_id: chatId, verb: "queued-card.delete-orphan" }).catch(() => {
80210
+ return;
80211
+ });
80212
+ }
80213
+ function envThreadIdNum(threadId) {
80214
+ if (threadId == null)
80215
+ return null;
80216
+ const n = Number(threadId);
80217
+ return Number.isFinite(n) ? n : null;
80218
+ }
80219
+ function finalizeParkedEntryCard(deps, entry, html) {
80220
+ if (!QUEUED_CARD_ENABLED)
80221
+ return;
80222
+ if (entry.queuedCardMessageId == null || entry.chatId == null)
80223
+ return;
80224
+ finalizeQueuedCard(deps, entry.chatId, envThreadIdNum(entry.threadId), entry.queuedCardMessageId, html);
80136
80225
  }
80137
80226
  function beginTurn(deps, ev) {
80138
80227
  const {
@@ -80246,6 +80335,16 @@ function beginTurn(deps, ev) {
80246
80335
  `);
80247
80336
  }
80248
80337
  }
80338
+ if (QUEUED_CARD_ENABLED && ev.queuedCardMessageId != null && next.activityMessageId == null) {
80339
+ next.activityMessageId = ev.queuedCardMessageId;
80340
+ next.activityEverOpened = true;
80341
+ process.stderr.write(`telegram gateway: queued card adopted turnId=${turnId} card=${ev.queuedCardMessageId}
80342
+ `);
80343
+ } else if (QUEUED_CARD_ENABLED && ev.queuedCardMessageId != null && ev.chatId != null && next.activityMessageId != null && next.activityMessageId !== ev.queuedCardMessageId) {
80344
+ deleteQueuedCard(deps, ev.chatId, ev.queuedCardMessageId);
80345
+ process.stderr.write(`telegram gateway: queued card superseded by handback adoption turnId=${turnId} ` + `queued=${ev.queuedCardMessageId} adopted=${next.activityMessageId}
80346
+ `);
80347
+ }
80249
80348
  startTurnTypingLoop(ev.chatId, enqThreadIdNum ?? null);
80250
80349
  setCurrentTurn(next, statusKey(ev.chatId, enqThreadIdNum));
80251
80350
  scheduleEarlyLivenessOpen(next);
@@ -80394,7 +80493,7 @@ function handleSessionEvent(deps, ev) {
80394
80493
  ackDelivery(deliveryQueue, chatKey(ev.chatId, ev.threadId != null ? Number(ev.threadId) : null), ev.messageId, ev.rawContent);
80395
80494
  }
80396
80495
  }
80397
- pruneParkedTurnStarts(now);
80496
+ pruneParkedTurnStarts(now, (e) => finalizeParkedEntryCard(deps, e, QUEUED_CARD_EXPIRED_HTML));
80398
80497
  if (!ev.chatId) {
80399
80498
  beginTurn(deps, ev);
80400
80499
  return;
@@ -80405,18 +80504,38 @@ function handleSessionEvent(deps, ev) {
80405
80504
  beginTurn(deps, ev);
80406
80505
  return;
80407
80506
  }
80408
- parkTurnStart({
80507
+ const parkedEntry = parkTurnStart({
80409
80508
  chatId: ev.chatId,
80410
80509
  messageId: ev.messageId,
80411
80510
  threadId: ev.threadId,
80412
80511
  rawContent: ev.rawContent
80413
- }, now);
80512
+ }, now, (evicted) => finalizeParkedEntryCard(deps, evicted, QUEUED_CARD_EXPIRED_HTML));
80414
80513
  process.stderr.write(`telegram gateway: turn-start parked (session busy) chat=${ev.chatId} ` + `thread=${enqThreadIdNum ?? "-"} msg=${ev.messageId ?? "-"} ` + `parked=${parkedTurnStarts.length}
80415
80514
  `);
80515
+ const parkTurnId = deriveTurnId(ev.chatId, enqThreadIdNum ?? null, ev.messageId);
80516
+ const handbackOwnsSurface = HANDBACK_PRETURN_ENABLED && parkTurnId != null && handbackPreturnSignal.hasPendingForTurnId(parkTurnId);
80517
+ if (handbackOwnsSurface) {
80518
+ process.stderr.write(`telegram gateway: queued card suppressed (handback owns surface) ` + `turnId=${parkTurnId} msg=${ev.messageId ?? "-"}
80519
+ `);
80520
+ }
80521
+ if (QUEUED_CARD_ENABLED && !handbackOwnsSurface) {
80522
+ const cardChatId = ev.chatId;
80523
+ const replyToRaw = ev.messageId != null ? Number(ev.messageId) : null;
80524
+ const replyTo = replyToRaw != null && Number.isFinite(replyToRaw) ? replyToRaw : null;
80525
+ openQueuedCard(deps, cardChatId, enqThreadIdNum ?? null, replyTo).then((cardId) => {
80526
+ if (cardId == null)
80527
+ return;
80528
+ if (parkedTurnStarts.includes(parkedEntry)) {
80529
+ parkedEntry.queuedCardMessageId = cardId;
80530
+ } else {
80531
+ deleteQueuedCard(deps, cardChatId, cardId);
80532
+ }
80533
+ });
80534
+ }
80416
80535
  return;
80417
80536
  }
80418
80537
  case "dequeue": {
80419
- pruneParkedTurnStarts(Date.now());
80538
+ pruneParkedTurnStarts(Date.now(), (e) => finalizeParkedEntryCard(deps, e, QUEUED_CARD_EXPIRED_HTML));
80420
80539
  const parked = takeParkedTurnStart();
80421
80540
  if (parked == null)
80422
80541
  return;
@@ -80424,8 +80543,10 @@ function handleSessionEvent(deps, ev) {
80424
80543
  return;
80425
80544
  }
80426
80545
  case "queue_remove": {
80427
- pruneParkedTurnStarts(Date.now());
80428
- discardParkedTurnStart(ev.rawContent);
80546
+ pruneParkedTurnStarts(Date.now(), (e) => finalizeParkedEntryCard(deps, e, QUEUED_CARD_EXPIRED_HTML));
80547
+ const removed = discardParkedTurnStart(ev.rawContent);
80548
+ if (removed != null)
80549
+ finalizeParkedEntryCard(deps, removed, QUEUED_CARD_FOLDED_HTML);
80429
80550
  return;
80430
80551
  }
80431
80552
  case "model": {
@@ -84944,8 +85065,8 @@ var HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION = 16 * 1024;
84944
85065
  var HINDSIGHT_PG_APP_ANON_MIB = 2560;
84945
85066
  var HINDSIGHT_PG_PAGE_CACHE_FLOOR_MIB = 2048;
84946
85067
  var HINDSIGHT_PG_SHARED_BUFFERS_BUDGET_MIB = HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION - HINDSIGHT_PG_APP_ANON_MIB - HINDSIGHT_PG_PAGE_CACHE_FLOOR_MIB;
84947
- var HINDSIGHT_PG_DEFAULT_SHARED_BUFFERS_MIB = 3072;
84948
- var HINDSIGHT_PG_DEFAULT_EFFECTIVE_CACHE_SIZE_MIB = 7168;
85068
+ var HINDSIGHT_PG_DEFAULT_SHARED_BUFFERS_MIB = 6144;
85069
+ var HINDSIGHT_PG_DEFAULT_EFFECTIVE_CACHE_SIZE_MIB = 12288;
84949
85070
  function pgMib(mib) {
84950
85071
  return `${mib}MB`;
84951
85072
  }
@@ -84989,7 +85110,7 @@ var HINDSIGHT_DEFAULT_RERANKER_MAX_CANDIDATES = 150;
84989
85110
  var HINDSIGHT_DEFAULT_RERANKER_LOCAL_MAX_CONCURRENT = 4;
84990
85111
  var HINDSIGHT_DEFAULT_RECALL_MAX_CONCURRENT = 8;
84991
85112
  var HINDSIGHT_DEFAULT_REFLECT_WALL_TIMEOUT_S = 600;
84992
- var HINDSIGHT_DEFAULT_CONSOLIDATION_MAX_MEMORIES_PER_ROUND = 500;
85113
+ var HINDSIGHT_DEFAULT_CONSOLIDATION_MAX_MEMORIES_PER_ROUND = 250;
84993
85114
  var HINDSIGHT_DEFAULT_CONSOLIDATION_SLOT_LIMIT = 6;
84994
85115
  var HINDSIGHT_DEFAULT_CONSOLIDATION_MAX_SLOTS = 1;
84995
85116
  var HINDSIGHT_DEFAULT_RECENCY_DECAY_FUNCTION = "exponential";
@@ -99678,10 +99799,10 @@ function startOutboxSweep(deps) {
99678
99799
  }
99679
99800
 
99680
99801
  // ../src/build-info.ts
99681
- var VERSION2 = "0.19.38";
99682
- var COMMIT_SHA = "9ec88983";
99683
- var COMMIT_DATE = "2026-07-30T09:50:08Z";
99684
- var LATEST_PR = 4031;
99802
+ var VERSION2 = "0.19.39";
99803
+ var COMMIT_SHA = "4aff2bdd";
99804
+ var COMMIT_DATE = "2026-07-31T00:54:36Z";
99805
+ var LATEST_PR = 4041;
99685
99806
  var COMMITS_AHEAD_OF_TAG = 0;
99686
99807
 
99687
99808
  // gateway/boot-version.ts
@@ -246,6 +246,15 @@ export interface HandbackPreturnSignal {
246
246
  * re-keyed to the real `statusKey` so the turn's end-of-turn
247
247
  * `clearActivitySummary` finalizes it. Cancels the debounce/self-reap. */
248
248
  tryAdopt: (turnId: string) => HandbackAdoption | null
249
+ /** True IFF a live (un-consumed) pre-turn entry is armed whose adopting turn
250
+ * is `turnId`. Consulted by the queued-card surface (stream-render Part B) at
251
+ * PARK time: when a handback pre-turn signal already owns the surface for the
252
+ * turn this parked message will mint, the queued card must NOT be posted —
253
+ * otherwise the same message ends up with two cards (the handback card the
254
+ * turn adopts, plus a queued card that then freezes). Turn-scoped, NOT
255
+ * key-scoped, so an unrelated user message parked on the same topic (a
256
+ * DIFFERENT adoptTurnId) is not wrongly suppressed. */
257
+ hasPendingForTurnId: (turnId: string) => boolean
249
258
  /** True IFF `turnKey` is a synthetic pre-turn record key. */
250
259
  isPreTurnRecord: (turnKey: string) => boolean
251
260
  /** Reap hook for the gateway's mid-session / boot card reapers: stop the
@@ -516,6 +525,13 @@ export function createHandbackPreturnSignal(
516
525
  return adoption
517
526
  },
518
527
 
528
+ hasPendingForTurnId(turnId) {
529
+ for (const e of byKey.values()) {
530
+ if (e.adoptTurnId === turnId && !e.consumed) return true
531
+ }
532
+ return false
533
+ },
534
+
519
535
  isPreTurnRecord(turnKey) {
520
536
  return turnKey.startsWith(PRETURN_TURNKEY_PREFIX)
521
537
  },