@sema-agent/cli 1.0.87 → 1.0.89

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/sema-main.js CHANGED
@@ -55614,6 +55614,12 @@ function isLimitsExceededCode(code2) {
55614
55614
  function isDelegationCapCode(code2) {
55615
55615
  return typeof code2 == "string" && code2.startsWith("delegation.");
55616
55616
  }
55617
+ function delegationCapDispositionOf(code2) {
55618
+ if (code2 === DELEGATION_CONCURRENCY_CAP)
55619
+ return "wait-for-slot";
55620
+ if (code2 === DELEGATION_SESSION_CAP)
55621
+ return "reuse-existing-or-await-reap";
55622
+ }
55617
55623
  function isConfigRefusalCode(code2) {
55618
55624
  return typeof code2 == "string" && code2.startsWith("config.");
55619
55625
  }
@@ -55626,7 +55632,7 @@ function isRewindFamilyCode(code2) {
55626
55632
  function asModelFallbackReason(v2) {
55627
55633
  return v2 === MODEL_FALLBACK_INHERIT_NO_TIER_BINDING ? MODEL_FALLBACK_INHERIT_NO_TIER_BINDING : void 0;
55628
55634
  }
55629
- var LIMITS_MAX_TOKENS_EXCEEDED, LIMITS_MAX_COST_EXCEEDED, LIMITS_MAX_TURNS_EXCEEDED, LIMITS_MAX_WALLTIME_EXCEEDED, LIMITS_ERROR_CODE_PREFIX, USAGE_WINDOW_EXHAUSTED, ENV_LIFETIME_EXPIRED, CONFIG_LIMIT_INVALID, CONFIG_STRATEGY_FIND_LIMIT_INVALID, CONFIG_STRATEGY_MAX_SIZE_INVALID, CONFIG_LIMIT_UNKNOWN_KEY, CONFIG_DELEGATION_ENTRY_CAPS, CONFIG_REFUSAL_CODES, DELEGATION_CONCURRENCY_CAP, DELEGATION_SESSION_CAP, DELEGATION_CAP_CODES, TOOL_END_INTERRUPTED_NEVER_STARTED, TOOL_END_INTERRUPTED_OUTCOME_UNKNOWN, TOOL_END_INTERRUPTED_CODES, ACTIVE_RUN_BUSY_ERROR_CODE, STOP_PARK_ARBITER_UNREACHABLE, STOP_PARK_RESUME_WON, STOP_NOT_LANDED, STOP_NOT_LOCAL, STOP_PARKED, STOP_CONFLICT_CODES, OUTPUT_INVALID, RESUME_AT_ERROR_CODE_PREFIX, REWIND_ERROR_CODE_PREFIXES, DRAINING_ERROR_CODE, SCENARIO_NOT_ALLOWED_ERROR_CODE, STREAM_MAX_DURATION, MODEL_FALLBACK_INHERIT_NO_TIER_BINDING, init_engineErrorCodes = __esm({
55635
+ var LIMITS_MAX_TOKENS_EXCEEDED, LIMITS_MAX_COST_EXCEEDED, LIMITS_MAX_TURNS_EXCEEDED, LIMITS_MAX_WALLTIME_EXCEEDED, LIMITS_ERROR_CODE_PREFIX, USAGE_WINDOW_EXHAUSTED, ENV_LIFETIME_EXPIRED, CONFIG_LIMIT_INVALID, CONFIG_STRATEGY_FIND_LIMIT_INVALID, CONFIG_STRATEGY_MAX_SIZE_INVALID, CONFIG_LIMIT_UNKNOWN_KEY, CONFIG_DELEGATION_ENTRY_CAPS, CONFIG_REFUSAL_CODES, DELEGATION_CONCURRENCY_CAP, DELEGATION_SESSION_CAP, DELEGATION_CAP_CODES, MCP_SERVER_REVOKED, TOOL_END_INTERRUPTED_NEVER_STARTED, TOOL_END_INTERRUPTED_OUTCOME_UNKNOWN, TOOL_END_INTERRUPTED_CODES, ACTIVE_RUN_BUSY_ERROR_CODE, STOP_PARK_ARBITER_UNREACHABLE, STOP_PARK_RESUME_WON, STOP_NOT_LANDED, STOP_NOT_LOCAL, STOP_PARKED, STOP_CONFLICT_CODES, OUTPUT_INVALID, RESUME_AT_ERROR_CODE_PREFIX, REWIND_ERROR_CODE_PREFIXES, DRAINING_ERROR_CODE, SCENARIO_NOT_ALLOWED_ERROR_CODE, STREAM_MAX_DURATION, MODEL_FALLBACK_INHERIT_NO_TIER_BINDING, init_engineErrorCodes = __esm({
55630
55636
  "node_modules/@sema-agent/client-core/dist/engineErrorCodes.js"() {
55631
55637
  LIMITS_MAX_TOKENS_EXCEEDED = "limits.max_tokens_exceeded", LIMITS_MAX_COST_EXCEEDED = "limits.max_cost_exceeded", LIMITS_MAX_TURNS_EXCEEDED = "limits.max_turns_exceeded", LIMITS_MAX_WALLTIME_EXCEEDED = "limits.max_walltime_exceeded", LIMITS_ERROR_CODE_PREFIX = "limits.";
55632
55638
  USAGE_WINDOW_EXHAUSTED = "usage.window_exhausted", ENV_LIFETIME_EXPIRED = "env.lifetime_expired", CONFIG_LIMIT_INVALID = "config.limit_invalid", CONFIG_STRATEGY_FIND_LIMIT_INVALID = "config.strategy_find_limit_invalid", CONFIG_STRATEGY_MAX_SIZE_INVALID = "config.strategy_max_size_invalid", CONFIG_LIMIT_UNKNOWN_KEY = "config.limit_unknown_key", CONFIG_DELEGATION_ENTRY_CAPS = "config.delegation_entry_caps", CONFIG_REFUSAL_CODES = /* @__PURE__ */ new Set([
@@ -55639,6 +55645,7 @@ var LIMITS_MAX_TOKENS_EXCEEDED, LIMITS_MAX_COST_EXCEEDED, LIMITS_MAX_TURNS_EXCEE
55639
55645
  DELEGATION_CONCURRENCY_CAP,
55640
55646
  DELEGATION_SESSION_CAP
55641
55647
  ]);
55648
+ MCP_SERVER_REVOKED = "mcp.server_revoked";
55642
55649
  TOOL_END_INTERRUPTED_NEVER_STARTED = "interrupted_never_started", TOOL_END_INTERRUPTED_OUTCOME_UNKNOWN = "interrupted_outcome_unknown", TOOL_END_INTERRUPTED_CODES = /* @__PURE__ */ new Set([
55643
55650
  TOOL_END_INTERRUPTED_NEVER_STARTED,
55644
55651
  TOOL_END_INTERRUPTED_OUTCOME_UNKNOWN
@@ -59397,7 +59404,7 @@ function eventToSdkMessage(ev, ctx) {
59397
59404
  // falls back to the mock synthesizer (events.d.ts:79). Not a renderable CC SDKMessage —
59398
59405
  // a side-channel arm `sdkMessagesToCcEvents` reads; CC's own renderer never sees it.
59399
59406
  case "tool_end": {
59400
- let structured = ev.structured, toolEndErrorCode = ev.errorCode, toolEndSettledBy = ev.settledBy, toolEndApprover = ev.approver;
59407
+ let structured = ev.structured, toolEndErrorCode = ev.errorCode, toolEndSettledBy = ev.settledBy, toolEndApprover = ev.approver, collateralAbort = ev._sema_collateral_abort;
59401
59408
  return projected(stamp(ctx, {
59402
59409
  type: "tool_end_result",
59403
59410
  toolCallId: ev.toolCallId,
@@ -59414,6 +59421,8 @@ function eventToSdkMessage(ev, ctx) {
59414
59421
  // #263 半场:结算种类 + 结算方身份(开集、缺席不铸、在场原样;顶部大段头注是判据本体)。
59415
59422
  ...typeof toolEndSettledBy == "string" && toolEndSettledBy.length > 0 ? { settledBy: toolEndSettledBy } : {},
59416
59423
  ...typeof toolEndApprover == "string" && toolEndApprover.length > 0 ? { approver: toolEndApprover } : {},
59424
+ // #324:连坐 abort 机读位(严格 true 才上臂;见上方头注)。
59425
+ ...collateralAbort === !0 ? { _sema_collateral_abort: !0 } : {},
59417
59426
  ...ev.eventId !== void 0 ? { eventId: ev.eventId } : {},
59418
59427
  ...ev.parentToolCallId !== void 0 ? { parentToolCallId: ev.parentToolCallId } : {}
59419
59428
  }));
@@ -63077,8 +63086,8 @@ function ensureWorkflowActivityLedger(cfg) {
63077
63086
  let evicted = activityLedgers.get(victim);
63078
63087
  evicted && (evicted.closed = !0, evicted.closedReason = "stopped", evicted.abort.abort(), emitActivityTick(evicted)), activityLedgers.delete(victim);
63079
63088
  }
63080
- let ledger = newActivityLedger(cfg.workflowId, scope);
63081
- activityLedgers.set(cfg.workflowId, ledger), consumeWorkflowActivity(ledger, cfg);
63089
+ let ledger2 = newActivityLedger(cfg.workflowId, scope);
63090
+ activityLedgers.set(cfg.workflowId, ledger2), consumeWorkflowActivity(ledger2, cfg);
63082
63091
  }
63083
63092
  function stopWorkflowActivityLedger(workflowId) {
63084
63093
  let l3 = activityLedgers.get(workflowId);
@@ -63160,21 +63169,21 @@ function createLiveWorkflowSource(config4) {
63160
63169
  ...config4.fetchImpl ? { fetchImpl: config4.fetchImpl } : {}
63161
63170
  });
63162
63171
  }
63163
- let ledger = activityDisabled ? void 0 : activityLedgers.get(id);
63164
- if (ledger) {
63165
- ledger.consumers += 1;
63172
+ let ledger2 = activityDisabled ? void 0 : activityLedgers.get(id);
63173
+ if (ledger2) {
63174
+ ledger2.consumers += 1;
63166
63175
  try {
63167
63176
  for (; ; ) {
63168
- let beat = await waitActivityTick(ledger, abort.signal);
63177
+ let beat = await waitActivityTick(ledger2, abort.signal);
63169
63178
  if (beat === "abort" || disposed4)
63170
63179
  return;
63171
63180
  if (beat === "tick" && (connected = !0), Date.now() - lastGetAt >= REFRESH_THROTTLE_MS && await refresh(id, abort.signal), degraded || beat === "closed")
63172
63181
  break;
63173
63182
  }
63174
63183
  } finally {
63175
- ledger.consumers -= 1;
63184
+ ledger2.consumers -= 1;
63176
63185
  }
63177
- ledger.displaced && (activityDisabled = !0, engineWireDebugEnabled() && hostLog("debug", `[sema][workflow] activity ledger for ${id} was taken over by another engine target/principal \u2014 this source stops re-opening it (GET polling only)`));
63186
+ ledger2.displaced && (activityDisabled = !0, engineWireDebugEnabled() && hostLog("debug", `[sema][workflow] activity ledger for ${id} was taken over by another engine target/principal \u2014 this source stops re-opening it (GET polling only)`));
63178
63187
  }
63179
63188
  !disposed4 && !abort.signal.aborted && await abortableSleep(STREAM_DROP_BACKOFF_MS, abort.signal);
63180
63189
  } catch (err8) {
@@ -65444,6 +65453,9 @@ function pathFromGateMessage(message) {
65444
65453
  if (typeof message == "string")
65445
65454
  return FS_WRITE_GATE_ASK_PATTERN.exec(message)?.[1];
65446
65455
  }
65456
+ function isNonNegativeFinite(v2) {
65457
+ return typeof v2 == "number" && Number.isFinite(v2) && v2 >= 0;
65458
+ }
65447
65459
  function isWireRecordCarrier(v2) {
65448
65460
  return typeof v2 == "object" && v2 !== null && !Array.isArray(v2);
65449
65461
  }
@@ -65487,6 +65499,22 @@ async function surfaceToolApprovalFrameAndRespond(frame, respond, streamArgs, si
65487
65499
  ...isFromSubagent(frame) ? { workerBadge: subagentBadgeFor(frame) } : {},
65488
65500
  ...wireNote !== void 0 ? { wireNote } : {},
65489
65501
  ...frame.governanceForced === !0 ? { governanceForced: !0 } : {},
65502
+ // [4851]:窗三键透传,三闸合取(异源对抗复审 P1/P2 收编):
65503
+ // ① `lane.windowIsCurrent === true` —— durable 账本重放的历史帧带的是铸帧时刻的旧余量,
65504
+ // 给它续窗 = 过期 ask 渲出精确假倒计时(壳孪生族同名闸的本包席位,见 LaneOpts 注);
65505
+ // ② **非负有限数**才 stamp —— `Number.isFinite` 单独放行负数,而三键定义域按 SDK 契约
65506
+ // 本就非负(`expiresInMs = max(0, …)`;0 合法 = 窗恰好到点)。负数/NaN/Infinity =
65507
+ // 坏形降缺席,绝不折 0 或猜(同文件 delegation.depth 曾同款教训);
65508
+ // ③ 三键各自独立 stamp:server 承诺同门在场,但包边界不替上游把「半套在场」湮灭成全缺席
65509
+ // —— 读器自己按「expiresAtMs 优先、expiresInMs 兜底」消化半套。
65510
+ // 任一键 stamp 时同步盖 `receivedAtMs`(本地收帧锚):卡口串行阻塞下,排队靠后的卡若按
65511
+ // 「呈现那一刻」起算余量,窗被整段还回去 —— 壳读器明文优先这枚锚。
65512
+ ...lane?.windowIsCurrent === !0 ? {
65513
+ ...isNonNegativeFinite(frame.expiresInMs) ? { expiresInMs: frame.expiresInMs } : {},
65514
+ ...isNonNegativeFinite(frame.expiresAtMs) ? { expiresAtMs: frame.expiresAtMs } : {},
65515
+ ...isNonNegativeFinite(frame.serverNowMs) ? { serverNowMs: frame.serverNowMs } : {},
65516
+ ...isNonNegativeFinite(frame.expiresInMs) || isNonNegativeFinite(frame.expiresAtMs) ? { receivedAtMs: Date.now() } : {}
65517
+ } : {},
65490
65518
  // 🔴 跨字段不变量(对抗复审命中):`delegation` 只在**子代 ask** 的门上在场(SDK 头注:
65491
65519
  // "Present on the same door as fromSubagent (child asks only)")。只校对象形不校这一条 ⇒
65492
65520
  // 一个**宿主自己**的破坏性工具审批也能带着 delegation 到卡口,被呈成「某层子代发起的」——
@@ -65581,6 +65609,14 @@ var cardPortByKey, cardPortMissesByKey, TOOL_APPROVAL_FRAME_KEYS_MIRROR, RESPOND
65581
65609
  // sdk 7.1.0 的运行期锚**尚无**本键(node 直读实证:锚 17 项)⇒ 这是一次**领先**,进对账门的
65582
65610
  // AHEAD_OF_ANCHOR 带退出条件登记(SDK 追平当天那条登记自红逼删,回到逐元素相等)。
65583
65611
  "requiresRealApproval",
65612
+ // [4851] 头号请托(client-core 0.38.2):server 7.34.0 起真发窗三键(#288/[4429]② cli 自己请托,
65613
+ // server src/tool-approval.ts 三键声明+条件 stamp)。⚠️ 与 requiresRealApproval 同形=**领先** SDK
65614
+ // 运行期锚(sdk 7.2.0 锚 17 项,node 直读实证无三键)⇒ 进对账门 AHEAD_OF_ANCHOR 带退出条件登记
65615
+ // (SDK 追平当天登记自红逼删)。0.38.1 把三键丢在包边界外 = [4845]「卡到期屏幕零反应」的直接成因
65616
+ // (壳读器 readAskDeadlineMs 早已预埋,缺的一直是包边界这一格——#283 逐字同形第四例)。
65617
+ "expiresInMs",
65618
+ "expiresAtMs",
65619
+ "serverNowMs",
65584
65620
  "delegation",
65585
65621
  "outcome"
65586
65622
  ];
@@ -65615,6 +65651,9 @@ function isAskTool(toolName2) {
65615
65651
  function isGatedToolName(name) {
65616
65652
  return isAskToolLoose(name) ? !0 : typeof name != "string" ? !1 : toolNameIsFsWrite(name) || toolNameIsShellExec(name);
65617
65653
  }
65654
+ function isFsOrShellToolName(name) {
65655
+ return typeof name == "string" && (toolNameIsFsWrite(name) || toolNameIsShellExec(name));
65656
+ }
65618
65657
  function isGatedToolEnd(ev) {
65619
65658
  return isGatedToolName(ev.toolName) ? !0 : toolEndOutputText(ev.output) === ENGINE_ABORT_TOOL_RESULT;
65620
65659
  }
@@ -65669,14 +65708,14 @@ function routeToolEnd(ev, callId, led) {
65669
65708
  throw new Error("frameRouter: tool_end \u6709\u5E8F\u81C2\u5168\u90E8\u843D\u7A7A \u2014\u2014 generic-close \u4E0D\u518D\u662F\u65E0\u6761\u4EF6\u515C\u5E95\u81C2");
65670
65709
  }
65671
65710
  function routeSuspended(ev, ctx) {
65672
- return ev.gate && isAskToolLoose(ev.gate.toolName) && ctx.taskId.current ? { kind: "park", gate: "ask" } : ev.gate && isToolApprovalGate(ev.gate) && ctx.taskId.current ? { kind: "park", gate: "fs" } : { kind: "yield", events: [ev] };
65711
+ return ev.gate && isAskToolLoose(ev.gate.toolName) && ctx.taskId.current ? (ctx.led.noteParkGate({ fsOrShellFamily: !1 }), { kind: "park", gate: "ask" }) : ev.gate && isToolApprovalGate(ev.gate) && ctx.taskId.current ? (ctx.led.noteParkGate({ fsOrShellFamily: isFsOrShellToolName(ev.gate.toolName) }), { kind: "park", gate: "fs" }) : { kind: "yield", events: [ev] };
65673
65712
  }
65674
65713
  function routeDone(ev, ctx) {
65675
65714
  let { led } = ctx;
65676
65715
  if (isAskGatePark(ev.result))
65677
- return ctx.taskId.current = ctx.taskId.current ?? ev.result.taskId, { kind: "park", gate: "ask", pendingDone: ev };
65716
+ return ctx.taskId.current = ctx.taskId.current ?? ev.result.taskId, led.noteParkGate({ fsOrShellFamily: !1 }), { kind: "park", gate: "ask", pendingDone: ev };
65678
65717
  if (isFsApprovalPark(ev.result))
65679
- return ctx.taskId.current = ctx.taskId.current ?? ev.result.taskId, { kind: "park", gate: "fs", pendingDone: ev };
65718
+ return ctx.taskId.current = ctx.taskId.current ?? ev.result.taskId, led.noteParkGate({ fsOrShellFamily: isFsOrShellToolName(ev.result.checkpointGate?.toolName) }), { kind: "park", gate: "fs", pendingDone: ev };
65680
65719
  let events3 = [...led.flushHeld()], r = ev.result, realTaskId = ctx.taskId.current;
65681
65720
  return realTaskId && r && r.taskId === r.sessionId && r.taskId !== realTaskId ? events3.push({ ...ev, result: { ...ev.result, taskId: realTaskId } }) : events3.push(ev), { kind: "end", events: events3 };
65682
65721
  }
@@ -65763,7 +65802,17 @@ var HITL_REJECT_MESSAGE, ENGINE_ABORT_TOOL_RESULT, TOOL_END_ARM_ORDER, TOOL_END_
65763
65802
 
65764
65803
  // node_modules/@sema-agent/client-core/dist/hitl/gateLedger.js
65765
65804
  function createGateLedger() {
65766
- let startedCalls = /* @__PURE__ */ new Set(), endedCalls = /* @__PURE__ */ new Set(), heldAskEnds = /* @__PURE__ */ new Map(), gatedStartArgsByCall = /* @__PURE__ */ new Map(), deniedCalls = /* @__PURE__ */ new Set(), pendingFsCalls = [], resolvedAnswers = /* @__PURE__ */ new Map(), decidedGates = /* @__PURE__ */ new Set(), lastFsOrShellGatedCall, denyStampNextFsEnd = !1, seq;
65805
+ let startedCalls = /* @__PURE__ */ new Set(), endedCalls = /* @__PURE__ */ new Set(), heldAskEnds = /* @__PURE__ */ new Map(), gatedStartArgsByCall = /* @__PURE__ */ new Map(), deniedCalls = /* @__PURE__ */ new Set(), pendingFsCalls = [], resolvedAnswers = /* @__PURE__ */ new Map(), decidedGates = /* @__PURE__ */ new Set(), fsOrShellFamilyGate = !1, droppedFromBatch = /* @__PURE__ */ new Set(), batchParkCount = 0, heldSinceLastPark = !1, fsOrShellGatedCalls = /* @__PURE__ */ new Set(), lastFsOrShellGatedCall, resolveGateSubjects = () => {
65806
+ if (batchParkCount !== 1 || !fsOrShellFamilyGate)
65807
+ return;
65808
+ for (let id of heldAskEnds.keys())
65809
+ if (!startedCalls.has(id))
65810
+ return;
65811
+ let family = [.../* @__PURE__ */ new Set([...heldAskEnds.keys(), ...droppedFromBatch])].filter((id) => fsOrShellGatedCalls.has(id));
65812
+ return family.length === 1 ? new Set(family) : void 0;
65813
+ }, retireBatchState = () => {
65814
+ fsOrShellFamilyGate = !1, droppedFromBatch.clear(), batchParkCount = 0, heldSinceLastPark = !1;
65815
+ }, denyStampNextFsEnd = !1, seq;
65767
65816
  return {
65768
65817
  noteSeq(ev) {
65769
65818
  let rawSeq = ev.id ?? ev.seq;
@@ -65788,18 +65837,19 @@ function createGateLedger() {
65788
65837
  endedCalls.add(callId);
65789
65838
  },
65790
65839
  hold(callId, ev) {
65791
- heldAskEnds.set(callId, ev);
65840
+ heldAskEnds.has(callId) || (heldSinceLastPark = !0), heldAskEnds.set(callId, ev);
65792
65841
  },
65793
65842
  dropHeld(callId) {
65794
- heldAskEnds.delete(callId);
65843
+ heldAskEnds.delete(callId) && droppedFromBatch.add(callId), heldAskEnds.size === 0 && retireBatchState();
65795
65844
  },
65796
65845
  heldCount() {
65797
65846
  return heldAskEnds.size;
65798
65847
  },
65799
65848
  *flushHeld() {
65800
- for (let [callId, held] of heldAskEnds)
65801
- endedCalls.add(callId), yield held;
65802
- heldAskEnds.clear();
65849
+ let subjects = resolveGateSubjects();
65850
+ for (let [callId, ev] of heldAskEnds)
65851
+ endedCalls.add(callId), yield subjects !== void 0 && !subjects.has(callId) ? { ...ev, [SEMA_COLLATERAL_ABORT_KEY]: !0 } : ev;
65852
+ heldAskEnds.clear(), retireBatchState();
65803
65853
  },
65804
65854
  markDenied(callId) {
65805
65855
  deniedCalls.add(callId);
@@ -65827,11 +65877,14 @@ function createGateLedger() {
65827
65877
  return pendingFsCalls.length > 0 ? pendingFsCalls[pendingFsCalls.length - 1] : void 0;
65828
65878
  },
65829
65879
  noteFsOrShellGate(callId) {
65830
- lastFsOrShellGatedCall = callId;
65880
+ lastFsOrShellGatedCall = callId, fsOrShellGatedCalls.add(callId);
65831
65881
  },
65832
65882
  lastFsOrShellGatedCallId() {
65833
65883
  return lastFsOrShellGatedCall;
65834
65884
  },
65885
+ noteParkGate(evidence) {
65886
+ batchParkCount > 0 && !heldSinceLastPark || (batchParkCount += 1, fsOrShellFamilyGate = evidence.fsOrShellFamily, heldSinceLastPark = !1);
65887
+ },
65835
65888
  rememberAnswer(callId, answered) {
65836
65889
  resolvedAnswers.set(callId, answered);
65837
65890
  },
@@ -65852,8 +65905,9 @@ function createGateLedger() {
65852
65905
  }
65853
65906
  };
65854
65907
  }
65855
- var init_gateLedger = __esm({
65908
+ var SEMA_COLLATERAL_ABORT_KEY, init_gateLedger = __esm({
65856
65909
  "node_modules/@sema-agent/client-core/dist/hitl/gateLedger.js"() {
65910
+ SEMA_COLLATERAL_ABORT_KEY = "_sema_collateral_abort";
65857
65911
  }
65858
65912
  });
65859
65913
 
@@ -66044,6 +66098,7 @@ var init_askGateWire = __esm({
66044
66098
  init_frameRouter();
66045
66099
  init_parkResolver();
66046
66100
  init_frameRouter();
66101
+ init_gateLedger();
66047
66102
  init_parkResolver();
66048
66103
  }
66049
66104
  });
@@ -68747,6 +68802,7 @@ __export(dist_exports, {
68747
68802
  MAX_TURNS_MAX: () => MAX_TURNS_MAX,
68748
68803
  MAX_TURNS_MIN: () => MAX_TURNS_MIN,
68749
68804
  MCP_CAPS: () => MCP_CAPS,
68805
+ MCP_SERVER_REVOKED: () => MCP_SERVER_REVOKED,
68750
68806
  MIGRATED_COMPENSATIONS: () => MIGRATED_COMPENSATIONS,
68751
68807
  MODEL_FALLBACK_INHERIT_NO_TIER_BINDING: () => MODEL_FALLBACK_INHERIT_NO_TIER_BINDING,
68752
68808
  MODEL_FAMILIES: () => MODEL_FAMILIES,
@@ -68799,6 +68855,7 @@ __export(dist_exports, {
68799
68855
  SEAT_VALIDATOR_COVERAGE_EXEMPT: () => SEAT_VALIDATOR_COVERAGE_EXEMPT,
68800
68856
  SEAT_VALIDATOR_KEY_COVERAGE: () => SEAT_VALIDATOR_KEY_COVERAGE,
68801
68857
  SELF_ORCHESTRATION_ENV: () => SELF_ORCHESTRATION_ENV,
68858
+ SEMA_COLLATERAL_ABORT_KEY: () => SEMA_COLLATERAL_ABORT_KEY,
68802
68859
  SEND_MESSAGE_REQUEST_KEYS: () => SEND_MESSAGE_REQUEST_KEYS,
68803
68860
  SESSION_SEARCH_RESULT_KEYS: () => SESSION_SEARCH_RESULT_KEYS,
68804
68861
  SKILL_CAPS: () => SKILL_CAPS,
@@ -68968,6 +69025,7 @@ __export(dist_exports, {
68968
69025
  deferToolsForRequest: () => deferToolsForRequest,
68969
69026
  degradedToolResultBody: () => degradedToolResultBody,
68970
69027
  delegatedPromptText: () => delegatedPromptText,
69028
+ delegationCapDispositionOf: () => delegationCapDispositionOf,
68971
69029
  denyReasonForWire: () => denyReasonForWire,
68972
69030
  deriveAgentLabel: () => deriveAgentLabel,
68973
69031
  deriveNotificationResidualLines: () => deriveNotificationResidualLines,
@@ -78844,7 +78902,7 @@ function extraBodyUnsafe(v2) {
78844
78902
  function workerRouteKey(w2) {
78845
78903
  return w2.routePrefix ?? w2.name;
78846
78904
  }
78847
- var SECRET_LITERAL_RE, ENV_NAME, hasNul, NON_SECRET_URL, K8S_QUANTITY, TCP_PORT, ModelCost, SEALED_BOX_ALG, BASE64_SHAPE, SealedApiKey, ModelEntry, ModelRole, RoleTarget, TierBindings, TierGroup, ModelsConfig, RosterEntry, RostersConfig, ScenarioEntry, ScenarioConfig, DELIVER_DENYLIST, SystemEntry, SystemsConfig, SystemStatusEntry, RuntimeConfig, GovernanceConfig, EntitlementBudget, TokenQuota, BudgetGroupMember, BudgetGroup, ScenarioAssignments, EntitlementRuntimeCaps, EntitlementTier, EntitlementOverride, EntitlementSubject, EntitlementGroupBinding, EntitlementConfig, PrincipalOrgMemoryWire, PrincipalCapsWire, ActorAssertionWire, SESSION_MIRROR_ENGINE_URL, SessionMirrorPolicy, ExecutionPublicKey, ExecutionPolicy, PROJECT_ID_REGEX, ProjectRegistration, ProjectsConfig, CollabTopology, CollabFinalizerType, CollabEarlyStop, CollabPersistence, CollabMember, CollabSlot, CollabTemplate, CollabConfig, DURATION, WorkerLifecycle, WorkerSecretRefs, RESERVED_WORKER_ENV, RESERVED_ENV_FIELD, WorkerSpec, WorkersConfig, WorkerCondition, WorkerStatus, HOST_NAME_MAX, HOSTS_ARRAY_MAX, HostEntry, HostsConfig, PROBE_CPU_CORES_MAX, PROBE_MEM_BYTES_MAX, HostProbes, HostStatus, SkillSpec, SkillsConfig, SkillsManifestSchema, McpEnvRefs, HTTP_HEADER_NAME, McpHeaderRefs, McpTransport, McpServerSpec, McpConfig, PLUGIN_ORIGIN, GIT_COMMIT_SHA, PluginSource, PluginSpec, PluginsConfig, PromptTextDeclaration, PromptBinding, PROMPT_ARTIFACT_LIMITS, PromptArtifactSection, PromptCatalogSnapshot, PromptEpochArtifactPayload, PublishedPromptArtifactEnvelope, PromptsConfig, EffectivePrompts, EffectivePromptsWire, DOMAIN_SCHEMAS, SettingSource, EffectiveKey, DOMAINS, init_types6 = __esm({
78905
+ var SECRET_LITERAL_RE, ENV_NAME, hasNul, NON_SECRET_URL, K8S_QUANTITY, TCP_PORT, ModelCost, SEALED_BOX_ALG, BASE64_SHAPE, SealedApiKey, ModelEntry, ModelRole, RoleTarget, TierBindings, TierGroup, ModelsConfig, RosterEntry, RostersConfig, ScenarioEntry, ScenarioConfig, DELIVER_DENYLIST, SystemEntry, SystemsConfig, SystemStatusEntry, RuntimeConfig, InfraCostRates, LimitsConfig, GovernanceConfig, EntitlementBudget, TokenQuota, BudgetGroupMember, BudgetGroup, ScenarioAssignments, EntitlementRuntimeCaps, EntitlementTier, EntitlementOverride, EntitlementSubject, EntitlementGroupBinding, EntitlementConfig, PrincipalOrgMemoryWire, PrincipalCapsWire, ActorAssertionWire, SESSION_MIRROR_ENGINE_URL, SessionMirrorPolicy, ExecutionPublicKey, ExecutionPolicy, PROJECT_ID_REGEX, ProjectRegistration, ProjectsConfig, CollabTopology, CollabFinalizerType, CollabEarlyStop, CollabPersistence, CollabMember, CollabSlot, CollabTemplate, CollabConfig, DURATION, WorkerLifecycle, WorkerSecretRefs, RESERVED_WORKER_ENV, RESERVED_ENV_FIELD, WorkerSpec, WorkersConfig, WorkerCondition, WorkerStatus, HOST_NAME_MAX, HOSTS_ARRAY_MAX, HostEntry, HostsConfig, PROBE_CPU_CORES_MAX, PROBE_MEM_BYTES_MAX, HostProbes, HostStatus, SkillSpec, SkillsConfig, SkillsManifestSchema, McpEnvRefs, HTTP_HEADER_NAME, McpHeaderRefs, McpTransport, McpServerSpec, McpConfig, PLUGIN_ORIGIN, GIT_COMMIT_SHA, PluginSource, PluginSpec, PluginsConfig, PromptTextDeclaration, PromptBinding, PROMPT_ARTIFACT_LIMITS, PromptArtifactSection, PromptCatalogSnapshot, PromptEpochArtifactPayload, PublishedPromptArtifactEnvelope, PromptsConfig, EffectivePrompts, EffectivePromptsWire, DOMAIN_SCHEMAS, SettingSource, EffectiveKey, DOMAINS, init_types6 = __esm({
78848
78906
  "node_modules/@sema-agent/registry-core/dist/types.js"() {
78849
78907
  init_zod();
78850
78908
  init_hash2();
@@ -79114,7 +79172,43 @@ var SECRET_LITERAL_RE, ENV_NAME, hasNul, NON_SECRET_URL, K8S_QUANTITY, TCP_PORT,
79114
79172
  maxTaskTokens: external_exports2.number().int().nonnegative().optional(),
79115
79173
  maxPrincipalCostUsd: external_exports2.number().finite().nonnegative().optional(),
79116
79174
  costQuotaWindowSec: external_exports2.number().int().positive().optional()
79117
- }), GovernanceConfig = external_exports2.object({
79175
+ }), InfraCostRates = external_exports2.object({
79176
+ toolCallMicroUsd: external_exports2.number().finite().optional(),
79177
+ sandboxSecMicroUsd: external_exports2.number().finite().optional(),
79178
+ egressGbMicroUsd: external_exports2.number().finite().optional()
79179
+ }).passthrough(), LimitsConfig = external_exports2.object({
79180
+ // `.optional()` 无默认,与 RuntimeConfig 同纪律:ABSENT = 「center 不管这一键」⇒ 消费方回自己的 env 底;
79181
+ // 显式值(**包括 0**)= 发布了一个真值(0 多半是「关断哨兵」,语义归消费方)。给默认值 = 静默覆盖部署。
79182
+ /** 每 principal 每分钟请求上限。 */
79183
+ rateLimitPerMin: external_exports2.number().finite().optional(),
79184
+ /** 每 principal 滚动窗累计花费上限(USD)。 */
79185
+ maxPrincipalCostUsd: external_exports2.number().finite().optional(),
79186
+ /** 上面那条配额的窗长(秒)。 */
79187
+ costQuotaWindowSec: external_exports2.number().finite().optional(),
79188
+ /** 单任务成本天花板(USD)。 */
79189
+ maxTaskCostUsd: external_exports2.number().finite().optional(),
79190
+ /** 单任务 token 天花板。 */
79191
+ maxTaskTokens: external_exports2.number().finite().optional(),
79192
+ /** 基建计价(micro-USD/单位)。见 {@link InfraCostRates}。 */
79193
+ infraCostRates: InfraCostRates.optional(),
79194
+ /** 附件孤儿对象 GC 宽限(ms)。 */
79195
+ attachmentOrphanGraceMs: external_exports2.number().finite().optional(),
79196
+ /** workspace 单文件读上限(字节)。 */
79197
+ workspaceFileMaxBytes: external_exports2.number().finite().optional(),
79198
+ /** 附件单文件上限(字节)。 */
79199
+ attachmentMaxBytes: external_exports2.number().finite().optional(),
79200
+ /** 附件 mime 白名单。**空数组 = 显式「一个都不许」**,与缺席(本键不管)不是一回事——元素只判
79201
+ * 「是字符串」,空串/大小写/别名归消费方(它会响亮拒,见域头注的判据分工)。 */
79202
+ attachmentMimeAllowlist: external_exports2.array(external_exports2.string()).optional(),
79203
+ /** 未绑定附件 TTL(ms)。 */
79204
+ attachmentUnboundTtlMs: external_exports2.number().finite().optional(),
79205
+ /** SIGTERM drain 窗(ms)。 */
79206
+ drainGraceMs: external_exports2.number().finite().optional(),
79207
+ /** run 心跳陈旧窗(秒)。 */
79208
+ runStaleSec: external_exports2.number().finite().optional(),
79209
+ /** 卸载工具结果的 TTL(秒)。 */
79210
+ toolResultTtlSec: external_exports2.number().finite().optional()
79211
+ }).passthrough(), GovernanceConfig = external_exports2.object({
79118
79212
  // autonomy:一个跨 knob 的安全总开关 / 放权梯度(普通用户敢用 + 专业用户放权)。
79119
79213
  // read-only(只读规划,不落改)| ask(每个放权动作问)| plan(plan-review 门)| auto(放开)。
79120
79214
  // ⚠️ 消费侧(service)把它**展开**到 core 已有三原语(handsReadOnly / shellGate+onAsk / plan_review),
@@ -79959,8 +80053,10 @@ var SECRET_LITERAL_RE, ENV_NAME, hasNul, NON_SECRET_URL, K8S_QUANTITY, TCP_PORT,
79959
80053
  // 0.8.0: S3 execution-lane policy (scope 级; client-advisory until service gate)
79960
80054
  projects: ProjectsConfig,
79961
80055
  // 0.10.0: 142-S3 project identity ledger + 无仓铸造权威 (scope=tenant 轴; NOT portable — 租户身份数据)
79962
- prompts: PromptsConfig
80056
+ prompts: PromptsConfig,
79963
80057
  // 0.10.18: center prompts 战役 v1(board [1050]/[1051]/[1057];写门/store 携带解锁=[1064]②)
80058
+ limits: LimitsConfig
80059
+ // 0.19.0: cost/限流族热更新发布位(sema-server #322 批1;本地腿闭集缺口的源头修复)
79964
80060
  // integrations + access: DELETED in 0.6.0 (EXPERT-REDESIGN §9) — parseDomain/effective/路由随之 404。
79965
80061
  }, SettingSource = external_exports2.discriminatedUnion("axis", [
79966
80062
  external_exports2.object({ axis: external_exports2.literal("layer"), layer: external_exports2.enum(["MANAGED", "PROJECT", "LOCAL"]), applied: external_exports2.boolean().optional(), reason: external_exports2.string().optional() }),
@@ -80095,10 +80191,13 @@ function parseDomain(domain2, raw2) {
80095
80191
  return r.data;
80096
80192
  throw sanitizeZodError(r.error);
80097
80193
  }
80098
- var USER_ROLES, init_config_fns = __esm({
80194
+ var USER_ROLES, OPEN_WORLD_KNOWN_KEYS, init_config_fns = __esm({
80099
80195
  "node_modules/@sema-agent/registry-core/dist/config-fns.js"() {
80100
80196
  init_types6();
80101
80197
  USER_ROLES = ["viewer", "editor", "publisher", "admin"];
80198
+ OPEN_WORLD_KNOWN_KEYS = {
80199
+ limits: { "": Object.keys(LimitsConfig.shape), infraCostRates: Object.keys(InfraCostRates.shape) }
80200
+ };
80102
80201
  }
80103
80202
  });
80104
80203
 
@@ -110610,7 +110709,7 @@ var import_stack_utils, import_jsx_runtime6, cleanupPath, stackUtils, init_Error
110610
110709
  // build-src/src/ink/components/TerminalSizeContext.tsx
110611
110710
  var import_react9, TerminalSizeContext, init_TerminalSizeContext = __esm({
110612
110711
  "build-src/src/ink/components/TerminalSizeContext.tsx"() {
110613
- import_react9 = __toESM(require_react()), TerminalSizeContext = (0, import_react9.createContext)(null);
110712
+ import_react9 = __toESM(require_react(), 1), TerminalSizeContext = (0, import_react9.createContext)(null);
110614
110713
  }
110615
110714
  });
110616
110715
 
@@ -116685,6 +116784,24 @@ var init_types8 = __esm({
116685
116784
  }
116686
116785
  });
116687
116786
 
116787
+ // build-src/src/sema/untrustedDisplayText.ts
116788
+ function cleanUntrustedForDisplay(v2, max2) {
116789
+ return String(v2 ?? "").replace(CONTROL_CHARS, ".").replace(BIDI_AND_SEPARATORS, ".").replace(LONE_SURROGATE, ".").slice(0, max2).replace(LONE_SURROGATE, ".");
116790
+ }
116791
+ function cleanUntrustedKeepLayout(v2) {
116792
+ return String(v2 ?? "").replace(CONTROL_CHARS_KEEP_LAYOUT, ".").replace(BIDI_AND_SEPARATORS, ".").replace(LONE_SURROGATE, ".");
116793
+ }
116794
+ function cleanUntrustedScalar(v2) {
116795
+ return String(v2 ?? "").replace(SCALAR_UNSAFE, (ch2) => "\\u" + (ch2.codePointAt(0) ?? 0).toString(16).toUpperCase().padStart(4, "0"));
116796
+ }
116797
+ var CONTROL_CHARS, BIDI_AND_SEPARATORS, LONE_SURROGATE, CONTROL_CHARS_KEEP_LAYOUT, SCALAR_UNSAFE, init_untrustedDisplayText = __esm({
116798
+ "build-src/src/sema/untrustedDisplayText.ts"() {
116799
+ CONTROL_CHARS = /[\u0000-\u001f\u007f-\u009f]/g, BIDI_AND_SEPARATORS = /[\u061c\u200e\u200f\u2028\u2029\u202a-\u202e\u2066-\u2069]/g, LONE_SURROGATE = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g;
116800
+ CONTROL_CHARS_KEEP_LAYOUT = /[\u0000-\u0008\u000b-\u001f\u007f-\u009f]/g;
116801
+ SCALAR_UNSAFE = /[\u0000-\u001F\u007F-\u009F\u061C\u200E\u200F\u2028\u2029\u202A-\u202E\u2066-\u2069]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g;
116802
+ }
116803
+ });
116804
+
116688
116805
  // build-src/src/sema/sessionIdMapping.ts
116689
116806
  var sessionIdMapping_exports = {};
116690
116807
  __export(sessionIdMapping_exports, {
@@ -117102,10 +117219,7 @@ function hostSink(e, billTurnCosts = !0) {
117102
117219
  return;
117103
117220
  }
117104
117221
  if (e.kind === "human_input") {
117105
- let clean8 = (v2) => (
117106
- // eslint-disable-next-line no-control-regex
117107
- String(v2 ?? "").replace(/[\x00-\x1f\x7f]/g, ".").slice(0, 120)
117108
- ), who = e.actor?.id ? `${clean8(e.actor.id)}${e.actor.hostAsserted === !0 ? "" : " (unverified)"}` : "unattributed";
117222
+ let clean8 = (v2) => cleanUntrustedForDisplay(v2, 120), who = e.actor?.id ? `${clean8(e.actor.id)}${e.actor.hostAsserted === !0 ? "" : " (unverified)"}` : "unattributed";
117109
117223
  Promise.resolve().then(() => (init_debug(), debug_exports)).then(
117110
117224
  (m2) => m2.logForDebugging(
117111
117225
  `[sema][wire] human_input ledger: carrier=${clean8(e.carrier)} source=${clean8(e.source)} delivery=${clean8(e.delivery)} actor=${who}${e.eventId ? ` eventId=${clean8(e.eventId)}` : ""}`
@@ -117153,6 +117267,7 @@ function runStream2(events3, ctx, handle2 = {}, o = {}) {
117153
117267
  var reportedDroppedTypes2, DROPPED_TYPE_MEMO_CAP2, init_runStream2 = __esm({
117154
117268
  "build-src/src/seam/adapter/runStream.ts"() {
117155
117269
  init_dist();
117270
+ init_untrustedDisplayText();
117156
117271
  init_activeRunSelfHeal2();
117157
117272
  init_dist();
117158
117273
  reportedDroppedTypes2 = /* @__PURE__ */ new Set(), DROPPED_TYPE_MEMO_CAP2 = 64;
@@ -184546,8 +184661,12 @@ function stripImagesFromMessages(messages) {
184546
184661
  } : message;
184547
184662
  });
184548
184663
  }
184664
+ function hasPtlRetryMarkerHead(messages) {
184665
+ let head = messages[0];
184666
+ return head?.type === "user" && head.isMeta === !0 && head.message.content === PTL_RETRY_MARKER;
184667
+ }
184549
184668
  function truncateHeadForPTLRetry(messages, ptlResponse) {
184550
- let input = messages[0]?.type === "user" && messages[0].isMeta && messages[0].message.content === PTL_RETRY_MARKER ? messages.slice(1) : messages, groups = groupMessagesByApiRound(input);
184669
+ let input = hasPtlRetryMarkerHead(messages) ? messages.slice(1) : messages, groups = groupMessagesByApiRound(input);
184551
184670
  if (groups.length < 2) return null;
184552
184671
  let tokenGap = getPromptTooLongTokenGap(ptlResponse), dropCount;
184553
184672
  if (tokenGap !== void 0) {
@@ -184803,11 +184922,14 @@ async function partialCompactConversation(allMessages, pivotIndex, context3, cac
184803
184922
  User context: ${userFeedback}` : hookResult.newCustomInstructions ? customInstructions = hookResult.newCustomInstructions : userFeedback && (customInstructions = `User context: ${userFeedback}`), context3.setStreamMode?.("requesting"), context3.setResponseLength?.(() => 0), context3.onCompactProgress?.({ type: "compact_start" });
184804
184923
  let compactPrompt = getPartialCompactPrompt(customInstructions, direction), summaryRequest = createUserMessage({
184805
184924
  content: compactPrompt
184806
- }), failureMetadata = {
184925
+ }), apiMessages = direction === "up_to" ? messagesToSummarize : allMessages, retryCacheSafeParams = direction === "up_to" ? { ...cacheSafeParams, forkContextMessages: messagesToSummarize } : cacheSafeParams, summarizedCount = () => {
184926
+ let real = apiMessages.length - (hasPtlRetryMarkerHead(apiMessages) ? 1 : 0);
184927
+ return Math.min(real, messagesToSummarize.length);
184928
+ }, failureMetadata = () => ({
184807
184929
  preCompactTokenCount,
184808
184930
  direction,
184809
- messagesSummarized: messagesToSummarize.length
184810
- }, apiMessages = direction === "up_to" ? messagesToSummarize : allMessages, retryCacheSafeParams = direction === "up_to" ? { ...cacheSafeParams, forkContextMessages: messagesToSummarize } : cacheSafeParams, summaryResponse, summary, ptlAttempts = 0;
184931
+ messagesSummarized: summarizedCount()
184932
+ }), summaryResponse, summary, ptlAttempts = 0;
184811
184933
  for (; summaryResponse = await streamCompactSummary({
184812
184934
  messages: apiMessages,
184813
184935
  summaryRequest,
@@ -184820,7 +184942,7 @@ User context: ${userFeedback}` : hookResult.newCustomInstructions ? customInstru
184820
184942
  let truncated = ptlAttempts <= MAX_PTL_RETRIES ? truncateHeadForPTLRetry(apiMessages, summaryResponse) : null;
184821
184943
  if (!truncated)
184822
184944
  throw {
184823
- ...failureMetadata
184945
+ ...failureMetadata()
184824
184946
  }, new Error(ERROR_MESSAGE_PROMPT_TOO_LONG);
184825
184947
  apiMessages.length - truncated.length, truncated.length, apiMessages = truncated, retryCacheSafeParams = {
184826
184948
  ...retryCacheSafeParams,
@@ -184830,10 +184952,10 @@ User context: ${userFeedback}` : hookResult.newCustomInstructions ? customInstru
184830
184952
  if (summary) {
184831
184953
  if (startsWithApiErrorPrefix(summary) || isGovernanceStopRowText(summary))
184832
184954
  throw {
184833
- ...failureMetadata
184955
+ ...failureMetadata()
184834
184956
  }, new Error(summary);
184835
184957
  } else throw {
184836
- ...failureMetadata
184958
+ ...failureMetadata()
184837
184959
  }, new Error(
184838
184960
  "Failed to generate conversation summary - response did not contain valid text content"
184839
184961
  );
@@ -184881,13 +185003,15 @@ User context: ${userFeedback}` : hookResult.newCustomInstructions ? customInstru
184881
185003
  }), postCompactTokenCount = tokenCountFromLastAPIResponse([
184882
185004
  summaryResponse
184883
185005
  ]), compactionUsage = getTokenUsage(summaryResponse);
184884
- messagesToKeep.length, messagesToSummarize.length, compactionUsage?.input_tokens, compactionUsage?.output_tokens, compactionUsage?.cache_read_input_tokens, compactionUsage?.cache_creation_input_tokens;
185006
+ messagesToKeep.length, summarizedCount(), compactionUsage?.input_tokens, compactionUsage?.output_tokens, compactionUsage?.cache_read_input_tokens, compactionUsage?.cache_creation_input_tokens;
184885
185007
  let lastPreCompactUuid = direction === "up_to" ? allMessages.slice(0, pivotIndex).findLast((m2) => m2.type !== "progress")?.uuid : messagesToKeep.at(-1)?.uuid, boundaryMarker = createCompactBoundaryMessage(
184886
185008
  "manual",
184887
185009
  preCompactTokenCount ?? 0,
184888
185010
  lastPreCompactUuid,
184889
185011
  userFeedback,
184890
- messagesToSummarize.length
185012
+ // 同族同修:边界标记里的这一位与屏上那一位是**同一个量**,两处读同一个函数,
185013
+ // 否则同一次压缩会在转录里留两个互相矛盾的 N。
185014
+ summarizedCount()
184891
185015
  ), preCompactDiscovered = extractDiscoveredToolNames(allMessages);
184892
185016
  preCompactDiscovered.size > 0 && (boundaryMarker.compactMetadata.preCompactDiscoveredTools = [
184893
185017
  ...preCompactDiscovered
@@ -184898,7 +185022,8 @@ User context: ${userFeedback}` : hookResult.newCustomInstructions ? customInstru
184898
185022
  isCompactSummary: !0,
184899
185023
  ...messagesToKeep.length > 0 ? {
184900
185024
  summarizeMetadata: {
184901
- messagesSummarized: messagesToSummarize.length,
185025
+ // 屏上 "Summarized N messages" 的 N(CompactSummary.tsx)——读真参与摘要的条数。
185026
+ messagesSummarized: summarizedCount(),
184902
185027
  userContext: userFeedback,
184903
185028
  direction
184904
185029
  }
@@ -254620,24 +254745,6 @@ var MCP_TOKEN_COUNT_THRESHOLD_FACTOR, IMAGE_TOKEN_ESTIMATE, DEFAULT_MAX_MCP_OUTP
254620
254745
  }
254621
254746
  });
254622
254747
 
254623
- // build-src/src/sema/untrustedDisplayText.ts
254624
- function cleanUntrustedForDisplay(v2, max2) {
254625
- return String(v2 ?? "").replace(CONTROL_CHARS, ".").replace(BIDI_AND_SEPARATORS, ".").replace(LONE_SURROGATE, ".").slice(0, max2).replace(LONE_SURROGATE, ".");
254626
- }
254627
- function cleanUntrustedKeepLayout(v2) {
254628
- return String(v2 ?? "").replace(CONTROL_CHARS_KEEP_LAYOUT, ".").replace(BIDI_AND_SEPARATORS, ".").replace(LONE_SURROGATE, ".");
254629
- }
254630
- function cleanUntrustedScalar(v2) {
254631
- return String(v2 ?? "").replace(SCALAR_UNSAFE, (ch2) => "\\u" + (ch2.codePointAt(0) ?? 0).toString(16).toUpperCase().padStart(4, "0"));
254632
- }
254633
- var CONTROL_CHARS, BIDI_AND_SEPARATORS, LONE_SURROGATE, CONTROL_CHARS_KEEP_LAYOUT, SCALAR_UNSAFE, init_untrustedDisplayText = __esm({
254634
- "build-src/src/sema/untrustedDisplayText.ts"() {
254635
- CONTROL_CHARS = /[\u0000-\u001f\u007f-\u009f]/g, BIDI_AND_SEPARATORS = /[\u061c\u200e\u200f\u2028\u2029\u202a-\u202e\u2066-\u2069]/g, LONE_SURROGATE = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g;
254636
- CONTROL_CHARS_KEEP_LAYOUT = /[\u0000-\u0008\u000b-\u001f\u007f-\u009f]/g;
254637
- SCALAR_UNSAFE = /[\u0000-\u001F\u007F-\u009F\u061C\u200E\u200F\u2028\u2029\u202A-\u202E\u2066-\u2069]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g;
254638
- }
254639
- });
254640
-
254641
254748
  // build-src/src/tools/MCPTool/UI.tsx
254642
254749
  function renderToolUseMessage2(input, {
254643
254750
  verbose
@@ -280942,7 +281049,7 @@ function FileEditToolUseRejectedMessage(t0) {
280942
281049
  }
280943
281050
  var import_compiler_runtime43, import_jsx_runtime52, MAX_LINES_TO_RENDER, init_FileEditToolUseRejectedMessage = __esm({
280944
281051
  "build-src/src/components/FileEditToolUseRejectedMessage.tsx"() {
280945
- import_compiler_runtime43 = __toESM(require_compiler_runtime(), 1);
281052
+ import_compiler_runtime43 = __toESM(require_compiler_runtime());
280946
281053
  init_useTerminalSize();
280947
281054
  init_cwd();
280948
281055
  init_ink2();
@@ -280950,7 +281057,7 @@ var import_compiler_runtime43, import_jsx_runtime52, MAX_LINES_TO_RENDER, init_F
280950
281057
  init_MessageResponse();
280951
281058
  init_StructuredDiffList();
280952
281059
  init_stringUtils();
280953
- import_jsx_runtime52 = __toESM(require_jsx_runtime(), 1), MAX_LINES_TO_RENDER = 10;
281060
+ import_jsx_runtime52 = __toESM(require_jsx_runtime()), MAX_LINES_TO_RENDER = 10;
280954
281061
  }
280955
281062
  });
280956
281063
 
@@ -292672,21 +292779,21 @@ function createMissLedger() {
292672
292779
  }
292673
292780
  };
292674
292781
  }
292675
- function interpolate(template, key, params, ledger) {
292782
+ function interpolate(template, key, params, ledger2) {
292676
292783
  return template.includes("{") ? template.replace(PLACEHOLDER, (token, name) => {
292677
292784
  let v2 = params?.[name];
292678
- return v2 === void 0 ? (ledger.record(`${key}#${name}`), token) : String(v2);
292785
+ return v2 === void 0 ? (ledger2.record(`${key}#${name}`), token) : String(v2);
292679
292786
  }) : template;
292680
292787
  }
292681
- function translate(lang, key, params, ledger = uiMissLedger) {
292788
+ function translate(lang, key, params, ledger2 = uiMissLedger) {
292682
292789
  let hit = CATALOGS[lang][key];
292683
- if (hit !== void 0) return interpolate(hit, key, params, ledger);
292684
- ledger.record(key);
292790
+ if (hit !== void 0) return interpolate(hit, key, params, ledger2);
292791
+ ledger2.record(key);
292685
292792
  let fallback = CATALOGS.en[key];
292686
- return fallback === void 0 ? "" : interpolate(fallback, key, params, ledger);
292793
+ return fallback === void 0 ? "" : interpolate(fallback, key, params, ledger2);
292687
292794
  }
292688
- function createTranslator(lang, ledger = uiMissLedger) {
292689
- return (key, params) => translate(lang, key, params, ledger);
292795
+ function createTranslator(lang, ledger2 = uiMissLedger) {
292796
+ return (key, params) => translate(lang, key, params, ledger2);
292690
292797
  }
292691
292798
  var uiMissLedger, CATALOGS, PLACEHOLDER, init_translate = __esm({
292692
292799
  "build-src/src/sema/i18n/core/translate.ts"() {
@@ -304351,7 +304458,7 @@ function useClaudeAiLimits() {
304351
304458
  }
304352
304459
  var import_react69, init_claudeAiLimitsHook = __esm({
304353
304460
  "build-src/src/services/claudeAiLimitsHook.ts"() {
304354
- import_react69 = __toESM(require_react());
304461
+ import_react69 = __toESM(require_react(), 1);
304355
304462
  init_claudeAiLimits();
304356
304463
  }
304357
304464
  });
@@ -307953,7 +308060,7 @@ function UserToolErrorMessage(t0) {
307953
308060
  verbose,
307954
308061
  isTranscriptMode
307955
308062
  } = t0, param = normalizeEngineReminderParam(rawParam);
307956
- if (typeof param.content == "string" && (param.content.startsWith(INTERRUPTED_BATCH_FOLD_PREFIX) || param.content.startsWith(REPEATED_NOTICE_FOLD_PREFIX) || param.content.startsWith(REPEATED_ERROR_FOLD_PREFIX)))
308063
+ if (typeof param.content == "string" && (param.content.startsWith(INTERRUPTED_BATCH_FOLD_PREFIX) || param.content.startsWith(REPEATED_NOTICE_FOLD_PREFIX) || param.content.startsWith(REPEATED_ERROR_FOLD_PREFIX) || param.content.startsWith(COLLATERAL_ABORT_FOLD_PREFIX)))
307957
308064
  return /* @__PURE__ */ (0, import_jsx_runtime128.jsx)(MessageResponse, { height: 1, children: /* @__PURE__ */ (0, import_jsx_runtime128.jsx)(ThemedText, { dimColor: !0, children: param.content }) });
307958
308065
  if (typeof param.content == "string" && param.content.includes(INTERRUPT_MESSAGE_FOR_TOOL_USE)) {
307959
308066
  let t12;
@@ -307998,7 +308105,7 @@ function UserToolErrorMessage(t0) {
307998
308105
  isTranscriptMode
307999
308106
  }) ?? /* @__PURE__ */ (0, import_jsx_runtime128.jsx)(FallbackToolUseErrorMessage, { result: param.content, verbose }), $3[7] = isTranscriptMode, $3[8] = param.content, $3[9] = progressMessagesForMessage, $3[10] = tool, $3[11] = tools, $3[12] = verbose, $3[13] = t1) : t1 = $3[13], t1;
308000
308107
  }
308001
- var import_compiler_runtime105, import_jsx_runtime128, INTERRUPTED_BATCH_FOLD_PREFIX, REPEATED_NOTICE_FOLD_PREFIX, REPEATED_ERROR_FOLD_PREFIX, init_UserToolErrorMessage = __esm({
308108
+ var import_compiler_runtime105, import_jsx_runtime128, INTERRUPTED_BATCH_FOLD_PREFIX, REPEATED_NOTICE_FOLD_PREFIX, REPEATED_ERROR_FOLD_PREFIX, COLLATERAL_ABORT_FOLD_PREFIX, init_UserToolErrorMessage = __esm({
308002
308109
  "build-src/src/components/messages/UserToolResultMessage/UserToolErrorMessage.tsx"() {
308003
308110
  import_compiler_runtime105 = __toESM(require_compiler_runtime(), 1);
308004
308111
  init_systemReminderTag();
@@ -308012,7 +308119,7 @@ var import_compiler_runtime105, import_jsx_runtime128, INTERRUPTED_BATCH_FOLD_PR
308012
308119
  init_RejectedPlanMessage();
308013
308120
  init_RejectedToolUseMessage();
308014
308121
  import_jsx_runtime128 = __toESM(require_jsx_runtime(), 1);
308015
- INTERRUPTED_BATCH_FOLD_PREFIX = "Interrupted with the batch: ", REPEATED_NOTICE_FOLD_PREFIX = "Same notice as above \xD7", REPEATED_ERROR_FOLD_PREFIX = "Same error as above \xD7";
308122
+ INTERRUPTED_BATCH_FOLD_PREFIX = "Interrupted with the batch: ", REPEATED_NOTICE_FOLD_PREFIX = "Same notice as above \xD7", REPEATED_ERROR_FOLD_PREFIX = "Same error as above \xD7", COLLATERAL_ABORT_FOLD_PREFIX = "Aborted alongside the pending approval: ";
308016
308123
  }
308017
308124
  });
308018
308125
 
@@ -356411,25 +356518,25 @@ function getSessionMcpConfigLedger(slot) {
356411
356518
  let created = createMcpConfigLedger();
356412
356519
  return sessionConfigLedgers.set(slot, created), created;
356413
356520
  }
356414
- function pinSessionMcpConfigs(fresh, ledger) {
356521
+ function pinSessionMcpConfigs(fresh, ledger2) {
356415
356522
  let configs = {}, changed = [], deferred = [];
356416
356523
  for (let [name, config4] of Object.entries(fresh)) {
356417
- let pinned = ledger.entries.get(name);
356524
+ let pinned = ledger2.entries.get(name);
356418
356525
  if (pinned === void 0) {
356419
- if (ledger.sealed) {
356526
+ if (ledger2.sealed) {
356420
356527
  deferred.push(name);
356421
356528
  continue;
356422
356529
  }
356423
- ledger.entries.set(name, config4), configs[name] = config4;
356530
+ ledger2.entries.set(name, config4), configs[name] = config4;
356424
356531
  continue;
356425
356532
  }
356426
356533
  configs[name] = pinned, hashMcpConfig(pinned) !== hashMcpConfig(config4) && changed.push(name);
356427
356534
  }
356428
- return ledger.sealed = !0, { configs, changed, deferred };
356535
+ return ledger2.sealed = !0, { configs, changed, deferred };
356429
356536
  }
356430
- function syncSessionMcpRevocations(ledger, active2, isDisabled = () => !1) {
356537
+ function syncSessionMcpRevocations(ledger2, active2, isDisabled = () => !1) {
356431
356538
  let revoked = [];
356432
- for (let [name, pinned] of ledger.entries) {
356539
+ for (let [name, pinned] of ledger2.entries) {
356433
356540
  let reason;
356434
356541
  if (active2[name] === void 0 ? reason = "removed-from-config" : isDisabled(name) && (reason = "disabled"), reason === void 0) {
356435
356542
  sessionRevokedServers.delete(name);
@@ -356480,10 +356587,10 @@ function noteEngineSwapWindowStart() {
356480
356587
  function noteEngineSwapWindowEnd() {
356481
356588
  swapInFlightCount = Math.max(0, swapInFlightCount - 1);
356482
356589
  }
356483
- function summarizeEngineRestartInflight(inflight4) {
356484
- let live = (inflight4.bg?.tasks ?? []).filter((t2) => t2.retiredByNotification !== !0), wf = Math.max(0, inflight4.workflows ?? 0), others = Math.max(0, inflight4.otherSessionsMidTurn ?? 0), parts = [];
356485
- if (live.length > 0 && parts.push(`${live.length} background task${live.length === 1 ? "" : "s"} / subagent${live.length === 1 ? "" : "s"}`), wf > 0 && parts.push(`${wf} workflow run${wf === 1 ? "" : "s"}`), inflight4.leaderStreaming === !0 && parts.push("this turn (still streaming)"), others > 0 && parts.push(`${others} other session${others === 1 ? "" : "s"} mid-turn`), parts.length === 0) return null;
356486
- let stale = inflight4.bg && inflight4.bg.fresh === !1 && live.length > 0 ? " (stale fleet view)" : "";
356590
+ function summarizeEngineRestartInflight(inflight3) {
356591
+ let live = (inflight3.bg?.tasks ?? []).filter((t2) => t2.retiredByNotification !== !0), wf = Math.max(0, inflight3.workflows ?? 0), others = Math.max(0, inflight3.otherSessionsMidTurn ?? 0), parts = [];
356592
+ if (live.length > 0 && parts.push(`${live.length} background task${live.length === 1 ? "" : "s"} / subagent${live.length === 1 ? "" : "s"}`), wf > 0 && parts.push(`${wf} workflow run${wf === 1 ? "" : "s"}`), inflight3.leaderStreaming === !0 && parts.push("this turn (still streaming)"), others > 0 && parts.push(`${others} other session${others === 1 ? "" : "s"} mid-turn`), parts.length === 0) return null;
356593
+ let stale = inflight3.bg && inflight3.bg.fresh === !1 && live.length > 0 ? " (stale fleet view)" : "";
356487
356594
  return `\u26A0 ${parts.join(" + ")} in flight will be interrupted${stale}`;
356488
356595
  }
356489
356596
  var swapInFlightCount, init_engineSwapGate = __esm({
@@ -358590,7 +358697,7 @@ function scopeSessionId() {
358590
358697
  return engineSessionParam();
358591
358698
  }
358592
358699
  function createLiveFleetSource(config4, now2 = Date.now()) {
358593
- let t0 = now2, mainName = config4.mainName ?? "main", ledger = createFleetLedger({
358700
+ let t0 = now2, mainName = config4.mainName ?? "main", ledger2 = createFleetLedger({
358594
358701
  onHookNotice: (frame, sessionScoped) => maybeIngestFleetFrame(frame, sessionScoped),
358595
358702
  // #242 批 3:终态兜底腿的 bg 事实源改接包的 accepted 钩子(归属判别通过之后才回调)。
358596
358703
  // 此前壳在 consume 环里自设一道「meta 两位(sessionScoped+bgNotifyFailClosed)都真才记账」的
@@ -358617,7 +358724,7 @@ function createLiveFleetSource(config4, now2 = Date.now()) {
358617
358724
  viewed: !0
358618
358725
  };
358619
358726
  function project2(nowMs = Date.now()) {
358620
- let viewingTaskId = getAppStateStoreRef()?.getState().viewingAgentTaskId, { tasks: tasks3, workflows } = ledger.project(nowMs, {
358727
+ let viewingTaskId = getAppStateStoreRef()?.getState().viewingAgentTaskId, { tasks: tasks3, workflows } = ledger2.project(nowMs, {
358621
358728
  rowFilter: ROW_FILTER,
358622
358729
  ...viewingTaskId !== void 0 ? { viewingTaskId } : {}
358623
358730
  });
@@ -358644,7 +358751,7 @@ function createLiveFleetSource(config4, now2 = Date.now()) {
358644
358751
  let stream5 = client3.fleet.stream({ ...fleetStreamOptions(), signal: conn.signal });
358645
358752
  for await (let frame of stream5) {
358646
358753
  if (disposed4) return;
358647
- if (ledger.setConnected(!0), lastError = null, process.env.SEMA_DEBUG) {
358754
+ if (ledger2.setConnected(!0), lastError = null, process.env.SEMA_DEBUG) {
358648
358755
  if (process.env.SEMA_DEBUG_FILE && frame.type === "task" && frame.row) {
358649
358756
  let r = frame.row;
358650
358757
  try {
@@ -358677,12 +358784,12 @@ function createLiveFleetSource(config4, now2 = Date.now()) {
358677
358784
  }
358678
358785
  if (observeWorkflowFrame(frame), frame.type === "task" && frame.row && observeFleetTaskFrame(frame.row), frame.type === "snapshot" && Array.isArray(frame.tasks))
358679
358786
  for (let snapRow of frame.tasks) observeFleetTaskFrame(snapRow);
358680
- ledger.applyFrame(frame);
358787
+ ledger2.applyFrame(frame);
358681
358788
  }
358682
- ledger.setConnected(!1), lastError = "stream ended (EOF)";
358789
+ ledger2.setConnected(!1), lastError = "stream ended (EOF)";
358683
358790
  } catch (err8) {
358684
358791
  if (disposed4 || abort.signal.aborted) return;
358685
- scopeSessionId() === sessionAtOpen && (ledger.setConnected(!1), lastError = err8 instanceof Error ? err8.message : String(err8), process.env.SEMA_DEBUG && console.error("[sema][fleet] stream error (will reconnect):", lastError));
358792
+ scopeSessionId() === sessionAtOpen && (ledger2.setConnected(!1), lastError = err8 instanceof Error ? err8.message : String(err8), process.env.SEMA_DEBUG && console.error("[sema][fleet] stream error (will reconnect):", lastError));
358686
358793
  } finally {
358687
358794
  clearInterval(watch4), abort.signal.removeEventListener("abort", onGlobalAbort);
358688
358795
  }
@@ -358704,10 +358811,10 @@ function createLiveFleetSource(config4, now2 = Date.now()) {
358704
358811
  return Math.max(0, nowMs - t0);
358705
358812
  },
358706
358813
  dispose() {
358707
- disposed4 = !0, ledger.dispose(), abort.abort();
358814
+ disposed4 = !0, ledger2.dispose(), abort.abort();
358708
358815
  },
358709
358816
  status() {
358710
- let s = ledger.status();
358817
+ let s = ledger2.status();
358711
358818
  return {
358712
358819
  connected: s.connected,
358713
358820
  version: s.version,
@@ -358806,7 +358913,9 @@ __export(engineUpgradeCoordinator_exports, {
358806
358913
  notePendingEngineRestart: () => notePendingEngineRestart,
358807
358914
  pendingEngineRestartKind: () => pendingEngineRestartKind,
358808
358915
  pendingRestartBannerCopy: () => pendingRestartBannerCopy,
358916
+ pendingRestartLaneAvailable: () => pendingRestartLaneAvailable,
358809
358917
  resetUserConfirmedRestartWindowForTests: () => resetUserConfirmedRestartWindowForTests,
358918
+ retractHeartbeatConfigPending: () => retractHeartbeatConfigPending,
358810
358919
  subscribeUpgradeState: () => subscribeUpgradeState
358811
358920
  });
358812
358921
  import { readFileSync as readFileSync28, statSync as statSync9 } from "fs";
@@ -358828,8 +358937,13 @@ function engineSpawnSettingsFingerprint() {
358828
358937
  return "";
358829
358938
  }
358830
358939
  }
358940
+ function mergedPendingKind() {
358941
+ if (pendingCauses.size === 0) return null;
358942
+ for (let k2 of pendingCauses.values()) if (k2 === "config") return "config";
358943
+ return "update";
358944
+ }
358831
358945
  function setPhase(phase, opts) {
358832
- state2 = {
358946
+ phase !== "ready" && pendingCauses.clear(), state2 = {
358833
358947
  phase,
358834
358948
  ...phase === "ready" && opts?.kind ? { kind: opts.kind } : {},
358835
358949
  ...phase === "done" ? { appliedAt: Date.now(), ...opts?.version ? { version: opts.version } : {} } : {}
@@ -358891,8 +359005,36 @@ function noteEngineTurnBoundary() {
358891
359005
  }
358892
359006
  detectPendingFromDisk();
358893
359007
  }
358894
- function notePendingEngineRestart(kind) {
358895
- applying || state2.phase === "ready" && state2.kind === "config" && kind === "update" || state2.phase === "ready" && state2.kind === kind || setPhase("ready", { kind });
359008
+ function notePendingEngineRestart(kind, cause = "disk") {
359009
+ if (restartLedgerTxn) {
359010
+ let q2 = applyQueuedNotes.get(cause);
359011
+ applyQueuedNotes.set(cause, q2 === "config" && kind === "update" ? "config" : kind), applyQueuedRetractions.delete(cause);
359012
+ return;
359013
+ }
359014
+ let prev = pendingCauses.get(cause), effective = prev === "config" && kind === "update" ? "config" : kind, hadSameEntry = prev === effective;
359015
+ pendingCauses.set(cause, effective);
359016
+ let merged = mergedPendingKind() ?? effective;
359017
+ state2.phase === "ready" && state2.kind === merged && hadSameEntry || setPhase("ready", { kind: merged });
359018
+ }
359019
+ function pendingRestartLaneAvailable() {
359020
+ return deps !== null;
359021
+ }
359022
+ function retractHeartbeatConfigPending() {
359023
+ if (restartLedgerTxn) {
359024
+ applyQueuedRetractions.add("heartbeat-config"), applyQueuedNotes.delete("heartbeat-config");
359025
+ return;
359026
+ }
359027
+ if (!pendingCauses.delete("heartbeat-config")) return;
359028
+ let remaining = mergedPendingKind();
359029
+ if (remaining !== null) {
359030
+ logForDebugging(
359031
+ `[engine-upgrade] heartbeat config drift resolved, but other pending causes remain (${[...pendingCauses.keys()].join(", ")}) \u2014 keeping the banner`
359032
+ ), state2.phase === "ready" && state2.kind !== remaining && setPhase("ready", { kind: remaining });
359033
+ return;
359034
+ }
359035
+ state2.phase === "ready" && (logForDebugging(
359036
+ "[engine-upgrade] the engine finished hot-applying the config change that raised this banner \u2014 retracting the pending restart (nothing left to apply)"
359037
+ ), setPhase("idle"));
358896
359038
  }
358897
359039
  function pendingEngineRestartKind() {
358898
359040
  return state2.phase === "ready" ? state2.kind ?? "update" : null;
@@ -358901,6 +359043,8 @@ async function applyPendingEngineRestart() {
358901
359043
  if (!deps || applying) return "unchanged";
358902
359044
  let d4 = deps, kindBefore = pendingEngineRestartKind();
358903
359045
  if (kindBefore === null) return "unchanged";
359046
+ let causesBefore = new Map(pendingCauses);
359047
+ applyQueuedNotes.clear(), applyQueuedRetractions.clear(), restartLedgerTxn = !0;
358904
359048
  let killedSnapshot = [];
358905
359049
  try {
358906
359050
  killedSnapshot = (d4.readBgTasks ?? (await Promise.resolve().then(() => (init_fleetClient(), fleetClient_exports))).readEngineActiveBgTasks)().tasks.filter((t2) => t2.retiredByNotification !== !0);
@@ -358924,7 +359068,12 @@ async function applyPendingEngineRestart() {
358924
359068
  `[engine-upgrade] user-confirmed restart moved the engine endpoint (${baseUrlBefore} -> ${baseUrlAfter}) \u2014 fixed-port expectation broken; other attached shells still point at the old one`
358925
359069
  ), !ok2) {
358926
359070
  let stillAlive = await engineStillAlive(instanceBefore);
358927
- if (setPhase("ready", { kind: kindBefore }), stillAlive) return "unchanged";
359071
+ for (let [cause, kind] of causesBefore) pendingCauses.has(cause) || pendingCauses.set(cause, kind);
359072
+ for (let [cause, kind] of applyQueuedNotes) pendingCauses.set(cause, kind);
359073
+ for (let cause of applyQueuedRetractions) pendingCauses.delete(cause);
359074
+ if (applyQueuedNotes.clear(), applyQueuedRetractions.clear(), restartLedgerTxn = !1, mergedPendingKind() === null ? (logForDebugging(
359075
+ "[engine-upgrade] the confirmed restart did not go through, but every pending cause resolved while it ran \u2014 no banner to restore"
359076
+ ), setPhase("idle")) : setPhase("ready", { kind: mergedPendingKind() ?? kindBefore }), stillAlive) return "unchanged";
358928
359077
  if (killedSnapshot.length > 0) {
358929
359078
  let notify5 = d4.notifyKilled ?? synthesizeKilledNotifications;
358930
359079
  try {
@@ -358956,6 +359105,10 @@ async function applyPendingEngineRestart() {
358956
359105
  } catch {
358957
359106
  }
358958
359107
  }
359108
+ let carryCatalog = applyQueuedNotes.get("catalog");
359109
+ restartLedgerTxn = !1, applyQueuedNotes.clear(), applyQueuedRetractions.clear(), carryCatalog !== void 0 && (logForDebugging(
359110
+ "[engine-upgrade] a model-catalog change landed while the confirmed restart was running \u2014 re-arming the banner (models.json is outside the fingerprint, so we cannot prove the new engine picked it up)"
359111
+ ), notePendingEngineRestart(carryCatalog, "catalog"));
358959
359112
  let nowFingerprint = fingerprint(d4.entryPath);
358960
359113
  return nowFingerprint !== null && appliedFingerprint !== null && nowFingerprint !== appliedFingerprint && (logForDebugging(
358961
359114
  "[engine-upgrade] configuration changed again while the confirmed restart was running \u2014 re-arming the pending banner (the new engine does not have it)"
@@ -359028,7 +359181,7 @@ async function classifyStreamTear() {
359028
359181
  let r = await sdkProbeHealth3(base, 2e3);
359029
359182
  return r.alive ? typeof r.health.instanceId == "string" && r.health.instanceId !== before ? "restarted" : "not-restart" : "engine-down";
359030
359183
  }
359031
- var deps, baseline, turnRefs, state2, applying, listeners7, doneFadeTimer, swapOpSeq, activeSwapOp, USER_RESTART_GRACE_MS, userRestartDepth, userRestartUntil, USER_RESTART_TRANSCRIPT_LINE, init_engineUpgradeCoordinator = __esm({
359184
+ var deps, baseline, turnRefs, state2, applying, listeners7, pendingCauses, applyQueuedNotes, applyQueuedRetractions, restartLedgerTxn, doneFadeTimer, swapOpSeq, activeSwapOp, USER_RESTART_GRACE_MS, userRestartDepth, userRestartUntil, USER_RESTART_TRANSCRIPT_LINE, init_engineUpgradeCoordinator = __esm({
359032
359185
  "build-src/src/sema/engineUpgradeCoordinator.ts"() {
359033
359186
  init_envUtils();
359034
359187
  init_engineReadFace();
@@ -359037,6 +359190,7 @@ var deps, baseline, turnRefs, state2, applying, listeners7, doneFadeTimer, swapO
359037
359190
  init_dist();
359038
359191
  init_engineSwapGate();
359039
359192
  deps = null, baseline = null, turnRefs = 0, state2 = { phase: "idle" }, applying = !1, listeners7 = /* @__PURE__ */ new Set();
359193
+ pendingCauses = /* @__PURE__ */ new Map(), applyQueuedNotes = /* @__PURE__ */ new Map(), applyQueuedRetractions = /* @__PURE__ */ new Set(), restartLedgerTxn = !1;
359040
359194
  doneFadeTimer = null, swapOpSeq = 0, activeSwapOp = null;
359041
359195
  USER_RESTART_GRACE_MS = 2e4, userRestartDepth = 0, userRestartUntil = 0;
359042
359196
  USER_RESTART_TRANSCRIPT_LINE = "Engine restarted (user-confirmed) \u2014 press \u2191 to resend an interrupted prompt.";
@@ -359530,6 +359684,128 @@ var nextTurnId, activeTurnId, heldTurnIds, lostTurnIds, MAX_HELD_TURNS, init_inj
359530
359684
  }
359531
359685
  });
359532
359686
 
359687
+ // build-src/src/sema/terminationIntentLedger.ts
359688
+ function ttlMs() {
359689
+ return ttlOverrideMs ?? DEFAULT_TTL_MS;
359690
+ }
359691
+ function purgeExpired(now2) {
359692
+ let window2 = ttlMs();
359693
+ for (let [taskId, row2] of ledger)
359694
+ now2 - row2.at >= window2 && ledger.delete(taskId);
359695
+ }
359696
+ function recordTerminationIntent(taskId, source) {
359697
+ if (typeof taskId != "string" || taskId.length === 0) return;
359698
+ let now2 = Date.now();
359699
+ purgeExpired(now2), ledger.set(taskId, { at: now2, source });
359700
+ }
359701
+ function wasRecentlyTerminatedByUs(taskId) {
359702
+ if (typeof taskId != "string" || taskId.length === 0) return !1;
359703
+ let now2 = Date.now();
359704
+ return purgeExpired(now2), ledger.has(taskId);
359705
+ }
359706
+ function terminationIntentSource(taskId) {
359707
+ return typeof taskId != "string" || taskId.length === 0 ? null : (purgeExpired(Date.now()), ledger.get(taskId)?.source ?? null);
359708
+ }
359709
+ function armTerminationIntentOnAbort(signal, taskId) {
359710
+ if (signal === void 0 || typeof taskId != "string" || taskId.length === 0) return;
359711
+ let record2 = () => {
359712
+ signal.reason !== "background" && recordTerminationIntent(taskId, "esc-abort");
359713
+ };
359714
+ if (signal.aborted) {
359715
+ record2();
359716
+ return;
359717
+ }
359718
+ signal.addEventListener("abort", record2, { once: !0 });
359719
+ }
359720
+ function forgetTerminationIntent(taskId) {
359721
+ typeof taskId != "string" || taskId.length === 0 || ledger.delete(taskId);
359722
+ }
359723
+ function readStatus2(row2) {
359724
+ let s = row2?.status;
359725
+ return typeof s == "string" && s.length > 0 ? s : null;
359726
+ }
359727
+ function defaultSleep(ms, signal) {
359728
+ return new Promise((resolve57) => {
359729
+ if (signal?.aborted === !0) {
359730
+ resolve57();
359731
+ return;
359732
+ }
359733
+ let timer3 = setTimeout(() => {
359734
+ signal?.removeEventListener("abort", onAbort), resolve57();
359735
+ }, ms);
359736
+ function onAbort() {
359737
+ clearTimeout(timer3), resolve57();
359738
+ }
359739
+ signal?.addEventListener("abort", onAbort, { once: !0 });
359740
+ });
359741
+ }
359742
+ function anySignal(a, b3) {
359743
+ if (a === void 0) return b3;
359744
+ if (typeof AbortSignal.any == "function") return AbortSignal.any([a, b3]);
359745
+ let ac = new AbortController(), forward = (s) => ac.abort(s.reason);
359746
+ return a.aborted ? forward(a) : a.addEventListener("abort", () => forward(a), { once: !0 }), b3.aborted ? forward(b3) : b3.addEventListener("abort", () => forward(b3), { once: !0 }), ac.signal;
359747
+ }
359748
+ async function awaitInterruptedRunSettle(taskId, deps2) {
359749
+ let getRun = deps2.getRun;
359750
+ if (typeof getRun != "function") return { kind: "unknown" };
359751
+ if (typeof taskId != "string" || taskId.length === 0) return { kind: "unknown" };
359752
+ let budgetMs = deps2.budgetMs ?? settleBudgetOverrideMs ?? SETTLE_BUDGET_MS, intervalMs = deps2.intervalMs ?? settlePollOverrideMs ?? SETTLE_POLL_INTERVAL_MS, started2 = Date.now(), sawRunning = !1, isAborted3 = () => deps2.signal?.aborted === !0, budgetAc = new AbortController(), budgetSpent = !1, markStopped = () => {
359753
+ }, stopped = new Promise((resolve57) => {
359754
+ markStopped = () => resolve57(PROBE_STOPPED);
359755
+ }), onCallerAbort = () => markStopped(), budgetTimer = setTimeout(() => {
359756
+ budgetSpent = !0, budgetAc.abort(), markStopped();
359757
+ }, budgetMs);
359758
+ deps2.signal?.addEventListener("abort", onCallerAbort, { once: !0 }), isAborted3() && markStopped();
359759
+ let probeSignal = anySignal(deps2.signal, budgetAc.signal);
359760
+ try {
359761
+ for (; ; ) {
359762
+ if (isAborted3()) return { kind: "unknown" };
359763
+ if (budgetSpent) break;
359764
+ let probe3 = getRun(taskId, {
359765
+ signal: probeSignal
359766
+ }).then(
359767
+ (row2) => row2,
359768
+ () => PROBE_FAILED
359769
+ ), outcome = await Promise.race([probe3, stopped]);
359770
+ if (isAborted3()) return { kind: "unknown" };
359771
+ let status3 = outcome === PROBE_STOPPED || outcome === PROBE_FAILED ? null : readStatus2(outcome);
359772
+ if (status3 !== null) {
359773
+ if (CLAIM_RELEASED_STATES.includes(status3)) return { kind: "settled", status: status3 };
359774
+ if (PARK_STATES.includes(status3)) return { kind: "parked", status: status3 };
359775
+ status3 === "running" && (sawRunning = !0);
359776
+ }
359777
+ if (budgetSpent) break;
359778
+ let left = started2 + budgetMs - Date.now();
359779
+ if (left <= 0) break;
359780
+ if (await defaultSleep(Math.min(intervalMs, left), probeSignal), isAborted3()) return { kind: "unknown" };
359781
+ }
359782
+ return isAborted3() ? { kind: "unknown" } : sawRunning ? { kind: "still-running", waitedMs: Math.max(0, Date.now() - started2) } : { kind: "unknown" };
359783
+ } finally {
359784
+ clearTimeout(budgetTimer);
359785
+ try {
359786
+ deps2.signal?.removeEventListener("abort", onCallerAbort);
359787
+ } catch {
359788
+ }
359789
+ }
359790
+ }
359791
+ function interruptedRunSettleRow(taskId, verdict) {
359792
+ if (verdict.kind === "settled")
359793
+ return `The turn you interrupted has finished stopping on the engine (run ${taskId}), so sema is sending your message now as a new turn.`;
359794
+ if (verdict.kind === "still-running") {
359795
+ let secs = Math.max(1, Math.round(verdict.waitedMs / 1e3));
359796
+ return `The turn you interrupted is still finishing up on the engine (run ${taskId}), so your message was NOT sent \u2014 a session runs one turn at a time. sema waited ${String(secs)}s for that run to stop and does not send your message automatically after that: send it again in a moment.`;
359797
+ }
359798
+ return null;
359799
+ }
359800
+ var DEFAULT_TTL_MS, ledger, ttlOverrideMs, SETTLE_BUDGET_MS, SETTLE_POLL_INTERVAL_MS, settleBudgetOverrideMs, settlePollOverrideMs, PARK_STATES, PROBE_STOPPED, PROBE_FAILED, init_terminationIntentLedger = __esm({
359801
+ "build-src/src/sema/terminationIntentLedger.ts"() {
359802
+ init_dist();
359803
+ DEFAULT_TTL_MS = 6e4, ledger = /* @__PURE__ */ new Map(), ttlOverrideMs = null;
359804
+ SETTLE_BUDGET_MS = 1e4, SETTLE_POLL_INTERVAL_MS = 1e3, settleBudgetOverrideMs = null, settlePollOverrideMs = null, PARK_STATES = ["suspended", "needs_review"];
359805
+ PROBE_STOPPED = /* @__PURE__ */ Symbol("sema.interruptedSettleProbeStopped"), PROBE_FAILED = /* @__PURE__ */ Symbol("sema.interruptedSettleProbeFailed");
359806
+ }
359807
+ });
359808
+
359533
359809
  // build-src/src/sema/engineAttachCapabilityGate.ts
359534
359810
  var engineAttachCapabilityGate_exports = {};
359535
359811
  __export(engineAttachCapabilityGate_exports, {
@@ -359627,6 +359903,25 @@ var lastRecord, init_engineAttachCapabilityGate = __esm({
359627
359903
  }
359628
359904
  });
359629
359905
 
359906
+ // build-src/src/sema/engineConfigDriftGate.ts
359907
+ function readOrdinal(v2) {
359908
+ return typeof v2 == "number" && Number.isFinite(v2) && v2 >= 0 ? v2 : void 0;
359909
+ }
359910
+ function decideConfigDriftVerdict(input) {
359911
+ let { baselineConfigHash, baselineInstanceId, health } = input, nowHash = typeof health?.configHash == "string" ? health.configHash : void 0;
359912
+ if (!baselineConfigHash || !nowHash) return "skip";
359913
+ if (nowHash === baselineConfigHash) return "in-sync";
359914
+ if (health?.restartRequired === !0) return "ask";
359915
+ let nowInstance = typeof health?.instanceId == "string" ? health.instanceId : void 0;
359916
+ if (!baselineInstanceId || !nowInstance || nowInstance !== baselineInstanceId) return "ask";
359917
+ let target = readOrdinal(health?.configTargetOrdinal), applied = readOrdinal(health?.configAppliedOrdinal);
359918
+ return target === void 0 || applied === void 0 ? "ask" : target === applied ? "advance-baseline" : "ask";
359919
+ }
359920
+ var init_engineConfigDriftGate = __esm({
359921
+ "build-src/src/sema/engineConfigDriftGate.ts"() {
359922
+ }
359923
+ });
359924
+
359630
359925
  // build-src/src/sema/engineLogSweep.ts
359631
359926
  import { readdirSync as readdirSync8, rmSync as rmSync5, statSync as statSync10 } from "node:fs";
359632
359927
  import { basename as basename36, join as join119 } from "node:path";
@@ -361000,8 +361295,8 @@ async function reapStaleEngine(portFile, opts) {
361000
361295
  async function reapAnchoredEngineForUpdate() {
361001
361296
  let existing = readPortFile(getEnginePortFilePath());
361002
361297
  if (!existing || !isProcessAlive(existing.pid)) return { status: "none", midTurn: 0 };
361003
- let midTurn = otherSessionsMidTurn(), inflight4 = activeTurnInflight();
361004
- return midTurn > 0 || inflight4 !== null ? { status: "busy", midTurn: midTurn > 0 ? midTurn : 1 } : (await reapStaleEngine(existing, { killPid: !0 }), { status: "reaped", midTurn: 0 });
361298
+ let midTurn = otherSessionsMidTurn(), inflight3 = activeTurnInflight();
361299
+ return midTurn > 0 || inflight3 !== null ? { status: "busy", midTurn: midTurn > 0 ? midTurn : 1 } : (await reapStaleEngine(existing, { killPid: !0 }), { status: "reaped", midTurn: 0 });
361005
361300
  }
361006
361301
  function pinnedEnginePort() {
361007
361302
  let override = process.env.SEMA_ENGINE_PORT;
@@ -361094,16 +361389,16 @@ async function initEngineLifecycleInner(opts) {
361094
361389
  );
361095
361390
  let sourceStale = (existing.configSource ?? "local") !== engineConfigSource, desiredPort = pinnedEnginePort(), portStale = desiredPort !== null && existing.port !== desiredPort, pidStale = health2 !== null && typeof health2.pid == "number" && health2.pid !== existing.pid, identityOk = health2 !== null && !pidStale && healthIdentityMatches(health2, expectedDataRoot), upgradeDeferred = !1;
361096
361391
  if (identityOk && (versionStale || sourceStale)) {
361097
- let midTurn = otherSessionsMidTurn(), inflight4 = activeTurnInflight();
361098
- (midTurn > 0 || inflight4 !== null) && (upgradeDeferred = !0, logForDebugging(
361099
- `[engine-lifecycle] engine is ${versionStale ? "version-stale" : "config-source-stale"} but ${midTurn} local session(s) are mid-turn${inflight4 ? ` (turn-inflight marker pid=${inflight4.pid})` : ""} \u2014 deferring the reap, reusing the running engine (the upgrade applies on a later launch when no turn is in flight)`
361392
+ let midTurn = otherSessionsMidTurn(), inflight3 = activeTurnInflight();
361393
+ (midTurn > 0 || inflight3 !== null) && (upgradeDeferred = !0, logForDebugging(
361394
+ `[engine-lifecycle] engine is ${versionStale ? "version-stale" : "config-source-stale"} but ${midTurn} local session(s) are mid-turn${inflight3 ? ` (turn-inflight marker pid=${inflight3.pid})` : ""} \u2014 deferring the reap, reusing the running engine (the upgrade applies on a later launch when no turn is in flight)`
361100
361395
  ));
361101
361396
  }
361102
361397
  let forceFresh = opts?.forceFreshEngine === !0, engineCompatible = !forceFresh && identityOk && (!versionStale && !sourceStale || upgradeDeferred), portMoveDeferred = !1;
361103
361398
  if (engineCompatible && portStale) {
361104
- let midTurn = otherSessionsMidTurn(), inflight4 = midTurn > 0 ? null : activeTurnInflight();
361105
- (midTurn > 0 || inflight4 !== null) && (portMoveDeferred = !0, logForDebugging(
361106
- `[engine-lifecycle] port-config mismatch (anchor port=${existing.port} != configured ${desiredPort}) but ${midTurn} local session(s) are mid-turn${inflight4 ? ` (turn-inflight marker pid=${inflight4.pid})` : ""} \u2014 deferring the restart, reusing the engine on port ${existing.port} (the port moves on a later launch when no turn is in flight)`
361399
+ let midTurn = otherSessionsMidTurn(), inflight3 = midTurn > 0 ? null : activeTurnInflight();
361400
+ (midTurn > 0 || inflight3 !== null) && (portMoveDeferred = !0, logForDebugging(
361401
+ `[engine-lifecycle] port-config mismatch (anchor port=${existing.port} != configured ${desiredPort}) but ${midTurn} local session(s) are mid-turn${inflight3 ? ` (turn-inflight marker pid=${inflight3.pid})` : ""} \u2014 deferring the restart, reusing the engine on port ${existing.port} (the port moves on a later launch when no turn is in flight)`
361107
361402
  ));
361108
361403
  }
361109
361404
  if (engineCompatible && (!portStale || portMoveDeferred)) {
@@ -361343,7 +361638,7 @@ function sleep7(ms) {
361343
361638
  return new Promise((resolve57) => setTimeout(resolve57, ms));
361344
361639
  }
361345
361640
  function startHealthCheckLoop(instance2, onSignal) {
361346
- let misses = 0, fired2 = !1, versionDriftBeats = 0, newerEngineLogged = !1, configDriftReported = !1, versionDriftReported = !1, baselineConfigHash = instance2.configHash, timer3 = setInterval(() => {
361641
+ let misses = 0, fired2 = !1, versionDriftBeats = 0, newerEngineLogged = !1, configDriftReported = !1, versionDriftReported = !1, baselineConfigHash = instance2.configHash, baselineInstanceId = instance2.instanceId, timer3 = setInterval(() => {
361347
361642
  (async () => {
361348
361643
  if (fired2) return;
361349
361644
  let health = await probeHealth(instance2.port);
@@ -361353,12 +361648,13 @@ function startHealthCheckLoop(instance2, onSignal) {
361353
361648
  ), onSignal("engineDead"));
361354
361649
  return;
361355
361650
  }
361356
- if (misses = 0, baselineConfigHash && health.configHash) {
361357
- let drifted = health.configHash !== baselineConfigHash;
361358
- drifted && !configDriftReported ? (configDriftReported = !0, logForDebugging(
361359
- `[engine-lifecycle] heartbeat: configHash drift (${baselineConfigHash} \u2192 ${health.configHash}) \u2192 configDrift (pending user confirmation; heartbeat keeps running)`
361360
- ), onSignal("configDrift")) : !drifted && configDriftReported && (configDriftReported = !1);
361361
- }
361651
+ misses = 0;
361652
+ let verdict = decideConfigDriftVerdict({ baselineConfigHash, baselineInstanceId, health });
361653
+ verdict === "ask" && !configDriftReported ? (configDriftReported = !0, logForDebugging(
361654
+ `[engine-lifecycle] heartbeat: configHash drift (${String(baselineConfigHash)} \u2192 ${String(health.configHash)}) with an UNAPPLIED change (config apply ordinals not converged, or the endpoint is answered by a different instance) \u2192 configDrift (pending user confirmation; heartbeat keeps running)`
361655
+ ), onSignal("configDrift")) : verdict === "advance-baseline" ? (logForDebugging(
361656
+ `[engine-lifecycle] heartbeat: configHash drift (${String(baselineConfigHash)} \u2192 ${String(health.configHash)}) is already HOT-APPLIED (same instance, config apply ordinals converged) \u2014 advancing the baseline, no restart prompt`
361657
+ ), baselineConfigHash = health.configHash, configDriftReported && (configDriftReported = !1, onSignal("configDriftResolved"))) : verdict === "in-sync" && configDriftReported && (configDriftReported = !1, onSignal("configDriftResolved"));
361362
361658
  let want = localEngineVersion();
361363
361659
  if (want !== void 0 && health.version && health.version === want && versionDriftReported && (versionDriftReported = !1), want !== void 0 && health.version && health.version !== want && !fired2) {
361364
361660
  if (!localDistNewerThanEngine(want, health.version)) {
@@ -361692,6 +361988,7 @@ var PORT_FILE_VERSION, HEALTH_POLL_INTERVAL_MS, HEALTH_POLL_MAX_ATTEMPTS, HEALTH
361692
361988
  init_engineRuntimeStatus();
361693
361989
  init_engineAttachCapabilityGate();
361694
361990
  init_engineReadFace();
361991
+ init_engineConfigDriftGate();
361695
361992
  init_engineLogSweep();
361696
361993
  init_lockfile();
361697
361994
  init_debug();
@@ -362347,27 +362644,6 @@ var init_defaultModelWriter = __esm({
362347
362644
  }
362348
362645
  });
362349
362646
 
362350
- // build-src/src/sema/engineEndpointSwap.ts
362351
- var engineEndpointSwap_exports = {};
362352
- __export(engineEndpointSwap_exports, {
362353
- registerEngineConfigRespawn: () => registerEngineConfigRespawn,
362354
- requestEngineConfigRespawn: () => requestEngineConfigRespawn
362355
- });
362356
- function registerEngineConfigRespawn(fn2) {
362357
- respawnFn = fn2;
362358
- }
362359
- async function requestEngineConfigRespawn() {
362360
- return respawnFn ? (inflight2 || (inflight2 = respawnFn().finally(() => {
362361
- inflight2 = null;
362362
- })), inflight2) : !1;
362363
- }
362364
- var respawnFn, inflight2, init_engineEndpointSwap = __esm({
362365
- "build-src/src/sema/engineEndpointSwap.ts"() {
362366
- respawnFn = null;
362367
- inflight2 = null;
362368
- }
362369
- });
362370
-
362371
362647
  // build-src/src/sema/modelEndpointSwitch.ts
362372
362648
  var modelEndpointSwitch_exports = {};
362373
362649
  __export(modelEndpointSwitch_exports, {
@@ -362375,6 +362651,15 @@ __export(modelEndpointSwitch_exports, {
362375
362651
  ensureEngineServesModel: () => ensureEngineServesModel,
362376
362652
  poolEntryForModelRef: () => poolEntryForModelRef
362377
362653
  });
362654
+ function warnCrossEndpointResidual(entry, instanceId, extra) {
362655
+ if (instanceId !== void 0) {
362656
+ let key = JSON.stringify([instanceId, entry.id, servedEndpointFor(entry)]);
362657
+ if (warnedCrossEndpointEntries.has(key)) return;
362658
+ warnedCrossEndpointEntries.add(key);
362659
+ }
362660
+ let line = `Model "${entry.id}" lives on a different upstream endpoint (${entry.baseUrl}) and this engine cannot route it per-model. ${extra ?? "It is saved as the default, but the running engine still serves the previous endpoint"} \u2014 ${pendingRestartLaneAvailable() ? "press ctrl+u to restart the engine and apply it" : "it takes effect the next time a local engine is spawned"}. Until then this session's turns keep going to the previously configured provider.`;
362661
+ surfaceTranscriptSystemNotice(line) || console.error(`[sema] ${line}`);
362662
+ }
362378
362663
  function engineBootEnv() {
362379
362664
  let out6 = {};
362380
362665
  for (let k2 of Object.keys(process.env)) {
@@ -362386,10 +362671,13 @@ function engineBootEnv() {
362386
362671
  function poolEntryForModelRef(ref, pool = readModelPool()) {
362387
362672
  return pool.find((e) => e.id === ref) ?? pool.find((e) => e.modelId === ref);
362388
362673
  }
362674
+ function servedEndpointFor(entry, env6 = engineBootEnv()) {
362675
+ return entry.api === "anthropic-messages" ? norm(env6.ANTHROPIC_BASE_URL ?? env6.ANTHROPIC_BASEURL) : norm(env6.MODEL_GATEWAY_BASEURL);
362676
+ }
362389
362677
  function endpointSwitchNeeded(entry, env6 = engineBootEnv()) {
362390
362678
  if (entry.baseUrl.replace(/\/+$/, "") === "") return !1;
362391
362679
  let want = buildModelEnv({ defaultModel: toCatalogEntry(entry) });
362392
- return entry.api === "anthropic-messages" ? norm(want.ANTHROPIC_BASE_URL) !== norm(env6.ANTHROPIC_BASE_URL ?? env6.ANTHROPIC_BASEURL) : norm(want.MODEL_GATEWAY_BASEURL) !== norm(env6.MODEL_GATEWAY_BASEURL);
362680
+ return (entry.api === "anthropic-messages" ? norm(want.ANTHROPIC_BASE_URL) : norm(want.MODEL_GATEWAY_BASEURL)) !== servedEndpointFor(entry, env6);
362393
362681
  }
362394
362682
  function versionGte(v2, min) {
362395
362683
  let m2 = v2 ? /^(\d+)\.(\d+)\.(\d+)/.exec(v2) : null;
@@ -362400,16 +362688,20 @@ function versionGte(v2, min) {
362400
362688
  async function engineRoutesEntryItself(entry) {
362401
362689
  try {
362402
362690
  let u = new URL(entry.baseUrl);
362403
- if (u.protocol !== "http:" && u.protocol !== "https:") return !1;
362691
+ if (u.protocol !== "http:" && u.protocol !== "https:") return { instant: !1 };
362404
362692
  } catch {
362405
- return !1;
362693
+ return { instant: !1 };
362406
362694
  }
362407
- let { probeLocalEngineHealth: probeLocalEngineHealth2 } = await Promise.resolve().then(() => (init_engineLifecycleManager(), engineLifecycleManager_exports)), health = await probeLocalEngineHealth2();
362408
- if (!versionGte(health?.version, PER_MODEL_BASEURL_MIN)) return !1;
362695
+ let { probeLocalEngineHealth: probeLocalEngineHealth2 } = await Promise.resolve().then(() => (init_engineLifecycleManager(), engineLifecycleManager_exports)), health = await probeLocalEngineHealth2(), instanceId = typeof health?.instanceId == "string" ? health.instanceId : void 0;
362696
+ if (!versionGte(health?.version, PER_MODEL_BASEURL_MIN)) return { instant: !1, instanceId };
362409
362697
  let models = getLiveModelCatalog()?.models;
362410
- return models ? models.some((m2) => m2.name === entry.id || entry.modelId !== "" && m2.id === entry.modelId) : !1;
362698
+ return models ? {
362699
+ instant: models.some((m2) => m2.name === entry.id || entry.modelId !== "" && m2.id === entry.modelId),
362700
+ instanceId
362701
+ } : { instant: !1, instanceId };
362411
362702
  }
362412
362703
  async function ensureEngineServesModel(ref) {
362704
+ let crossEndpointRisk = null, engineInstanceId;
362413
362705
  try {
362414
362706
  let { hasManageableLocalEngine: hasManageableLocalEngine2 } = await Promise.resolve().then(() => (init_engineLifecycleManager(), engineLifecycleManager_exports));
362415
362707
  if (!hasManageableLocalEngine2()) return { switched: !1 };
@@ -362424,7 +362716,8 @@ async function ensureEngineServesModel(ref) {
362424
362716
  `[sema][model-endpoint] boot-readback echo of catalog default ${entry.id} \u2014 no persist, no respawn (S3 discipline)`
362425
362717
  ), { switched: !1 };
362426
362718
  }
362427
- let instant = await engineRoutesEntryItself(entry);
362719
+ let routed = await engineRoutesEntryItself(entry), instant = routed.instant;
362720
+ engineInstanceId = routed.instanceId, needsEndpoint && !instant && (crossEndpointRisk = entry);
362428
362721
  {
362429
362722
  let session2 = getSessionModelLatch();
362430
362723
  if (typeof session2 == "string" && session2.length > 0 && (session2 === ref || entry.id === session2 || entry.modelId !== "" && entry.modelId === session2) && (instant || !needsEndpoint))
@@ -362433,28 +362726,31 @@ async function ensureEngineServesModel(ref) {
362433
362726
  ), { switched: !1 };
362434
362727
  }
362435
362728
  let w2 = persistDefaultModelSelection(entry.id);
362436
- if (w2.error) return { switched: !1, error: w2.error };
362437
- if (instant || !needsEndpoint)
362438
- return process.env.SEMA_DEBUG && console.error(
362439
- `[sema][model-endpoint] ${instant ? "engine routes it per-model" : "same endpoint"}: ${entry.id} (${entry.api} @ ${entry.baseUrl}) \u2014 default persisted (env + top-level model), respawn skipped`
362440
- ), { switched: !1 };
362441
- let ok2 = await requestEngineConfigRespawn();
362442
- return process.env.SEMA_DEBUG && console.error(
362443
- `[sema][model-endpoint] switched main \u2192 ${entry.id} (${entry.api} @ ${entry.baseUrl}) \xB7 engine respawn ${ok2 ? "ok" : "unavailable"}`
362444
- ), { switched: ok2 };
362729
+ return w2.error ? (needsEndpoint && !instant && warnCrossEndpointResidual(
362730
+ entry,
362731
+ engineInstanceId,
362732
+ "Saving it as the default FAILED, and the running engine serves the previous endpoint"
362733
+ ), { switched: !1, error: w2.error }) : instant || !needsEndpoint ? (process.env.SEMA_DEBUG && console.error(
362734
+ `[sema][model-endpoint] ${instant ? "engine routes it per-model" : "same endpoint"}: ${entry.id} (${entry.api} @ ${entry.baseUrl}) \u2014 default persisted (env + top-level model), respawn skipped`
362735
+ ), { switched: !1 }) : (pendingRestartLaneAvailable() && notePendingEngineRestart("config", "catalog"), warnCrossEndpointResidual(entry, engineInstanceId), { switched: !1 });
362445
362736
  } catch (e) {
362737
+ try {
362738
+ crossEndpointRisk !== null && warnCrossEndpointResidual(crossEndpointRisk, engineInstanceId, "Switching the default FAILED");
362739
+ } catch {
362740
+ }
362446
362741
  return { switched: !1, error: e };
362447
362742
  }
362448
362743
  }
362449
- var norm, PER_MODEL_BASEURL_MIN, init_modelEndpointSwitch = __esm({
362744
+ var norm, warnedCrossEndpointEntries, PER_MODEL_BASEURL_MIN, init_modelEndpointSwitch = __esm({
362450
362745
  "build-src/src/sema/modelEndpointSwitch.ts"() {
362451
362746
  init_modelChannels();
362452
362747
  init_rosterStore();
362453
362748
  init_defaultModelWriter();
362454
362749
  init_dist();
362455
- init_engineEndpointSwap();
362750
+ init_engineUpgradeCoordinator();
362751
+ init_transcriptSystemNotice();
362456
362752
  init_applyOnboard();
362457
- norm = (u) => (u ?? "").replace(/\/+$/, "");
362753
+ norm = (u) => (u ?? "").replace(/\/+$/, ""), warnedCrossEndpointEntries = /* @__PURE__ */ new Set();
362458
362754
  PER_MODEL_BASEURL_MIN = [1, 128, 0];
362459
362755
  }
362460
362756
  });
@@ -362463,6 +362759,9 @@ var norm, PER_MODEL_BASEURL_MIN, init_modelEndpointSwitch = __esm({
362463
362759
  var seamQuery_exports = {};
362464
362760
  __export(seamQuery_exports, {
362465
362761
  SCENARIO_KEYS: () => SCENARIO_KEYS,
362762
+ _resetInteractiveCancelStateForTest: () => _resetInteractiveCancelStateForTest,
362763
+ _setInteractiveCancelTimeoutMsForTest: () => _setInteractiveCancelTimeoutMsForTest,
362764
+ bestEffortInteractiveCancel: () => bestEffortInteractiveCancel,
362466
362765
  canUseTool: () => canUseTool,
362467
362766
  cancelEngineRun: () => cancelEngineRun,
362468
362767
  drainingRetryDelayMs: () => drainingRetryDelayMs2,
@@ -362907,7 +363206,7 @@ Fix: run \`sema doctor\` to diagnose, or restart sema to retry.`
362907
363206
  } catch {
362908
363207
  }
362909
363208
  noteEngineTurnStart();
362910
- let setInProgress = params.toolUseContext?.setInProgressToolUseIDs, engineOpenToolIds = /* @__PURE__ */ new Set();
363209
+ let setInProgress = params.toolUseContext?.setInProgressToolUseIDs, engineOpenToolIds = /* @__PURE__ */ new Set(), foregroundRunRegistered = null;
362911
363210
  try {
362912
363211
  let sessionId = req.sessionId ?? mockClientIds.sessionId;
362913
363212
  try {
@@ -362966,18 +363265,21 @@ Fix: run \`sema doctor\` to diagnose, or restart sema to retry.`
362966
363265
  }
362967
363266
  }
362968
363267
  }
362969
- }, bgTearResends = 0, drainingRetries = 0, resumeAtRetried = !1, busySignal = null, readBusySignal = () => busySignal, runningChoiceOffered = !1, runningChoiceSilentWaitTaskId = null, engineFrameSeen = !1, retryStream = !0;
363268
+ }, bgTearResends = 0, drainingRetries = 0, resumeAtRetried = !1, busySignal = null, readBusySignal = () => busySignal, runningChoiceOffered = !1, runningChoiceSilentWaitTaskId = null, engineFrameSeen = !1, boundRunId, retryStream = !0, interruptedResendDone = !1, pendingInterruptedSettledRow = null;
362970
363269
  for (; retryStream; ) {
362971
- retryStream = !1, engineFrameSeen = !1, busySignal = null;
363270
+ retryStream = !1, engineFrameSeen = !1, busySignal = null, boundRunId = void 0;
362972
363271
  try {
362973
- let reattachArmed = typeof client.runs.get == "function" && !isBgHeadlessWorker(), boundRunId, rawLive = client.tasks.stream(req, {
363272
+ let reattachArmed = typeof client.runs.get == "function" && !isBgHeadlessWorker(), rawLive = client.tasks.stream(req, {
362974
363273
  signal,
362975
- ...reattachArmed ? {
362976
- onRunBound: (id) => {
362977
- boundRunId = id;
362978
- }
362979
- } : {}
362980
- }), liveEvents = reattachArmed ? withInteractiveReattach(rawLive, {
363274
+ onRunBound: (id) => {
363275
+ boundRunId = id, armTerminationIntentOnAbort(signal, id), isMainLaneQuerySource(params.querySource) && !isBackgroundJournalSuppressed() && (foregroundInteractiveRunId = id, foregroundRunRegistered = id);
363276
+ }
363277
+ });
363278
+ if (pendingInterruptedSettledRow !== null) {
363279
+ let settledRowNow = pendingInterruptedSettledRow;
363280
+ pendingInterruptedSettledRow = null, yield apiErrorRow(settledRowNow);
363281
+ }
363282
+ let liveEvents = reattachArmed ? withInteractiveReattach(rawLive, {
362981
363283
  getTaskId: () => boundRunId,
362982
363284
  ...signal ? { signal } : {},
362983
363285
  // 状态行只归**前台主车道**:后台 session(startBackgroundSession 的 ALS 链)与非主车道
@@ -363016,8 +363318,26 @@ Fix: run \`sema doctor\` to diagnose, or restart sema to retry.`
363016
363318
  for await (let ccEvent of sdkMessagesToCcEvents(sdk, { sessionId, uuid: uuid5, signal }))
363017
363319
  yield* flushChromeRows(), trackToolLifecycle(ccEvent), yield ccEvent;
363018
363320
  yield* flushChromeRows();
363019
- let detectedBusy = readBusySignal();
363020
- if (detectedBusy && !signal?.aborted) {
363321
+ let detectedBusy = readBusySignal(), interruptedTaskId = detectedBusy?.activeTaskId ?? null, interruptedShortCircuitSettled = !1;
363322
+ if (detectedBusy && !signal?.aborted && interruptedTaskId !== null && !interruptedResendDone && wasRecentlyTerminatedByUs(interruptedTaskId)) {
363323
+ let verdict = await awaitInterruptedRunSettle(interruptedTaskId, {
363324
+ getRun: durableRunVerbs(client).get,
363325
+ ...signal ? { signal } : {}
363326
+ });
363327
+ if (process.env.SEMA_DEBUG && console.error(
363328
+ `[sema][seamQuery] 409 running on ${interruptedTaskId} \u2014 we terminated it (${String(
363329
+ terminationIntentSource(interruptedTaskId)
363330
+ )}); settle verdict=${verdict.kind}`
363331
+ ), verdict.kind === "settled" && !signal?.aborted) {
363332
+ forgetTerminationIntent(interruptedTaskId), interruptedResendDone = !0, retryStream = !0, pendingInterruptedSettledRow = interruptedRunSettleRow(interruptedTaskId, verdict);
363333
+ continue;
363334
+ }
363335
+ if (verdict.kind === "still-running" && !signal?.aborted) {
363336
+ let row2 = interruptedRunSettleRow(interruptedTaskId, verdict);
363337
+ row2 !== null && (yield apiErrorRow(row2)), interruptedShortCircuitSettled = !0, isMainLaneQuerySource(params.querySource) && trailingStandaloneMetaUserMessages(params.messages).length > 0 && noteInjectionLostWhileHeld();
363338
+ }
363339
+ }
363340
+ if (detectedBusy && !signal?.aborted && !interruptedShortCircuitSettled) {
363021
363341
  let outcome = await attemptActiveRunSelfHeal2(detectedBusy, durableRunVerbs(client), {
363022
363342
  // `hasPendingDecision`(车L 12,原「故意不接」记账销案):真读面 = REPL
363023
363343
  // toolUseConfirmQueue 的模块级长度镜像(leaderPermissionBridge,队列变更 effect
@@ -363170,7 +363490,7 @@ ${notifSupplement}` : baseErrorContent
363170
363490
  return next;
363171
363491
  });
363172
363492
  }
363173
- disarmAllEngineDetachHints(params.toolUseContext), setActiveEngineTaskId(null), noteEngineTurnBoundary();
363493
+ disarmAllEngineDetachHints(params.toolUseContext), setActiveEngineTaskId(null), foregroundRunRegistered !== null && foregroundInteractiveRunId === foregroundRunRegistered && (foregroundInteractiveRunId = null), noteEngineTurnBoundary();
363174
363494
  }
363175
363495
  }
363176
363496
  function isHitlClient(c2) {
@@ -363187,11 +363507,64 @@ function makeControlRouter(sessionId) {
363187
363507
  async function bestEffortDurableCancel() {
363188
363508
  try {
363189
363509
  let router = getControlRouter();
363190
- if (!router || router.activeTaskId() === null) return;
363191
- await router.cancel();
363510
+ if (!router) return;
363511
+ let taskId = router.activeTaskId();
363512
+ if (taskId === null) return;
363513
+ recordTerminationIntent(taskId, "durable-cancel");
363514
+ try {
363515
+ await router.cancel();
363516
+ } catch (e) {
363517
+ throw forgetTerminationIntent(taskId), e;
363518
+ }
363192
363519
  } catch {
363193
363520
  }
363194
363521
  }
363522
+ function _setInteractiveCancelTimeoutMsForTest(ms) {
363523
+ escCancelTimeoutOverrideMs = ms;
363524
+ }
363525
+ function _resetInteractiveCancelStateForTest() {
363526
+ foregroundInteractiveRunId = null, escCancelInFlight.clear(), escCancelTimeoutOverrideMs = null;
363527
+ }
363528
+ function bestEffortInteractiveCancel() {
363529
+ try {
363530
+ let taskId = foregroundInteractiveRunId;
363531
+ if (taskId === null) return;
363532
+ let runs = client.runs, cancelFn = runs.cancel;
363533
+ if (typeof cancelFn != "function") {
363534
+ escCancelProbe(`no runs.cancel verb on this lane \u2014 nothing sent for ${taskId}`);
363535
+ return;
363536
+ }
363537
+ if (escCancelInFlight.has(taskId)) {
363538
+ escCancelProbe(`a cancel is already in flight for ${taskId} \u2014 this press yields to it`);
363539
+ return;
363540
+ }
363541
+ let prior = terminationIntentSource(taskId);
363542
+ escCancelInFlight.add(taskId), recordTerminationIntent(taskId, "esc-cancel"), (async () => {
363543
+ try {
363544
+ await cancelFn.call(runs, taskId, {
363545
+ signal: AbortSignal.timeout(escCancelTimeoutOverrideMs ?? ESC_CANCEL_TIMEOUT_MS)
363546
+ }), escCancelProbe(`cancel accepted for ${taskId}`);
363547
+ } catch (e) {
363548
+ terminationIntentSource(taskId) === "esc-cancel" && (prior === null ? forgetTerminationIntent(taskId) : recordTerminationIntent(taskId, prior)), escCancelProbe(
363549
+ `cancel refused for ${taskId} (${String(
363550
+ e?.errorCode ?? "transport"
363551
+ )}) \u2014 ledger restored to ${String(prior)}`
363552
+ );
363553
+ } finally {
363554
+ escCancelInFlight.delete(taskId);
363555
+ }
363556
+ })();
363557
+ } catch {
363558
+ }
363559
+ }
363560
+ function escCancelProbe(msg) {
363561
+ let line = `[sema][seamQuery] esc-cancel: ${msg}`;
363562
+ try {
363563
+ logForDebugging(line);
363564
+ } catch {
363565
+ }
363566
+ process.env.SEMA_DEBUG && console.error(line);
363567
+ }
363195
363568
  async function probeEngineRunState(taskId) {
363196
363569
  return (await probeEngineRunLiveness(taskId)).state;
363197
363570
  }
@@ -363221,7 +363594,7 @@ async function cancelEngineRun(taskId) {
363221
363594
  try {
363222
363595
  if (typeof taskId != "string" || taskId.length === 0) return "failed";
363223
363596
  let o = client;
363224
- return typeof o.runs?.cancel != "function" ? "failed" : (await o.runs.cancel(taskId), "cancelled");
363597
+ return typeof o.runs?.cancel != "function" ? "failed" : (await o.runs.cancel(taskId), recordTerminationIntent(taskId, "command-cancel"), "cancelled");
363225
363598
  } catch (e) {
363226
363599
  return e?.errorCode === "conflict.approval_settled" ? "approval_settled" : "failed";
363227
363600
  }
@@ -363310,7 +363683,7 @@ function resumeRunningArmWiring() {
363310
363683
  shellSessionId: () => getSessionId()
363311
363684
  };
363312
363685
  }
363313
- var BG_TEAR_MAX_RESENDS, BG_RECOVERY_WAIT_MS, DRAINING_MAX_RETRIES, drainingBackoffMs, client, clientExplicitlySet, seamSettings, printResolvedSettingsProvider, seamWebSearch, seamSkills, seamMcp, seamRewindCapture, seamPendingRewind, INTERRUPT_WIRE_MARKER, seamPendingInterrupt, seamHistorySeedPending, seamSandbox, seamAutoSandboxInjected, HISTORY_SEED_MAX_CHARS, SCENARIO_KEYS, API_ERROR_PREFIX, defaultGatePrompt, canUseTool, RUN_PROBE_TIMEOUT_MS, init_seamQuery = __esm({
363686
+ var BG_TEAR_MAX_RESENDS, BG_RECOVERY_WAIT_MS, DRAINING_MAX_RETRIES, drainingBackoffMs, client, clientExplicitlySet, seamSettings, printResolvedSettingsProvider, seamWebSearch, seamSkills, seamMcp, seamRewindCapture, seamPendingRewind, INTERRUPT_WIRE_MARKER, seamPendingInterrupt, seamHistorySeedPending, seamSandbox, seamAutoSandboxInjected, HISTORY_SEED_MAX_CHARS, SCENARIO_KEYS, API_ERROR_PREFIX, defaultGatePrompt, canUseTool, foregroundInteractiveRunId, escCancelInFlight, ESC_CANCEL_TIMEOUT_MS, escCancelTimeoutOverrideMs, RUN_PROBE_TIMEOUT_MS, init_seamQuery = __esm({
363314
363687
  "build-src/src/sema/seamQuery.ts"() {
363315
363688
  init_hotReconcile();
363316
363689
  init_adapter();
@@ -363370,6 +363743,7 @@ var BG_TEAR_MAX_RESENDS, BG_RECOVERY_WAIT_MS, DRAINING_MAX_RETRIES, drainingBack
363370
363743
  init_engineRuntimeStatus();
363371
363744
  init_activeRunSelfHeal2();
363372
363745
  init_injectionRequeueLatch();
363746
+ init_terminationIntentLedger();
363373
363747
  BG_TEAR_MAX_RESENDS = 2, BG_RECOVERY_WAIT_MS = 12e4, DRAINING_MAX_RETRIES = 3;
363374
363748
  client = makeMockClient(), clientExplicitlySet = !1;
363375
363749
  seamRewindCapture = !0;
@@ -363430,6 +363804,7 @@ var BG_TEAR_MAX_RESENDS, BG_RECOVERY_WAIT_MS, DRAINING_MAX_RETRIES, drainingBack
363430
363804
  updatedInput: input,
363431
363805
  toolUseID
363432
363806
  }), canUseTool = isHitlClient(client) ? makeHitlCanUseTool2(new HitlBridge(client, mockClientIds.taskId), defaultGatePrompt) : makeCanUseTool();
363807
+ foregroundInteractiveRunId = null, escCancelInFlight = /* @__PURE__ */ new Set(), ESC_CANCEL_TIMEOUT_MS = 5e3, escCancelTimeoutOverrideMs = null;
363433
363808
  RUN_PROBE_TIMEOUT_MS = 5e3;
363434
363809
  }
363435
363810
  });
@@ -381928,15 +382303,15 @@ function useManageMCPConnections(dynamicMcpConfig, isStrictMcpConfig = !1) {
381928
382303
  [addNotification]
381929
382304
  );
381930
382305
  (0, import_react129.useEffect)(() => {
381931
- let ledger = getSessionMcpConfigLedger("session"), cancelled = !1;
382306
+ let ledger2 = getSessionMcpConfigLedger("session"), cancelled = !1;
381932
382307
  async function initializeServersAsPending() {
381933
382308
  let { servers: existingConfigs, errors: mcpErrors } = isStrictMcpConfig ? { servers: {}, errors: [] } : await getClaudeCodeMcpConfigs(dynamicMcpConfig);
381934
382309
  if (cancelled) return;
381935
382310
  let pinned = pinSessionMcpConfigs(
381936
382311
  { ...existingConfigs, ...dynamicMcpConfig },
381937
- ledger
382312
+ ledger2
381938
382313
  ), configs = pinned.configs;
381939
- noticeConfigPinned(pinned), syncSessionMcpRevocations(ledger, configs, isMcpServerDisabled), addErrorsToAppState(setAppState, mcpErrors), setAppState((prevState) => {
382314
+ noticeConfigPinned(pinned), syncSessionMcpRevocations(ledger2, configs, isMcpServerDisabled), addErrorsToAppState(setAppState, mcpErrors), setAppState((prevState) => {
381940
382315
  let { stale, ...mcpWithoutStale } = excludeStalePluginClients(
381941
382316
  prevState.mcp,
381942
382317
  configs,
@@ -381983,7 +382358,7 @@ function useManageMCPConnections(dynamicMcpConfig, isStrictMcpConfig = !1) {
381983
382358
  noticeConfigPinned,
381984
382359
  bumpAttemptEpoch
381985
382360
  ]), (0, import_react129.useEffect)(() => {
381986
- let cancelled = !1, ledger = getSessionMcpConfigLedger("session"), claudeaiLedger = getSessionMcpConfigLedger("claudeai");
382361
+ let cancelled = !1, ledger2 = getSessionMcpConfigLedger("session"), claudeaiLedger = getSessionMcpConfigLedger("claudeai");
381987
382362
  async function loadAndConnectMcpConfigs() {
381988
382363
  let claudeaiPromise;
381989
382364
  isStrictMcpConfig || doesEnterpriseMcpConfigExist() ? claudeaiPromise = Promise.resolve({}) : (clearClaudeAIMcpConfigsCache(), claudeaiPromise = fetchClaudeAIMcpConfigsIfEligible());
@@ -381992,9 +382367,9 @@ function useManageMCPConnections(dynamicMcpConfig, isStrictMcpConfig = !1) {
381992
382367
  addErrorsToAppState(setAppState, mcpErrors);
381993
382368
  let pinned = pinSessionMcpConfigs(
381994
382369
  { ...claudeCodeConfigs, ...dynamicMcpConfig },
381995
- ledger
382370
+ ledger2
381996
382371
  ), configs = pinned.configs;
381997
- noticeConfigPinned(pinned), syncSessionMcpRevocations(ledger, configs, isMcpServerDisabled);
382372
+ noticeConfigPinned(pinned), syncSessionMcpRevocations(ledger2, configs, isMcpServerDisabled);
381998
382373
  let enabledConfigs = Object.fromEntries(
381999
382374
  Object.entries(configs).filter(([name]) => !isMcpServerDisabled(name))
382000
382375
  );
@@ -392664,19 +393039,14 @@ var sema_brand_default, init_sema_brand = __esm({
392664
393039
  _doc: "displayName/email \u7559 null = \u8FD0\u884C\u65F6\u56DE\u9000(\u540D\u5B57\u53D6\u672C\u673A OS \u7528\u6237\u540D,\u90AE\u7BB1\u4E0D\u663E\u793A)\u3002\u522B\u70E7\u4E2A\u4EBA\u4FE1\u606F\u8FDB\u54C1\u724C\u6587\u4EF6(F-S1-1:\u65B0\u7528\u6237\u66FE\u770B\u5230 Welcome back Clay!)\u3002"
392665
393040
  },
392666
393041
  whatsNew: {
392667
- version: "1.0.87",
393042
+ version: "1.0.89",
392668
393043
  notes: [
392669
- "Engine restarts now ask first: pressing ctrl+u (or any flow that needs an engine restart) shows a confirmation card before anything stops \u2014 and the card appears in every screen, including transcript, fleet and plugin panels",
392670
- 'Restart messages tell the truth: a crash, a user-requested restart and a config-driven restart each get their own wording instead of one vague "may have crashed" line',
392671
- 'Reasoning effort "xhigh" now persists: it survives restarts and resume instead of silently dropping to a lower level, and JSON-defined agents accept all five effort levels',
392672
- "Model Hub: models you added yourself can now be deleted from the UI, a vision toggle lets self-configured models accept images, and the effort row shows both the requested and the effective value when they differ",
392673
- "MCP panel no longer re-greets servers it already knows after reopening \u2014 approved servers stay approved, removed ones stay gone",
392674
- "Background shell completions show up as they happen instead of waiting for your next message",
392675
- "Saving engine port/bind/read-face settings while attached to an external engine no longer shows a restart banner that could never apply \u2014 the notice now says the setting takes effect on the next local engine start"
393044
+ "When an approval card is waiting for your decision and the engine aborts the other in-flight tool calls running alongside it, the transcript now folds those into one summary line ('Aborted alongside the pending approval: N more tool calls (ctrl+o for detail)') instead of repeating a full error block for each one \u2014 the call you're actually deciding on stays fully visible, full detail is still one ctrl+o away.",
393045
+ "Engine updated to server 7.41.0 (core 5.54)."
392676
393046
  ]
392677
393047
  },
392678
- productVersion: "1.0.87",
392679
- announcement: "sema 1.0.87 \u2014 engine restarts now ask first (ctrl+u confirmation card in every screen), restart messages tell the truth per cause, reasoning effort xhigh persists across restart/resume, and Model Hub gains model delete + vision toggle"
393048
+ productVersion: "1.0.89",
393049
+ announcement: "sema 1.0.89 \u2014 tool calls aborted alongside a pending approval now fold into one summary line instead of repeating a full error per call, so the approval you're deciding on doesn't get buried"
392680
393050
  };
392681
393051
  }
392682
393052
  });
@@ -393432,11 +393802,11 @@ function readErrorResult(msg) {
393432
393802
  if (!block2 || block2.type !== "tool_result" || block2.is_error !== !0 || typeof block2.tool_use_id != "string") return null;
393433
393803
  let isPlainText = typeof block2.content == "string", normalized = normalizeResultContent(block2.content);
393434
393804
  if (normalized === null) return null;
393435
- let text2 = isPlainText ? unwrapWholeSystemReminder(normalized).trim() : normalized, family = familyOf(text2, isPlainText);
393805
+ let text2 = isPlainText ? unwrapWholeSystemReminder(normalized).trim() : normalized, collateral = msg[SEMA_COLLATERAL_ABORT_KEY] === !0, family = familyOf(text2, isPlainText, collateral);
393436
393806
  return family === null ? null : { text: text2, toolUseId: block2.tool_use_id, family };
393437
393807
  }
393438
- function familyOf(text2, isPlainText) {
393439
- return isPlainText ? text2 === INTERRUPTED_REPEAT_SENTENCE ? "interrupted-batch" : text2.startsWith(APPROVAL_DENIED_ANCHOR) || text2.includes(APPROVAL_WINDOW_ANCHOR) ? "repeated-notice" : "repeated-error" : "repeated-error";
393808
+ function familyOf(text2, isPlainText, collateral) {
393809
+ return collateral ? "collateral-abort" : isPlainText ? text2 === INTERRUPTED_REPEAT_SENTENCE ? "interrupted-batch" : text2.startsWith(APPROVAL_DENIED_ANCHOR) || text2.includes(APPROVAL_WINDOW_ANCHOR) ? "repeated-notice" : "repeated-error" : "repeated-error";
393440
393810
  }
393441
393811
  function assistantToolUseId(msg) {
393442
393812
  if (!msg || msg.type !== "assistant") return null;
@@ -393451,6 +393821,7 @@ function foldRow(from, text2, count3) {
393451
393821
  let block2 = firstBlock(from), {
393452
393822
  toolUseResult: _droppedToolUseResult,
393453
393823
  _sema_degraded: _droppedDegraded,
393824
+ [SEMA_COLLATERAL_ABORT_KEY]: _droppedCollateralAbort,
393454
393825
  ...rest
393455
393826
  } = from;
393456
393827
  return {
@@ -393507,14 +393878,8 @@ function collapseRepeatedToolErrors(messages, verbose) {
393507
393878
  let unit = run2[k2];
393508
393879
  unit.span === 2 && result.push(messages[unit.start]);
393509
393880
  }
393510
- let prefix = first.view.family === "repeated-notice" ? REPEATED_NOTICE_FOLD_PREFIX : REPEATED_ERROR_FOLD_PREFIX;
393511
- result.push(
393512
- foldRow(
393513
- run2[1].result,
393514
- `${prefix}${String(run2.length - 1)}`,
393515
- run2.length - 1
393516
- )
393517
- );
393881
+ let folded = run2.length - 1, text2 = first.view.family === "repeated-notice" ? `${REPEATED_NOTICE_FOLD_PREFIX}${String(folded)}` : first.view.family === "collateral-abort" ? `${COLLATERAL_ABORT_FOLD_PREFIX}${String(folded)} more tool ${folded === 1 ? "call" : "calls"} (ctrl+o for detail)` : `${REPEATED_ERROR_FOLD_PREFIX}${String(folded)}`;
393882
+ result.push(foldRow(run2[1].result, text2, folded));
393518
393883
  }
393519
393884
  i = j3;
393520
393885
  }
@@ -393522,11 +393887,13 @@ function collapseRepeatedToolErrors(messages, verbose) {
393522
393887
  }
393523
393888
  var INTERRUPTED_REPEAT_SENTENCE, APPROVAL_DENIED_ANCHOR, APPROVAL_WINDOW_ANCHOR, MIN_RUN, init_collapseRepeatedToolErrors = __esm({
393524
393889
  "build-src/src/utils/collapseRepeatedToolErrors.ts"() {
393890
+ init_dist();
393525
393891
  init_UserToolErrorMessage();
393526
393892
  INTERRUPTED_REPEAT_SENTENCE = "[INTERRUPTED] Same as an earlier interrupted call in this batch: it never started and had no side effects \u2014 safe to re-issue.", APPROVAL_DENIED_ANCHOR = 'approval denied for "', APPROVAL_WINDOW_ANCHOR = "was not answered before the approver's own window elapsed", MIN_RUN = {
393527
393893
  "interrupted-batch": 2,
393528
393894
  "repeated-notice": 2,
393529
- "repeated-error": 3
393895
+ "repeated-error": 3,
393896
+ "collateral-abort": 2
393530
393897
  };
393531
393898
  }
393532
393899
  });
@@ -397020,19 +397387,14 @@ var require_sema_brand = __commonJS({
397020
397387
  _doc: "displayName/email \u7559 null = \u8FD0\u884C\u65F6\u56DE\u9000(\u540D\u5B57\u53D6\u672C\u673A OS \u7528\u6237\u540D,\u90AE\u7BB1\u4E0D\u663E\u793A)\u3002\u522B\u70E7\u4E2A\u4EBA\u4FE1\u606F\u8FDB\u54C1\u724C\u6587\u4EF6(F-S1-1:\u65B0\u7528\u6237\u66FE\u770B\u5230 Welcome back Clay!)\u3002"
397021
397388
  },
397022
397389
  whatsNew: {
397023
- version: "1.0.87",
397390
+ version: "1.0.89",
397024
397391
  notes: [
397025
- "Engine restarts now ask first: pressing ctrl+u (or any flow that needs an engine restart) shows a confirmation card before anything stops \u2014 and the card appears in every screen, including transcript, fleet and plugin panels",
397026
- 'Restart messages tell the truth: a crash, a user-requested restart and a config-driven restart each get their own wording instead of one vague "may have crashed" line',
397027
- 'Reasoning effort "xhigh" now persists: it survives restarts and resume instead of silently dropping to a lower level, and JSON-defined agents accept all five effort levels',
397028
- "Model Hub: models you added yourself can now be deleted from the UI, a vision toggle lets self-configured models accept images, and the effort row shows both the requested and the effective value when they differ",
397029
- "MCP panel no longer re-greets servers it already knows after reopening \u2014 approved servers stay approved, removed ones stay gone",
397030
- "Background shell completions show up as they happen instead of waiting for your next message",
397031
- "Saving engine port/bind/read-face settings while attached to an external engine no longer shows a restart banner that could never apply \u2014 the notice now says the setting takes effect on the next local engine start"
397392
+ "When an approval card is waiting for your decision and the engine aborts the other in-flight tool calls running alongside it, the transcript now folds those into one summary line ('Aborted alongside the pending approval: N more tool calls (ctrl+o for detail)') instead of repeating a full error block for each one \u2014 the call you're actually deciding on stays fully visible, full detail is still one ctrl+o away.",
397393
+ "Engine updated to server 7.41.0 (core 5.54)."
397032
397394
  ]
397033
397395
  },
397034
- productVersion: "1.0.87",
397035
- announcement: "sema 1.0.87 \u2014 engine restarts now ask first (ctrl+u confirmation card in every screen), restart messages tell the truth per cause, reasoning effort xhigh persists across restart/resume, and Model Hub gains model delete + vision toggle"
397396
+ productVersion: "1.0.89",
397397
+ announcement: "sema 1.0.89 \u2014 tool calls aborted alongside a pending approval now fold into one summary line instead of repeating a full error per call, so the approval you're deciding on doesn't get buried"
397036
397398
  };
397037
397399
  }
397038
397400
  });
@@ -431222,6 +431584,14 @@ function deriveUUID(parentUUID, index) {
431222
431584
  let hex3 = index.toString(16).padStart(12, "0");
431223
431585
  return `${parentUUID.slice(0, 24)}${hex3}`;
431224
431586
  }
431587
+ function preserveSemaRenderSidecars(from) {
431588
+ let src = from;
431589
+ if (src === null || typeof src != "object") return {};
431590
+ let out6 = {};
431591
+ for (let key of SEMA_RENDER_SIDECAR_KEYS)
431592
+ src[key] !== void 0 && (out6[key] = src[key]);
431593
+ return out6;
431594
+ }
431225
431595
  function normalizeMessages(messages) {
431226
431596
  let isNewChain = !1;
431227
431597
  return messages.flatMap((message) => {
@@ -431282,7 +431652,10 @@ function normalizeMessages(messages) {
431282
431652
  imagePasteIds: imageId !== void 0 ? [imageId] : void 0,
431283
431653
  origin: message.origin
431284
431654
  }),
431285
- uuid: isNewChain ? deriveUUID(message.uuid, index) : message.uuid
431655
+ uuid: isNewChain ? deriveUUID(message.uuid, index) : message.uuid,
431656
+ // 🔴 sema #324:顶层 sema sidecar 透传 —— 判据与族扫见 SEMA_RENDER_SIDECAR_KEYS 头注
431657
+ // (白名单重建把它们丢在消费者上游 = 折叠族在真管线上恒不触发)。
431658
+ ...preserveSemaRenderSidecars(message)
431286
431659
  };
431287
431660
  });
431288
431661
  }
@@ -433693,8 +434066,9 @@ ${raw2}
433693
434066
  IMPORTANT: After completing your current task, you MUST address the user's message above. Do not ignore it.`;
433694
434067
  }
433695
434068
  }
433696
- var MEMORY_CORRECTION_HINT, TOOL_REFERENCE_TURN_BOUNDARY, INTERRUPT_MESSAGE, INTERRUPT_MESSAGE_FOR_TOOL_USE, CANCEL_MESSAGE2, REJECT_MESSAGE2, REJECT_MESSAGE_WITH_REASON_PREFIX, SUBAGENT_REJECT_MESSAGE, SUBAGENT_REJECT_MESSAGE_WITH_REASON_PREFIX, PLAN_REJECTION_PREFIX, DENIAL_WORKAROUND_GUIDANCE, NO_RESPONSE_REQUESTED, SYNTHETIC_TOOL_RESULT_PLACEHOLDER, AUTO_MODE_REJECTION_PREFIX, SYNTHETIC_MODEL, SYNTHETIC_MESSAGES, EMPTY_LOOKUPS, EMPTY_STRING_SET, STRIPPED_TAGS_RE, PLAN_PHASE4_CONTROL, PLAN_PHASE4_TRIM, PLAN_PHASE4_CUT, PLAN_PHASE4_CAP, init_messages4 = __esm({
434069
+ var MEMORY_CORRECTION_HINT, TOOL_REFERENCE_TURN_BOUNDARY, INTERRUPT_MESSAGE, INTERRUPT_MESSAGE_FOR_TOOL_USE, CANCEL_MESSAGE2, REJECT_MESSAGE2, REJECT_MESSAGE_WITH_REASON_PREFIX, SUBAGENT_REJECT_MESSAGE, SUBAGENT_REJECT_MESSAGE_WITH_REASON_PREFIX, PLAN_REJECTION_PREFIX, DENIAL_WORKAROUND_GUIDANCE, NO_RESPONSE_REQUESTED, SYNTHETIC_TOOL_RESULT_PLACEHOLDER, AUTO_MODE_REJECTION_PREFIX, SYNTHETIC_MODEL, SYNTHETIC_MESSAGES, SEMA_RENDER_SIDECAR_KEYS, EMPTY_LOOKUPS, EMPTY_STRING_SET, STRIPPED_TAGS_RE, PLAN_PHASE4_CONTROL, PLAN_PHASE4_TRIM, PLAN_PHASE4_CUT, PLAN_PHASE4_CAP, init_messages4 = __esm({
433697
434070
  "build-src/src/utils/messages.ts"() {
434071
+ init_dist();
433698
434072
  init_systemReminderTag();
433699
434073
  init_isObject();
433700
434074
  init_last();
@@ -433767,6 +434141,12 @@ Rejected plan:
433767
434141
  REJECT_MESSAGE2,
433768
434142
  NO_RESPONSE_REQUESTED
433769
434143
  ]);
434144
+ SEMA_RENDER_SIDECAR_KEYS = [
434145
+ // 1.0.89 提货批族扫:键名走 client-core 包常量(铸点同一个符号),不再手抄字面量。
434146
+ // `_sema_degraded` 包侧今天没铸出公面常量 ⇒ 保留字面量,那一把到货再换(不硬凑)。
434147
+ SEMA_COLLATERAL_ABORT_KEY,
434148
+ "_sema_degraded"
434149
+ ];
433770
434150
  EMPTY_LOOKUPS = {
433771
434151
  siblingToolUseIDs: /* @__PURE__ */ new Map(),
433772
434152
  progressMessagesByToolUseID: /* @__PURE__ */ new Map(),
@@ -434044,18 +434424,18 @@ function maybeQueueAutoSyncPushAfterTurn() {
434044
434424
  backoffTurnsRemaining--;
434045
434425
  return;
434046
434426
  }
434047
- if (inflight3) {
434427
+ if (inflight2) {
434048
434428
  dirty = !0;
434049
434429
  return;
434050
434430
  }
434051
- inflight3 = runOnce().catch((err8) => {
434431
+ inflight2 = runOnce().catch((err8) => {
434052
434432
  logForDebugging(`sessionAutoSync: unexpected failure: ${err8}`);
434053
434433
  }).finally(() => {
434054
- inflight3 = null, dirty && (dirty = !1, maybeQueueAutoSyncPushAfterTurn());
434434
+ inflight2 = null, dirty && (dirty = !1, maybeQueueAutoSyncPushAfterTurn());
434055
434435
  });
434056
434436
  }
434057
434437
  async function flushAutoSyncQueue() {
434058
- for (; inflight3; ) await inflight3;
434438
+ for (; inflight2; ) await inflight2;
434059
434439
  }
434060
434440
  async function projectAutoSyncEnabled() {
434061
434441
  try {
@@ -434155,16 +434535,16 @@ async function runOnce() {
434155
434535
  }
434156
434536
  }
434157
434537
  function _resetAutoSyncForTests() {
434158
- inflight3 = null, dirty = !1, capsCache.clear(), degradedTargets.clear(), orgMirrorNotified.clear(), consecutiveFailures = 0, latchCount = 0, backoffTurnsRemaining = 0, listener3 = null, pendingEvents2 = [], transportOverride = null;
434538
+ inflight2 = null, dirty = !1, capsCache.clear(), degradedTargets.clear(), orgMirrorNotified.clear(), consecutiveFailures = 0, latchCount = 0, backoffTurnsRemaining = 0, listener3 = null, pendingEvents2 = [], transportOverride = null;
434159
434539
  }
434160
- var AUTO_SYNC_SETTINGS_KEY, TRANSIENT_FAILURE_LATCH, MAX_BACKOFF_TURNS, listener3, pendingEvents2, inflight3, dirty, capsCache, degradedTargets, orgMirrorNotified, consecutiveFailures, latchCount, backoffTurnsRemaining, transportOverride, init_sessionAutoSync = __esm({
434540
+ var AUTO_SYNC_SETTINGS_KEY, TRANSIENT_FAILURE_LATCH, MAX_BACKOFF_TURNS, listener3, pendingEvents2, inflight2, dirty, capsCache, degradedTargets, orgMirrorNotified, consecutiveFailures, latchCount, backoffTurnsRemaining, transportOverride, init_sessionAutoSync = __esm({
434161
434541
  "build-src/src/sema/sessionAutoSync.ts"() {
434162
434542
  init_livePrincipal();
434163
434543
  init_debug();
434164
434544
  init_liveSessionStore();
434165
434545
  init_sessionIdMapping();
434166
434546
  AUTO_SYNC_SETTINGS_KEY = "cloudSessionAutoSync", TRANSIENT_FAILURE_LATCH = 5, MAX_BACKOFF_TURNS = 64, listener3 = null, pendingEvents2 = [];
434167
- inflight3 = null, dirty = !1, capsCache = /* @__PURE__ */ new Map(), degradedTargets = /* @__PURE__ */ new Set(), orgMirrorNotified = /* @__PURE__ */ new Set(), consecutiveFailures = 0, latchCount = 0, backoffTurnsRemaining = 0;
434547
+ inflight2 = null, dirty = !1, capsCache = /* @__PURE__ */ new Map(), degradedTargets = /* @__PURE__ */ new Set(), orgMirrorNotified = /* @__PURE__ */ new Set(), consecutiveFailures = 0, latchCount = 0, backoffTurnsRemaining = 0;
434168
434548
  transportOverride = null;
434169
434549
  }
434170
434550
  });
@@ -434958,6 +435338,57 @@ var ENGINE_BG_SHELL_WATCH_INTERVAL_MS, watchIntervalMs, WATCH_TTL_MS2, outstandi
434958
435338
  }
434959
435339
  });
434960
435340
 
435341
+ // build-src/src/sema/engineToolEndGuidance.ts
435342
+ function toolEndGuidanceRow(errorCode) {
435343
+ if (!(typeof errorCode != "string" || errorCode === "")) {
435344
+ if (errorCode === MCP_SERVER_REVOKED)
435345
+ return "this MCP server was revoked by an operator \u2014 the request was NOT sent, and calls to it keep being refused until it is approved again";
435346
+ switch (delegationCapDispositionOf(errorCode)) {
435347
+ case "wait-for-slot":
435348
+ return "delegation concurrency cap reached \u2014 a seat frees up as soon as a sibling agent finishes; re-sending the same call later will go through (nothing to reconfigure)";
435349
+ case "reuse-existing-or-await-reap":
435350
+ return "delegation seat cap reached for the retained window \u2014 continue an existing agent with SendMessage, or wait for its row to be reaped and the quota comes back (no need to switch sessions or change any setting)";
435351
+ default:
435352
+ break;
435353
+ }
435354
+ if (isDelegationCapCode(errorCode))
435355
+ return `the engine refused this delegation with code "${cleanUntrustedForDisplay(errorCode, MAX_CODE_CHARS)}" \u2014 this build has no guidance for that code yet`;
435356
+ }
435357
+ }
435358
+ function createToolEndGuidanceLane() {
435359
+ let byFrame = /* @__PURE__ */ new Map(), total = 0;
435360
+ return {
435361
+ note(frameNo, frame) {
435362
+ let f = frame;
435363
+ if (f === null || typeof f != "object" || f.type !== "tool_end_result" || typeof f.parentToolCallId == "string" || typeof f.toolCallId != "string" || f.toolCallId === "") return;
435364
+ let row2 = toolEndGuidanceRow(f.errorCode);
435365
+ if (row2 === void 0 || total >= MAX_PENDING_ROWS) return;
435366
+ total++;
435367
+ let bucket = byFrame.get(frameNo);
435368
+ bucket === void 0 ? byFrame.set(frameNo, [row2]) : bucket.push(row2);
435369
+ },
435370
+ flushFrame(frameNo) {
435371
+ let rows2 = byFrame.get(frameNo);
435372
+ if (rows2 !== void 0) {
435373
+ byFrame.delete(frameNo), total -= rows2.length;
435374
+ for (let row2 of rows2) surfaceTranscriptSystemNotice(row2);
435375
+ }
435376
+ },
435377
+ discard() {
435378
+ byFrame.clear(), total = 0;
435379
+ }
435380
+ };
435381
+ }
435382
+ var MAX_CODE_CHARS, MAX_PENDING_ROWS, init_engineToolEndGuidance = __esm({
435383
+ "build-src/src/sema/engineToolEndGuidance.ts"() {
435384
+ init_dist();
435385
+ init_transcriptSystemNotice();
435386
+ init_untrustedDisplayText();
435387
+ MAX_CODE_CHARS = 80;
435388
+ MAX_PENDING_ROWS = 32;
435389
+ }
435390
+ });
435391
+
434961
435392
  // build-src/src/sema/enginePromptSuggestionsStore.ts
434962
435393
  function getEnginePromptSuggestions() {
434963
435394
  return current3;
@@ -434994,6 +435425,8 @@ var import_react198, EMPTY2, current3, listeners8, init_enginePromptSuggestionsS
434994
435425
  // build-src/src/sema/upstreamBridge.ts
434995
435426
  var upstreamBridge_exports = {};
434996
435427
  __export(upstreamBridge_exports, {
435428
+ collateralAbortCallIdOf: () => collateralAbortCallIdOf,
435429
+ collateralAbortStampTargetOf: () => collateralAbortStampTargetOf,
434997
435430
  deriveNotificationResidualLines: () => deriveNotificationResidualLines,
434998
435431
  engineTaskNotificationDedupKey: () => taskNotificationDedupKeyFromWire,
434999
435432
  sdkMessagesToCcEvents: () => sdkMessagesToCcEvents,
@@ -435087,6 +435520,26 @@ function isTaskNotificationRow(msg) {
435087
435520
  function stampTranscriptArrival(msg) {
435088
435521
  typeof msg.timestamp != "string" && (msg.timestamp = (/* @__PURE__ */ new Date()).toISOString());
435089
435522
  }
435523
+ function collateralAbortCallIdOf(frame) {
435524
+ let f = frame;
435525
+ if (f === null || typeof f != "object" || f.type !== "tool_end_result" || f[SEMA_COLLATERAL_ABORT_KEY] !== !0) return;
435526
+ let id = f.toolCallId;
435527
+ if (!(typeof id != "string" || id.length === 0))
435528
+ return id.length <= MAX_COLLATERAL_ABORT_ID_CHARS ? id : void 0;
435529
+ }
435530
+ function collateralAbortStampTargetOf(msg) {
435531
+ let content = msg?.message?.content;
435532
+ if (!Array.isArray(content)) return;
435533
+ let found;
435534
+ for (let block2 of content) {
435535
+ let b3 = block2;
435536
+ if (b3?.type === "tool_result") {
435537
+ if (found !== void 0 || typeof b3.tool_use_id != "string" || b3.tool_use_id.length === 0) return;
435538
+ found = b3.tool_use_id;
435539
+ }
435540
+ }
435541
+ return found;
435542
+ }
435090
435543
  async function* sdkMessagesToCcEvents(sdk, meta3) {
435091
435544
  function streamEvt(event) {
435092
435545
  return {
@@ -435217,10 +435670,7 @@ async function* sdkMessagesToCcEvents(sdk, meta3) {
435217
435670
  // 绝不铸 transcript 行(帧不带正文,替引擎编话=谎),落 debug 审计留痕(「这条 run 被谁插过话」
435218
435671
  // 可查);wire 值 UNTRUSTED,白名单键+控制字符消毒。
435219
435672
  case "human_input": {
435220
- let clean8 = (v2) => (
435221
- // eslint-disable-next-line no-control-regex
435222
- String(v2 ?? "").replace(/[\x00-\x1f\x7f]/g, ".").slice(0, 120)
435223
- ), who = e.actor?.id ? `${clean8(e.actor.id)}${e.actor.hostAsserted === !0 ? "" : " (unverified)"}` : "unattributed";
435673
+ let clean8 = (v2) => cleanUntrustedForDisplay(v2, 120), who = e.actor?.id ? `${clean8(e.actor.id)}${e.actor.hostAsserted === !0 ? "" : " (unverified)"}` : "unattributed";
435224
435674
  return logForDebugging(
435225
435675
  `[sema][bridge] human_input ledger frame (audit): carrier=${clean8(e.carrier)} eventId=${clean8(e.eventId)} by=${who}`
435226
435676
  ), [];
@@ -435255,33 +435705,43 @@ async function* sdkMessagesToCcEvents(sdk, meta3) {
435255
435705
  rowYielded: !1
435256
435706
  });
435257
435707
  }
435258
- let macrotask = () => new Promise((resolve57) => setTimeout(resolve57, 0)), curFrame = null, curFrameType = null, curFrameNo = 0, teed = (async function* () {
435708
+ let macrotask = () => new Promise((resolve57) => setTimeout(resolve57, 0)), curFrame = null, curFrameType = null, curFrameNo = 0, guidanceLane = createToolEndGuidanceLane(), collateralAbortCalls = /* @__PURE__ */ new Set();
435709
+ function noteCollateralAbortFrame(m2) {
435710
+ let id = collateralAbortCallIdOf(m2);
435711
+ id !== void 0 && (collateralAbortCalls.size >= MAX_COLLATERAL_ABORT_IDS || collateralAbortCalls.add(id));
435712
+ }
435713
+ function stampCollateralAbort(msg) {
435714
+ if (collateralAbortCalls.size === 0) return;
435715
+ let id = collateralAbortStampTargetOf(msg);
435716
+ id === void 0 || !collateralAbortCalls.has(id) || (msg[SEMA_COLLATERAL_ABORT_KEY] = !0);
435717
+ }
435718
+ let teed = (async function* () {
435259
435719
  for await (let raw2 of sdk) {
435260
435720
  let m2 = raw2;
435261
- curFrame = m2, curFrameType = typeof m2.type == "string" ? m2.type : null, curFrameNo++, observeFrame(m2), recordAgentToolStatsFromFrame(m2), yield raw2;
435721
+ curFrame = m2, curFrameType = typeof m2.type == "string" ? m2.type : null, curFrameNo++, observeFrame(m2), recordAgentToolStatsFromFrame(m2), guidanceLane.note(curFrameNo, m2), noteCollateralAbortFrame(m2), yield raw2;
435262
435722
  }
435263
435723
  curFrame = null, curFrameType = null, curFrameNo++;
435264
435724
  })(), seenFrameNo = -1, prevFrameWasStreamEvent = !1, lastOutWasDelta = !1, macrotaskPending = !1;
435265
435725
  noteBridgeDriveStart(), abortInFlightBgShellReads();
435266
435726
  try {
435267
435727
  for await (let out6 of bridgeAdapter().adapt(teed, ctx)) {
435268
- curFrameNo !== seenFrameNo && (seenFrameNo >= 0 && notifEpilogue(seenFrameNo), prevFrameWasStreamEvent && lastOutWasDelta && await macrotask(), seenFrameNo = curFrameNo, prevFrameWasStreamEvent = curFrameType === "stream_event", macrotaskPending = curFrame !== null && curFrameType !== "stream_event", lastOutWasDelta = !1);
435728
+ curFrameNo !== seenFrameNo && (seenFrameNo >= 0 && guidanceLane.flushFrame(seenFrameNo), seenFrameNo >= 0 && notifEpilogue(seenFrameNo), prevFrameWasStreamEvent && lastOutWasDelta && await macrotask(), seenFrameNo = curFrameNo, prevFrameWasStreamEvent = curFrameType === "stream_event", macrotaskPending = curFrame !== null && curFrameType !== "stream_event", lastOutWasDelta = !1);
435269
435729
  let isDelta = out6.plane === "chrome" && out6.event.kind === "stream_delta";
435270
435730
  if (!isDelta && macrotaskPending && (await macrotask(), macrotaskPending = !1), out6.plane === "transcript") {
435271
435731
  let msg = reduceApiErrorEnvelope(out6.message);
435272
435732
  noteModelEvidenceFrom(msg);
435273
435733
  let w2 = notifWatch.get(seenFrameNo);
435274
- w2 !== void 0 && !w2.rowYielded && isTaskNotificationRow(msg) && (w2.rowYielded = !0), stampTranscriptArrival(msg), yield msg;
435734
+ w2 !== void 0 && !w2.rowYielded && isTaskNotificationRow(msg) && (w2.rowYielded = !0), stampTranscriptArrival(msg), stampCollateralAbort(msg), yield msg;
435275
435735
  } else
435276
435736
  for (let ev of consumeChrome(out6.event)) yield ev;
435277
435737
  lastOutWasDelta = isDelta;
435278
435738
  }
435279
- notifEpilogue(Number.MAX_SAFE_INTEGER);
435739
+ seenFrameNo >= 0 && guidanceLane.flushFrame(seenFrameNo), notifEpilogue(Number.MAX_SAFE_INTEGER);
435280
435740
  } finally {
435281
- noteBridgeDriveEnd();
435741
+ guidanceLane.discard(), collateralAbortCalls.clear(), noteBridgeDriveEnd();
435282
435742
  }
435283
435743
  }
435284
- var BRIDGE_PROBE_ENV, init_upstreamBridge = __esm({
435744
+ var BRIDGE_PROBE_ENV, MAX_COLLATERAL_ABORT_IDS, MAX_COLLATERAL_ABORT_ID_CHARS, init_upstreamBridge = __esm({
435285
435745
  "build-src/src/sema/upstreamBridge.ts"() {
435286
435746
  init_dist();
435287
435747
  init_bridgeAdapter();
@@ -435292,6 +435752,7 @@ var BRIDGE_PROBE_ENV, init_upstreamBridge = __esm({
435292
435752
  init_modelVerificationStore();
435293
435753
  init_retryStatusStore();
435294
435754
  init_debug();
435755
+ init_untrustedDisplayText();
435295
435756
  init_thinkingActivityStore();
435296
435757
  init_dist();
435297
435758
  init_engineBgShellPanelStore();
@@ -435306,6 +435767,7 @@ var BRIDGE_PROBE_ENV, init_upstreamBridge = __esm({
435306
435767
  init_xml();
435307
435768
  init_engineTaskListSync();
435308
435769
  init_engineAgentToolStatsStore();
435770
+ init_engineToolEndGuidance();
435309
435771
  init_enginePromptSuggestionsStore();
435310
435772
  init_dist();
435311
435773
  BRIDGE_PROBE_ENV = {
@@ -435314,6 +435776,7 @@ var BRIDGE_PROBE_ENV, init_upstreamBridge = __esm({
435314
435776
  tick: "SEMA_TICK_PROBE",
435315
435777
  hook: "SEMA_HOOK_PROBE"
435316
435778
  };
435779
+ MAX_COLLATERAL_ABORT_IDS = 1024, MAX_COLLATERAL_ABORT_ID_CHARS = 256;
435317
435780
  }
435318
435781
  });
435319
435782
 
@@ -448415,6 +448878,7 @@ __export(background_agent_store_exports, {
448415
448878
  InMemoryBackgroundAgentStore: () => InMemoryBackgroundAgentStore,
448416
448879
  REVIVED_ROW_CLEARED_FIELDS: () => REVIVED_ROW_CLEARED_FIELDS,
448417
448880
  STALE_RUNNING_REAP_ATTRIBUTION: () => STALE_RUNNING_REAP_ATTRIBUTION,
448881
+ announceTranscriptIntegrityGapOnce: () => announceTranscriptIntegrityGapOnce,
448418
448882
  assertBackgroundAgentReapOptions: () => assertBackgroundAgentReapOptions,
448419
448883
  canAccessAgentRecord: () => canAccessAgentRecord,
448420
448884
  clearRevivedRowTerminalPayload: () => clearRevivedRowTerminalPayload,
@@ -448425,6 +448889,18 @@ function clearRevivedRowTerminalPayload(record2) {
448425
448889
  for (let field of REVIVED_ROW_CLEARED_FIELDS)
448426
448890
  delete record2[field];
448427
448891
  }
448892
+ function announceTranscriptIntegrityGapOnce(handle2, scope, sink2) {
448893
+ if (sink2 === void 0)
448894
+ return;
448895
+ let key = `${scope ?? ""}\0${handle2}`;
448896
+ if (!transcriptIntegrityAnnounced.has(key)) {
448897
+ transcriptIntegrityAnnounced.add(key);
448898
+ try {
448899
+ sink2(handle2, scope);
448900
+ } catch {
448901
+ }
448902
+ }
448903
+ }
448428
448904
  function canAccessAgentRecord(record2, access7) {
448429
448905
  if (access7.scope === void 0 || record2.scope !== access7.scope)
448430
448906
  return !1;
@@ -448516,7 +448992,7 @@ function queryBackgroundAgents(rows2, query2) {
448516
448992
  r.scope === query2.scope && (query2.sessionId !== void 0 && (r.sessionScoped ? r.owner : r.parentSessionId) !== query2.sessionId && r.rootSessionId !== query2.sessionId || query2.status !== void 0 && r.status !== query2.status || out6.push(toSummary(r)));
448517
448993
  return out6.sort((a, b3) => b3.spawnedAt - a.spawnedAt), query2.limit !== void 0 ? out6.slice(0, Math.max(0, query2.limit)) : out6;
448518
448994
  }
448519
- var REVIVED_ROW_CLEARED_FIELDS, BackgroundAgentStoreError, STALE_RUNNING_REAP_ATTRIBUTION, InMemoryBackgroundAgentStore, init_background_agent_store = __esm({
448995
+ var REVIVED_ROW_CLEARED_FIELDS, transcriptIntegrityAnnounced, BackgroundAgentStoreError, STALE_RUNNING_REAP_ATTRIBUTION, InMemoryBackgroundAgentStore, init_background_agent_store = __esm({
448520
448996
  "node_modules/@sema-agent/core/dist/core/background-agent-store.js"() {
448521
448997
  init_harness();
448522
448998
  init_retention_policy();
@@ -448537,6 +449013,7 @@ var REVIVED_ROW_CLEARED_FIELDS, BackgroundAgentStoreError, STALE_RUNNING_REAP_AT
448537
449013
  "editedFiles",
448538
449014
  "usage"
448539
449015
  ];
449016
+ transcriptIntegrityAnnounced = /* @__PURE__ */ new Set();
448540
449017
  BackgroundAgentStoreError = class extends Error {
448541
449018
  code;
448542
449019
  constructor(code2, message) {
@@ -449272,6 +449749,16 @@ var TASK_STOP_PARAMS, init_task_tool_shape = __esm({
449272
449749
 
449273
449750
  // node_modules/@sema-agent/core/dist/core/task-registry-agent.js
449274
449751
  import { randomBytes as randomBytes23 } from "node:crypto";
449752
+ function activeDelegationHandlesLane(core, scope, rootSessionId) {
449753
+ let out6 = [];
449754
+ for (let h of core.handles.values()) {
449755
+ if (h.type !== "background_agent" || h.status !== "running" && h.status !== "pending" || h.scope !== scope)
449756
+ continue;
449757
+ let bh = h;
449758
+ (bh.rootSessionId ?? bh.parentSessionId ?? (bh.sessionScoped ? bh.owner : void 0)) === rootSessionId && out6.push(h.id);
449759
+ }
449760
+ return out6;
449761
+ }
449275
449762
  function ensureDurableHeartbeatLane(core) {
449276
449763
  if (core.durableHeartbeatTimer !== void 0)
449277
449764
  return;
@@ -449386,7 +449873,7 @@ async function reapDurableAgentsLane(core, scope, deps2, policy2) {
449386
449873
  assertRetentionPolicy("reapDurableAgents", policy2);
449387
449874
  let now2 = policy2.now ?? Date.now();
449388
449875
  if (policy2.staleRunningMaxAgeMs !== void 0 && await deps2.store.reap(scope, now2, { staleRunningMaxAgeMs: policy2.staleRunningMaxAgeMs }), policy2.maxAgeMs === void 0 && policy2.keep === void 0)
449389
- return { rowsReaped: 0, sessionsReleased: 0, skippedNoSessions: 0 };
449876
+ return { rowsReaped: 0, sessionsReleased: 0, skippedNoSessions: 0, orphanPlacedReleased: 0 };
449390
449877
  let terminal = (await deps2.store.listByScope(scope)).filter((r) => r.status !== "running" && r.status !== "parked");
449391
449878
  terminal.sort((a, b3) => b3.spawnedAt - a.spawnedAt);
449392
449879
  let doomed = /* @__PURE__ */ new Map();
@@ -449422,7 +449909,12 @@ async function reapDurableAgentsLane(core, scope, deps2, policy2) {
449422
449909
  } catch {
449423
449910
  continue;
449424
449911
  }
449425
- if (rowsReaped++, core.reapedHandles.add(r.handle), deps2.mailbox !== void 0)
449912
+ rowsReaped++;
449913
+ {
449914
+ let staleInProc = core.handles.get(r.handle);
449915
+ staleInProc !== void 0 && staleInProc.status !== "running" && staleInProc.status !== "pending" && staleInProc.status !== "parked" && core.handles.delete(r.handle);
449916
+ }
449917
+ if (core.reapedHandles.add(r.handle), deps2.mailbox !== void 0)
449426
449918
  try {
449427
449919
  await deps2.mailbox.drop(scope, r.handle);
449428
449920
  } catch {
@@ -449436,7 +449928,40 @@ async function reapDurableAgentsLane(core, scope, deps2, policy2) {
449436
449928
  core.reapingHandles.delete(r.handle), core.reapedHandles.delete(r.handle);
449437
449929
  }
449438
449930
  }
449439
- return { rowsReaped, sessionsReleased, skippedNoSessions };
449931
+ let orphanPlacedReleased = 0;
449932
+ if (policy2.maxAgeMs !== void 0 && deps2.sessions !== void 0 && typeof deps2.sessions.listPlaced == "function") {
449933
+ let placed = [];
449934
+ try {
449935
+ placed = await deps2.sessions.listPlaced("subagent", { olderThanMs: policy2.maxAgeMs, scope });
449936
+ } catch {
449937
+ placed = [];
449938
+ }
449939
+ for (let p of placed) {
449940
+ if ("tupleIncomplete" in p || p.scope !== scope || core.claimingHandles.has(p.handle) || core.reapingHandles.has(p.handle))
449941
+ continue;
449942
+ let row2;
449943
+ try {
449944
+ row2 = await deps2.store.get(p.handle, scope);
449945
+ } catch {
449946
+ continue;
449947
+ }
449948
+ if (row2 !== null)
449949
+ continue;
449950
+ let inProc = core.handles.get(p.handle);
449951
+ if (!(inProc !== void 0 && (inProc.status === "running" || inProc.status === "pending" || inProc.status === "parked"))) {
449952
+ try {
449953
+ await deps2.sessions.unpin?.(p.sessionId), await deps2.sessions.release(p.sessionId), orphanPlacedReleased++;
449954
+ } catch {
449955
+ }
449956
+ if (deps2.mailbox !== void 0)
449957
+ try {
449958
+ await deps2.mailbox.drop(scope, p.handle);
449959
+ } catch {
449960
+ }
449961
+ }
449962
+ }
449963
+ }
449964
+ return { rowsReaped, sessionsReleased, skippedNoSessions, orphanPlacedReleased };
449440
449965
  }
449441
449966
  function releaseDurableTranscriptAnchorLane(core, id) {
449442
449967
  let handle2 = core.handles.get(id);
@@ -450019,10 +450544,10 @@ async function deliverToRunningAgentLane(core, id, access7, notification, opts)
450019
450544
  }
450020
450545
  let detachOnTimeout;
450021
450546
  return await bounded(new Promise((resolve57) => {
450022
- let inflight4 = handle2.inFlightDirect ??= /* @__PURE__ */ new Set(), settleOnce = (r) => {
450023
- inflight4.has(settleOnce) && (inflight4.delete(settleOnce), resolve57(r));
450547
+ let inflight3 = handle2.inFlightDirect ??= /* @__PURE__ */ new Set(), settleOnce = (r) => {
450548
+ inflight3.has(settleOnce) && (inflight3.delete(settleOnce), resolve57(r));
450024
450549
  };
450025
- inflight4.add(settleOnce), detachOnTimeout = () => inflight4.delete(settleOnce), (async () => {
450550
+ inflight3.add(settleOnce), detachOnTimeout = () => inflight3.delete(settleOnce), (async () => {
450026
450551
  let result;
450027
450552
  try {
450028
450553
  await handle2.notify?.(notification, opts) === "parked" ? result = handle2.retainedContinuation === !0 ? { ok: !0, disposition: "parked" } : { ok: !1, reason: "not_running" } : result = { ok: !0, disposition: "queued" };
@@ -450190,7 +450715,7 @@ async function stopBackgroundAgentLane(core, handle2) {
450190
450715
  if (arbiter === void 0)
450191
450716
  return {
450192
450717
  content: `${handle2.id} is parked on a pending approval \u2014 stop it by deciding (deny/expire) the pending approval in the durable approval inbox.`,
450193
- details: { task_id: handle2.id, type: "background_agent", status: "parked", retrieval_status: "not_ready", error: "parked_pending_approval" }
450718
+ details: { task_id: handle2.id, type: "background_agent", status: "parked", retrieval_status: "not_ready", error: "parked_pending_approval", code: "parked_pending_approval" }
450194
450719
  };
450195
450720
  let stopWon = !1, arbiterUnreachable = !1;
450196
450721
  try {
@@ -450232,11 +450757,11 @@ async function stopBackgroundAgentLane(core, handle2) {
450232
450757
  }
450233
450758
  return arbiterUnreachable ? {
450234
450759
  content: `${handle2.id} was not stopped: the approval arbitration store was unreachable \u2014 the row stays parked; retry the stop.`,
450235
- details: { task_id: handle2.id, type: "background_agent", status: handle2.status, retrieval_status: "not_ready", error: "park_arbiter_unreachable" },
450760
+ details: { task_id: handle2.id, type: "background_agent", status: handle2.status, retrieval_status: "not_ready", error: "park_arbiter_unreachable", code: "park_arbiter_unreachable" },
450236
450761
  isError: !0
450237
450762
  } : {
450238
450763
  content: `${handle2.id} was not stopped: its pending approval was already consumed (a resume won the arbitration).`,
450239
- details: { task_id: handle2.id, type: "background_agent", status: handle2.status, retrieval_status: "not_ready", error: "park_resume_won" },
450764
+ details: { task_id: handle2.id, type: "background_agent", status: handle2.status, retrieval_status: "not_ready", error: "park_resume_won", code: "park_resume_won" },
450240
450765
  isError: !0
450241
450766
  };
450242
450767
  }
@@ -450474,6 +450999,9 @@ var BLOCK_DEFAULT_TIMEOUT_MS, BLOCK_MAX_TIMEOUT_MS, TASK_PREFIX, TaskRegistry, d
450474
450999
  backgroundAgentCycleSeq(id) {
450475
451000
  return backgroundAgentCycleSeqLane(this.core, id);
450476
451001
  }
451002
+ activeDelegationHandles(scope, rootSessionId) {
451003
+ return activeDelegationHandlesLane(this.core, scope, rootSessionId);
451004
+ }
450477
451005
  reviveBackgroundAgent(id, access7, abort) {
450478
451006
  return reviveBackgroundAgentLane(this.core, id, access7, abort);
450479
451007
  }
@@ -450916,7 +451444,8 @@ The durable record is still marked running (last update ${new Date(row2.updatedA
450916
451444
  type: "background_agent",
450917
451445
  status: "running",
450918
451446
  retrieval_status: "not_ready",
450919
- error: "not_local"
451447
+ error: "not_local",
451448
+ code: "not_local"
450920
451449
  }
450921
451450
  };
450922
451451
  }
@@ -450944,7 +451473,8 @@ The durable record is still marked running (last update ${new Date(row2.updatedA
450944
451473
  type: "workflow",
450945
451474
  status: run2.status,
450946
451475
  retrieval_status: "success",
450947
- error: "not_local"
451476
+ error: "not_local",
451477
+ code: "not_local"
450948
451478
  }
450949
451479
  };
450950
451480
  }
@@ -450963,8 +451493,8 @@ The durable record is still marked running (last update ${new Date(row2.updatedA
450963
451493
  type: "background_agent",
450964
451494
  status: row2.status,
450965
451495
  retrieval_status: row2.status === "parked" ? "not_ready" : "success",
450966
- ...row2.status === "running" ? { error: "not_local" } : {},
450967
- ...row2.status === "parked" ? { error: "parked_pending_approval" } : {}
451496
+ ...row2.status === "running" ? { error: "not_local", code: "not_local" } : {},
451497
+ ...row2.status === "parked" ? { error: "parked_pending_approval", code: "parked_pending_approval" } : {}
450968
451498
  }
450969
451499
  };
450970
451500
  }
@@ -451264,6 +451794,14 @@ var init_image_downsample = __esm({
451264
451794
  }
451265
451795
  });
451266
451796
 
451797
+ // node_modules/@sema-agent/core/dist/core/reminder-disclosure.js
451798
+ var init_reminder_disclosure = __esm({
451799
+ "node_modules/@sema-agent/core/dist/core/reminder-disclosure.js"() {
451800
+ init_reminder_mint();
451801
+ init_untrusted_text();
451802
+ }
451803
+ });
451804
+
451267
451805
  // node_modules/@sema-agent/core/dist/core/memory-engine/content-origin.js
451268
451806
  var init_content_origin = __esm({
451269
451807
  "node_modules/@sema-agent/core/dist/core/memory-engine/content-origin.js"() {
@@ -451279,7 +451817,7 @@ var init_strict_output_schema = __esm({
451279
451817
  // node_modules/@sema-agent/core/dist/core/mcp.js
451280
451818
  import { tmpdir as tmpdir13 } from "node:os";
451281
451819
  import { join as join170 } from "node:path";
451282
- var MCP_PREFIX, MCP_IDLE_TIMEOUT_STDIO_DEFAULT_MS, MCP_IDLE_TIMEOUT_HTTP_DEFAULT_MS, MCP_BLOB_DIR, init_mcp4 = __esm({
451820
+ var MCP_PREFIX, MCP_IDLE_TIMEOUT_STDIO_DEFAULT_MS, MCP_IDLE_TIMEOUT_HTTP_DEFAULT_MS, MCP_BLOB_DIR, LIST_ENTRY_FINGERPRINT_MAX_CHARS, LOOP_REWIND_FINGERPRINT_MAX_CHARS, init_mcp4 = __esm({
451283
451821
  "node_modules/@sema-agent/core/dist/core/mcp.js"() {
451284
451822
  init_protocol_table();
451285
451823
  init_protocol_naming();
@@ -451287,15 +451825,17 @@ var MCP_PREFIX, MCP_IDLE_TIMEOUT_STDIO_DEFAULT_MS, MCP_IDLE_TIMEOUT_HTTP_DEFAULT
451287
451825
  init_stdio3();
451288
451826
  init_streamableHttp();
451289
451827
  init_types12();
451828
+ init_protocol();
451290
451829
  init_image_downsample();
451291
451830
  init_surrogate_safe_slice();
451292
451831
  init_tool_errors();
451293
451832
  init_untrusted_text();
451833
+ init_reminder_disclosure();
451294
451834
  init_content_origin();
451295
451835
  init_strict_output_schema();
451296
451836
  init_protocol_naming();
451297
451837
  init_image_downsample();
451298
- MCP_PREFIX = MCP_NAMESPACE.prefix, MCP_IDLE_TIMEOUT_STDIO_DEFAULT_MS = 30 * 6e4, MCP_IDLE_TIMEOUT_HTTP_DEFAULT_MS = 5 * 6e4, MCP_BLOB_DIR = join170(tmpdir13(), "sema-mcp-blobs");
451838
+ MCP_PREFIX = MCP_NAMESPACE.prefix, MCP_IDLE_TIMEOUT_STDIO_DEFAULT_MS = 30 * 6e4, MCP_IDLE_TIMEOUT_HTTP_DEFAULT_MS = 5 * 6e4, MCP_BLOB_DIR = join170(tmpdir13(), "sema-mcp-blobs"), LIST_ENTRY_FINGERPRINT_MAX_CHARS = 8 * 1024, LOOP_REWIND_FINGERPRINT_MAX_CHARS = 1024 * 1024;
451299
451839
  }
451300
451840
  });
451301
451841
 
@@ -451331,6 +451871,7 @@ var init_fs_pdf = __esm({
451331
451871
  init_mcp4();
451332
451872
  init_pdf2();
451333
451873
  init_fs_shared();
451874
+ init_reminder_disclosure();
451334
451875
  init_pdf2();
451335
451876
  }
451336
451877
  });
@@ -451348,6 +451889,7 @@ var init_fs_read = __esm({
451348
451889
  init_fs_shared();
451349
451890
  init_fs_pdf();
451350
451891
  init_reminder_mint();
451892
+ init_reminder_disclosure();
451351
451893
  }
451352
451894
  });
451353
451895
 
@@ -451405,12 +451947,30 @@ function parseLeadingCommandName(command8, options) {
451405
451947
  reject: "shell operators (pipes, redirects, ;, &&, command substitution, subshells, variable expansion) are not allowed \u2014 run a single simple command"
451406
451948
  };
451407
451949
  let first = trimmed2.split(/\s+/)[0];
451408
- return first.includes("/") ? { reject: "the command must be a bare name resolved via PATH (no path prefix)" } : first.includes("=") ? { reject: "leading environment-variable assignments are not allowed" } : /["'{}*?[\]~]/.test(first) ? { reject: "the command name must be a bare token (no quotes, braces, globs, or ~)" } : { name: first };
451950
+ return first.includes("/") && options?.pathPrefixedNameIsText !== !0 ? { reject: "the command must be a bare name resolved via PATH (no path prefix)" } : first.includes("=") ? { reject: "leading environment-variable assignments are not allowed" } : /["'{}*?[\]~]/.test(first) ? { reject: "the command name must be a bare token (no quotes, braces, globs, or ~)" } : { name: first };
451951
+ }
451952
+ function splitShellCompoundSegments(source, options) {
451953
+ if (SHELL_SEGMENT_HARD_REJECT.test(source))
451954
+ return { reject: "redirection, command/variable substitution, subshells, escapes, and line breaks are not allowed" };
451955
+ let scanned = options?.trailingTerminator !== "keep" ? source.replace(/;\s*$/, "") : source, segments = [], pipeFed = [!1], mask = quoteMask(scanned), quoted = (i) => mask.balanced && mask.quoted[i] === !0, cur = "";
451956
+ for (let i = 0; i < scanned.length; i++) {
451957
+ let c2 = scanned[i];
451958
+ if (quoted(i))
451959
+ cur += c2;
451960
+ else if (c2 === "&")
451961
+ if (scanned[i + 1] === "&")
451962
+ segments.push(cur), cur = "", pipeFed.push(!1), i++;
451963
+ else
451964
+ return { reject: "`&` backgrounding is not allowed \u2014 a backgrounded process outlives the command" };
451965
+ else c2 === "|" ? scanned[i + 1] === "|" ? (segments.push(cur), cur = "", pipeFed.push(!1), i++) : (segments.push(cur), cur = "", pipeFed.push(!0)) : c2 === ";" ? (segments.push(cur), cur = "", pipeFed.push(!1)) : cur += c2;
451966
+ }
451967
+ return segments.push(cur), { segments, pipeFed };
451409
451968
  }
451410
- var SHELL_OPERATORS2, init_bash_readonly_classifier = __esm({
451969
+ var SHELL_OPERATORS2, SHELL_SEGMENT_HARD_REJECT, init_bash_readonly_classifier = __esm({
451411
451970
  "node_modules/@sema-agent/core/dist/tools/fs/bash-readonly-classifier.js"() {
451412
451971
  init_safety();
451413
451972
  SHELL_OPERATORS2 = /[;&|<>$()`\n\r\\]/;
451973
+ SHELL_SEGMENT_HARD_REJECT = /[<>$()`\n\r\\]/;
451414
451974
  }
451415
451975
  });
451416
451976
 
@@ -451637,8 +452197,13 @@ function combinePolicies(...policies) {
451637
452197
  let asked, current5 = req, rewrite, settled, ruleAskText;
451638
452198
  for (let p of policies) {
451639
452199
  let d4 = refuseOutOfContractDecision(await p.check(current5, signal));
451640
- if (d4.action === "deny")
451641
- return rewrite?.updatedInput !== void 0 ? { ...d4, updatedInput: rewrite.updatedInput } : d4;
452200
+ if (d4.action === "deny") {
452201
+ if (rewrite?.updatedInput !== void 0) {
452202
+ let out6 = { ...d4, updatedInput: rewrite.updatedInput }, attested = coreMintedResolutions.get(d4);
452203
+ return attested !== void 0 && coreMintedResolutions.set(out6, attested), out6;
452204
+ }
452205
+ return d4;
452206
+ }
451642
452207
  if (d4.updatedInput !== void 0 && (current5 = { ...current5, args: d4.updatedInput }, rewrite = d4), d4.action === "allow") {
451643
452208
  let supplied = d4.settledBy;
451644
452209
  supplied !== void 0 && (settled = supplied);
@@ -451654,7 +452219,7 @@ function combinePolicies(...policies) {
451654
452219
  }
451655
452220
  };
451656
452221
  }
451657
- var DECISION_REASONS, DECISION_REASON_SET, ALLOW, RETIRED_TEXT_FIELD, RETIRED_TEXT_FIELD_DENY_MESSAGE, COARSE_SHELL_TOOLS, CASE_INSENSITIVE_FS, init_tool_policy = __esm({
452222
+ var DECISION_REASONS, DECISION_REASON_SET, ALLOW, RETIRED_TEXT_FIELD, RETIRED_TEXT_FIELD_DENY_MESSAGE, COARSE_SHELL_TOOLS, CASE_INSENSITIVE_FS, ASK_DENY_RESOLUTION_VALUES, ASK_DENY_RESOLUTION_SET, coreMintedResolutions, init_tool_policy = __esm({
451658
452223
  "node_modules/@sema-agent/core/dist/core/tool-policy.js"() {
451659
452224
  init_ask_class();
451660
452225
  init_fs();
@@ -451663,7 +452228,17 @@ var DECISION_REASONS, DECISION_REASON_SET, ALLOW, RETIRED_TEXT_FIELD, RETIRED_TE
451663
452228
  init_permission_rules();
451664
452229
  init_safety();
451665
452230
  DECISION_REASONS = ["rule", "mode", "hook", "safety", "classifier", "persisted_rule", "sandbox", "org_rule", "org_unavailable"], DECISION_REASON_SET = new Set(DECISION_REASONS), ALLOW = { action: "allow" }, RETIRED_TEXT_FIELD = "reason", RETIRED_TEXT_FIELD_DENY_MESSAGE = `a permission decision carries the retired "${RETIRED_TEXT_FIELD}" field \u2014 rename it to "message" (the one text field a decision carries); denied fail-closed rather than executing a decision whose text this layer cannot read`;
451666
- COARSE_SHELL_TOOLS = ["Bash", "Monitor"], CASE_INSENSITIVE_FS = process.platform === "darwin" || process.platform === "win32";
452231
+ COARSE_SHELL_TOOLS = ["Bash", "Monitor"], CASE_INSENSITIVE_FS = process.platform === "darwin" || process.platform === "win32", ASK_DENY_RESOLUTION_VALUES = [
452232
+ "human_refused",
452233
+ "window_expired",
452234
+ "no_approver",
452235
+ "blanket_allow_refused",
452236
+ "approver_unavailable",
452237
+ "task_aborted",
452238
+ "presentation_failed",
452239
+ "approver_error",
452240
+ "approver_contract"
452241
+ ], ASK_DENY_RESOLUTION_SET = new Set(ASK_DENY_RESOLUTION_VALUES), coreMintedResolutions = /* @__PURE__ */ new WeakMap();
451667
452242
  }
451668
452243
  });
451669
452244
 
@@ -451699,6 +452274,28 @@ var init_delegation_provenance = __esm({
451699
452274
  }
451700
452275
  });
451701
452276
 
452277
+ // node_modules/@sema-agent/core/dist/core/memory-engine/types.js
452278
+ var init_types27 = __esm({
452279
+ "node_modules/@sema-agent/core/dist/core/memory-engine/types.js"() {
452280
+ }
452281
+ });
452282
+
452283
+ // node_modules/@sema-agent/core/dist/core/memory-engine/layout.js
452284
+ import { closeSync as closeSync13, constants as fsConstants7, copyFileSync as copyFileSync6, existsSync as existsSync28, fstatSync as fstatSync3, fsyncSync as fsyncSync10, lstatSync as lstatSync4, mkdirSync as mkdirSync22, openSync as openSync14, readFileSync as readFileSync39, readdirSync as readdirSync12, realpathSync as realpathSync11, renameSync as renameSync13, rmSync as rmSync7, rmdirSync as rmdirSync3, statSync as statSync14, unlinkSync as unlinkSync11, writeFileSync as writeFileSync21, writeSync as writeSync7 } from "node:fs";
452285
+ var O_WRONLY, O_CREAT, O_TRUNC, O_NOFOLLOW3, O_EXCL, init_layout = __esm({
452286
+ "node_modules/@sema-agent/core/dist/core/memory-engine/layout.js"() {
452287
+ init_types27();
452288
+ ({ O_WRONLY, O_CREAT, O_TRUNC, O_NOFOLLOW: O_NOFOLLOW3, O_EXCL } = fsConstants7);
452289
+ }
452290
+ });
452291
+
452292
+ // node_modules/@sema-agent/core/dist/core/memory-engine/delegation-settlement.js
452293
+ var init_delegation_settlement = __esm({
452294
+ "node_modules/@sema-agent/core/dist/core/memory-engine/delegation-settlement.js"() {
452295
+ init_layout();
452296
+ }
452297
+ });
452298
+
451702
452299
  // node_modules/@sema-agent/core/dist/core/runner/synthetic-tools.js
451703
452300
  var OUTPUT_TOOL_NAME, REPORT_FINDING_SCHEMA, SKILL_CONTENT_MAX_CHARS, init_synthetic_tools = __esm({
451704
452301
  "node_modules/@sema-agent/core/dist/core/runner/synthetic-tools.js"() {
@@ -451753,21 +452350,6 @@ var WORKTREE_PARENT, init_git_worktree_env = __esm({
451753
452350
  }
451754
452351
  });
451755
452352
 
451756
- // node_modules/@sema-agent/core/dist/core/memory-engine/types.js
451757
- var init_types27 = __esm({
451758
- "node_modules/@sema-agent/core/dist/core/memory-engine/types.js"() {
451759
- }
451760
- });
451761
-
451762
- // node_modules/@sema-agent/core/dist/core/memory-engine/layout.js
451763
- import { closeSync as closeSync13, constants as fsConstants7, copyFileSync as copyFileSync6, existsSync as existsSync28, fstatSync as fstatSync3, fsyncSync as fsyncSync10, lstatSync as lstatSync4, mkdirSync as mkdirSync22, openSync as openSync14, readFileSync as readFileSync39, readdirSync as readdirSync12, realpathSync as realpathSync11, renameSync as renameSync13, rmSync as rmSync7, rmdirSync as rmdirSync3, statSync as statSync14, unlinkSync as unlinkSync11, writeFileSync as writeFileSync21, writeSync as writeSync7 } from "node:fs";
451764
- var O_WRONLY, O_CREAT, O_TRUNC, O_NOFOLLOW3, O_EXCL, init_layout = __esm({
451765
- "node_modules/@sema-agent/core/dist/core/memory-engine/layout.js"() {
451766
- init_types27();
451767
- ({ O_WRONLY, O_CREAT, O_TRUNC, O_NOFOLLOW: O_NOFOLLOW3, O_EXCL } = fsConstants7);
451768
- }
451769
- });
451770
-
451771
452353
  // node_modules/@sema-agent/core/dist/core/memory-engine/scope-contract.js
451772
452354
  var CASE_INSENSITIVE_FS2, FATAL_UTF8, init_scope_contract = __esm({
451773
452355
  "node_modules/@sema-agent/core/dist/core/memory-engine/scope-contract.js"() {
@@ -451841,6 +452423,25 @@ var init_retain_ledger = __esm({
451841
452423
  import { closeSync as closeSync14, constants as FS, existsSync as existsSync29, fstatSync as fstatSync4, linkSync as linkSync2, mkdirSync as mkdirSync23, openSync as openSync15, readFileSync as readFileSync40, readSync as readSync4, realpathSync as realpathSync12, renameSync as renameSync14, truncateSync, unlinkSync as unlinkSync12, writeFileSync as writeFileSync22, writeSync as writeSync8, fsyncSync as fsyncSync11 } from "node:fs";
451842
452424
  import { basename as basename51, dirname as dirname77, join as join171, resolve as resolvePath3 } from "node:path";
451843
452425
  import { createHash as createHash25, randomBytes as randomBytes25 } from "node:crypto";
452426
+ function writeThenLink(target, content) {
452427
+ ensureDir(dirnameOf(target));
452428
+ let tmp = `${target}.${process.pid}.${randomBytes25(6).toString("hex")}.tmp`, linked = !1;
452429
+ try {
452430
+ let fd2 = openSync15(tmp, FS.O_CREAT | FS.O_EXCL | FS.O_WRONLY, 384);
452431
+ try {
452432
+ writeFileSync22(fd2, content), fsyncSync11(fd2);
452433
+ } finally {
452434
+ closeSync14(fd2);
452435
+ }
452436
+ linkSync2(tmp, target), linked = !0;
452437
+ } finally {
452438
+ try {
452439
+ unlinkSync12(tmp);
452440
+ } catch {
452441
+ }
452442
+ }
452443
+ linked && fsyncDir(dirnameOf(target));
452444
+ }
451844
452445
  function ensureDir(dir) {
451845
452446
  mkdirSync23(dir, { recursive: !0, mode: 448 });
451846
452447
  }
@@ -451933,7 +452534,48 @@ function truncateTornTail(path28) {
451933
452534
  `);
451934
452535
  truncateSync(path28, lastNl === -1 ? 0 : Buffer.byteLength(raw2.slice(0, lastNl + 1), "utf8"));
451935
452536
  }
451936
- var AppendLog, init_fs_atomic = __esm({
452537
+ function acquireStoreDirLock(dir, opts) {
452538
+ let fileName = opts.fileName ?? "LOCK", lockPath2 = join171(dir, fileName), key = `${fileName}@${canonicalStoreKey(dir)}`, lease = (entry2) => {
452539
+ let released = !1;
452540
+ return {
452541
+ lockPath: lockPath2,
452542
+ release: () => {
452543
+ if (!released && (released = !0, heldStoreDirLocks.get(key) === entry2 && (entry2.refs -= 1, !(entry2.refs > 0)))) {
452544
+ if (entry2.lock.release()) {
452545
+ heldStoreDirLocks.delete(key);
452546
+ return;
452547
+ }
452548
+ console.warn(`[sema] file store: the ${opts.label} directory fence at ${lockPath2} could not be handed back \u2014 the removal could not be proven, so a lock file naming this live process (pid ${process.pid}) may still be there. While it is, another process opening that directory is refused by name; the next open of it in THIS process finishes the cleanup or refuses by name. After this process exits the file is reclaimed as a stale lock ONLY if it is readable and its directory writable \u2014 otherwise it has to be removed by hand.`);
452549
+ }
452550
+ }
452551
+ };
452552
+ }, existing = heldStoreDirLocks.get(key);
452553
+ if (existing !== void 0) {
452554
+ if (existing.refs > 0 || existing.lock.resumeAbandoned())
452555
+ return existing.refs += 1, lease(existing);
452556
+ heldStoreDirLocks.delete(key);
452557
+ }
452558
+ let lock2 = new BootLock(lockPath2);
452559
+ try {
452560
+ lock2.acquire();
452561
+ } catch (err8) {
452562
+ if (err8 instanceof FileStoreLockError) {
452563
+ let who = err8.ownerPid !== void 0 ? ` (pid ${err8.ownerPid})` : "", single = "This backend is SINGLE-WRITER per directory: a second process replays a private view (both sides can win a once-only decision) and its next compaction erases the records it never loaded.";
452564
+ throw new FileStoreLockError(err8.code, err8.code === "store.lock_unreadable" ? `file store: the ${opts.label} directory (${dir}) cannot be opened \u2014 ${err8.message}` : err8.code === "store.dir_claiming" ? `file store: another OS process${who} is claiming this data dir \u2014 it is reclaiming the ${opts.label} directory (${dir}) from a lock a crashed owner left behind. ${single} Retry in a moment: either that process finishes and owns the directory, or it dies and the next start reclaims it.` : `file store: another OS process${who} is using the ${opts.label} directory (${dir}). ${single} Stop the other process, point this one at a different data root, or use the pg/tidb backend for real multi-process concurrency.`, err8.code === "store.lock_unreadable" ? err8.lockPath : lockPath2, err8.ownerPid);
452565
+ }
452566
+ throw err8;
452567
+ }
452568
+ let entry = { lock: lock2, refs: 1 };
452569
+ return heldStoreDirLocks.set(key, entry), lease(entry);
452570
+ }
452571
+ function isProcessRunning4(pid) {
452572
+ try {
452573
+ return process.kill(pid, 0), !0;
452574
+ } catch (err8) {
452575
+ return err8.code === "EPERM";
452576
+ }
452577
+ }
452578
+ var AppendLog, FileStoreLockError, MAX_RECLAIM_DEPTH, MAX_ACQUIRE_ATTEMPTS, abandonedLocks, BootLock, heldStoreDirLocks, init_fs_atomic = __esm({
451937
452579
  "node_modules/@sema-agent/core/dist/stores/file/fs-atomic.js"() {
451938
452580
  AppendLog = class {
451939
452581
  fd;
@@ -452010,6 +452652,127 @@ var AppendLog, init_fs_atomic = __esm({
452010
452652
  }
452011
452653
  }
452012
452654
  };
452655
+ FileStoreLockError = class extends Error {
452656
+ code;
452657
+ lockPath;
452658
+ ownerPid;
452659
+ name = "FileStoreLockError";
452660
+ constructor(code2, message, lockPath2, ownerPid) {
452661
+ super(message), this.code = code2, this.lockPath = lockPath2, this.ownerPid = ownerPid;
452662
+ }
452663
+ }, MAX_RECLAIM_DEPTH = 8, MAX_ACQUIRE_ATTEMPTS = 4, abandonedLocks = /* @__PURE__ */ new Set(), BootLock = class _BootLock {
452664
+ lockPath;
452665
+ held = !1;
452666
+ spentVerdict;
452667
+ constructor(lockPath2) {
452668
+ this.lockPath = lockPath2;
452669
+ }
452670
+ acquire() {
452671
+ this.acquireWithin(0);
452672
+ }
452673
+ acquireWithin(depth) {
452674
+ for (let attempt = 0; attempt < MAX_ACQUIRE_ATTEMPTS; attempt++) {
452675
+ try {
452676
+ this.writeLock(), this.held = !0, abandonedLocks.delete(this.abandonKey);
452677
+ return;
452678
+ } catch (err8) {
452679
+ if (err8.code !== "EEXIST")
452680
+ throw err8;
452681
+ }
452682
+ let owner = this.inspectLock();
452683
+ if (owner.state === "absent")
452684
+ continue;
452685
+ if (owner.state === "unreadable")
452686
+ throw new FileStoreLockError("store.lock_unreadable", `file store: lock file at ${this.lockPath} is unreadable/corrupt; remove it manually if it is stale`, this.lockPath);
452687
+ if (owner.pid === process.pid && abandonedLocks.has(this.abandonKey)) {
452688
+ this.pruneOwnAbandoned();
452689
+ return;
452690
+ }
452691
+ if (isProcessRunning4(owner.pid))
452692
+ throw new FileStoreLockError("store.dir_in_use", `file store: another instance (pid ${owner.pid}) owns this data dir (${dirnameOf(this.lockPath)})`, this.lockPath, owner.pid);
452693
+ if (depth >= MAX_RECLAIM_DEPTH)
452694
+ throw new FileStoreLockError("store.lock_unreadable", `file store: lock file at ${this.lockPath} is buried under ${depth} nested stale reclaim gates (repeated crashes mid-reclaim); remove the ${basenameOf(this.lockPath)}.claim.* files manually`, this.lockPath);
452695
+ let gate = new _BootLock(`${this.lockPath}.claim.${owner.pid}`);
452696
+ try {
452697
+ gate.acquireWithin(depth + 1);
452698
+ } catch (err8) {
452699
+ throw err8 instanceof FileStoreLockError && err8.code === "store.dir_in_use" && err8.ownerPid !== void 0 ? new FileStoreLockError("store.dir_claiming", `file store: another instance${err8.ownerPid !== void 0 ? ` (pid ${err8.ownerPid})` : ""} is claiming this data dir (${dirnameOf(this.lockPath)}) from a stale lock`, this.lockPath, err8.ownerPid) : err8;
452700
+ }
452701
+ try {
452702
+ let under = this.inspectLock();
452703
+ if (under.state === "owner" && under.pid === owner.pid)
452704
+ try {
452705
+ unlinkSync12(this.lockPath);
452706
+ } catch {
452707
+ }
452708
+ else if (under.state !== "absent")
452709
+ continue;
452710
+ this.publishOrLoseRace();
452711
+ return;
452712
+ } finally {
452713
+ gate.release();
452714
+ }
452715
+ }
452716
+ throw new FileStoreLockError("store.dir_in_use", `file store: ownership of this data dir (${dirnameOf(this.lockPath)}) kept changing under us (${MAX_ACQUIRE_ATTEMPTS} attempts); another instance is starting and stopping on the same directory`, this.lockPath);
452717
+ }
452718
+ publishOrLoseRace() {
452719
+ try {
452720
+ this.writeLock(), this.held = !0, abandonedLocks.delete(this.abandonKey);
452721
+ } catch (err8) {
452722
+ throw err8.code === "EEXIST" ? new FileStoreLockError("store.dir_in_use", "file store: another instance won the lock race for this data dir", this.lockPath) : err8;
452723
+ }
452724
+ }
452725
+ pruneOwnAbandoned() {
452726
+ try {
452727
+ unlinkSync12(this.lockPath);
452728
+ } catch (err8) {
452729
+ throw new FileStoreLockError("store.lock_unreadable", `file store: this process still owns the lock file at ${this.lockPath} from an earlier release that could not remove it, and removing it now failed too (${String(err8.message)}); remove it manually`, this.lockPath, process.pid);
452730
+ }
452731
+ abandonedLocks.delete(this.abandonKey), this.publishOrLoseRace();
452732
+ }
452733
+ writeLock() {
452734
+ writeThenLink(this.lockPath, String(process.pid));
452735
+ }
452736
+ get abandonKey() {
452737
+ return resolvePath3(this.lockPath);
452738
+ }
452739
+ inspectLock() {
452740
+ let raw2;
452741
+ try {
452742
+ raw2 = readFileSync40(this.lockPath, "utf8").trim();
452743
+ } catch (err8) {
452744
+ return err8.code === "ENOENT" ? { state: "absent" } : { state: "unreadable" };
452745
+ }
452746
+ if (!/^[1-9][0-9]*$/.test(raw2))
452747
+ return { state: "unreadable" };
452748
+ let pid = Number.parseInt(raw2, 10);
452749
+ return Number.isInteger(pid) && pid > 0 ? { state: "owner", pid } : { state: "unreadable" };
452750
+ }
452751
+ release() {
452752
+ return this.held ? (this.held = !1, this.spentVerdict = this.removeOwnLock(), this.spentVerdict) : this.spentVerdict ?? !0;
452753
+ }
452754
+ removeOwnLock() {
452755
+ let before = this.inspectLock();
452756
+ if (before.state === "absent" || before.state === "owner" && before.pid !== process.pid)
452757
+ return abandonedLocks.delete(this.abandonKey), !0;
452758
+ if (before.state === "unreadable")
452759
+ return abandonedLocks.add(this.abandonKey), !1;
452760
+ try {
452761
+ unlinkSync12(this.lockPath);
452762
+ } catch {
452763
+ }
452764
+ let after = this.inspectLock(), gone = after.state === "absent" || after.state === "owner" && after.pid !== process.pid;
452765
+ return gone ? abandonedLocks.delete(this.abandonKey) : abandonedLocks.add(this.abandonKey), gone;
452766
+ }
452767
+ resumeAbandoned() {
452768
+ if (this.held)
452769
+ return !0;
452770
+ if (!abandonedLocks.has(this.abandonKey))
452771
+ return !1;
452772
+ let owner = this.inspectLock();
452773
+ return owner.state !== "owner" || owner.pid !== process.pid ? !1 : (this.held = !0, this.spentVerdict = void 0, abandonedLocks.delete(this.abandonKey), !0);
452774
+ }
452775
+ }, heldStoreDirLocks = /* @__PURE__ */ new Map();
452013
452776
  }
452014
452777
  });
452015
452778
 
@@ -452044,8 +452807,11 @@ var EXTRA_TOOLS_MAX_FACTORY_CALLS_PER_TREE, EXTRA_TOOLS_BUDGET_NOTE, FAILED_SESS
452044
452807
  "node_modules/@sema-agent/core/dist/agents/subagent.js"() {
452045
452808
  init_build3();
452046
452809
  init_tool_policy();
452810
+ init_tools3();
452047
452811
  init_surrogate_safe_slice();
452048
452812
  init_delegation_provenance();
452813
+ init_delegation_settlement();
452814
+ init_layout();
452049
452815
  init_roles();
452050
452816
  init_synthetic_tools();
452051
452817
  init_tool_disclosure();
@@ -452835,6 +453601,28 @@ function foldSpacing(s) {
452835
453601
  function reject2(code2, message) {
452836
453602
  return { reject: { code: code2, message } };
452837
453603
  }
453604
+ function commandBasename(name) {
453605
+ return name.slice(name.lastIndexOf("/") + 1);
453606
+ }
453607
+ function ruleLaneShapeOf(command8, reading) {
453608
+ let split = splitShellCompoundSegments(command8, { trailingTerminator: reading.terminator });
453609
+ if ("reject" in split)
453610
+ return { reject: split.reject };
453611
+ let names = [];
453612
+ for (let segment2 of split.segments) {
453613
+ let floor = parseLeadingCommandName(segment2, { ...RULE_LANE_FLOOR, quotedOperatorsAreText: reading.quotedOperatorsAreText });
453614
+ if ("reject" in floor)
453615
+ return {
453616
+ reject: split.segments.length > 1 ? `the segment "${escapeForDisclosure(segment2.trim())}" is not a single simple command (${floor.reject})` : floor.reject
453617
+ };
453618
+ if (SHELL_RESERVED_WORDS.has(floor.name))
453619
+ return {
453620
+ reject: `"${escapeForDisclosure(floor.name)}" is a shell keyword, not a command name \u2014 a control structure's real program is not named by the text this lane compares`
453621
+ };
453622
+ names.push(floor.name);
453623
+ }
453624
+ return { segments: split.segments, names };
453625
+ }
452838
453626
  function escapeForDisclosure(value) {
452839
453627
  let text2;
452840
453628
  try {
@@ -452861,11 +453649,14 @@ function parseAllowRuleText(text2, opts) {
452861
453649
  let content = parsed.ruleContent, prefixBody = /^(.+):\*$/.exec(content)?.[1], match = prefixBody !== void 0 ? "prefix" : "exact", body = prefixBody ?? content;
452862
453650
  if (body.includes("*"))
452863
453651
  return reject2("unsupported.wildcard", `wildcard rule forms are not supported in this version ("${text2}")`);
452864
- let floor = parseLeadingCommandName(body);
452865
- if ("reject" in floor)
452866
- return body.trim() === "" ? reject2("invalid.empty_command", `rule "${text2}" names no command`) : reject2("invalid.not_simple_command", `rule "${text2}" is not a single simple command (${floor.reject})`);
452867
- if (match === "prefix" && BARE_INTERPRETER_NAMES.has(floor.name) && opts?.direction !== "tighten")
452868
- return reject2("invalid.bare_interpreter_prefix", `prefix rule "${text2}" is headed by the interpreter "${floor.name}" \u2014 such a rule authorizes running arbitrary programs, which one approval click cannot be read as having granted (an exact rule naming the whole command line is accepted)`);
453652
+ let shape = ruleLaneShapeOf(body, MATCH_READING);
453653
+ if ("reject" in shape)
453654
+ return body.trim() === "" ? reject2("invalid.empty_command", `rule "${text2}" names no command`) : reject2("invalid.not_simple_command", `rule "${text2}" is not a command this lane can name (${shape.reject})`);
453655
+ if (match === "prefix" && shape.segments.length > 1)
453656
+ return reject2("invalid.not_simple_command", `prefix rule "${text2}" names more than one command \u2014 a prefix admits anything appended to its body, so only the exact form may name a connector chain`);
453657
+ let head = commandBasename(shape.names[0] ?? "");
453658
+ if (match === "prefix" && BARE_INTERPRETER_NAMES.has(head) && opts?.direction !== "tighten")
453659
+ return reject2("invalid.bare_interpreter_prefix", `prefix rule "${text2}" is headed by the interpreter "${head}" \u2014 such a rule authorizes running arbitrary programs, which one approval click cannot be read as having granted (an exact rule naming the whole command line is accepted)`);
452869
453660
  let command8 = foldSpacing(body);
452870
453661
  return command8 === void 0 ? reject2("invalid.unbalanced_quotes", `rule "${text2}" has unbalanced quoting, so the command it names is not determinable`) : { rule: { rule: formatAllowRuleText(command8, match), tool: "Bash", match, command: command8 } };
452871
453662
  }
@@ -452875,19 +453666,11 @@ function formatAllowRuleText(command8, match) {
452875
453666
  function isRuleLive(rule) {
452876
453667
  return rule.adds.length > 0;
452877
453668
  }
452878
- var MAX_RULE_TEXT_CHARS, BARE_INTERPRETER_NAMES, SUGGESTION_LEXICON, LEXICON_BODIES, CONTROL_CHARS_RE, CONTROL_CHARS_GLOBAL_RE, DISCLOSED_RULE_TEXT_MAX_CHARS, init_permission_rule_model = __esm({
453669
+ var MAX_RULE_TEXT_CHARS, BARE_INTERPRETER_NAMES, SHELL_RESERVED_WORDS, SUGGESTION_LEXICON, LEXICON_BODIES, RULE_LANE_FLOOR, MATCH_READING, CONTROL_CHARS_RE, CONTROL_CHARS_GLOBAL_RE, DISCLOSED_RULE_TEXT_MAX_CHARS, init_permission_rule_model = __esm({
452879
453670
  "node_modules/@sema-agent/core/dist/core/permission-rule-model.js"() {
452880
453671
  init_permission_rules();
452881
453672
  init_bash_readonly_classifier();
452882
453673
  MAX_RULE_TEXT_CHARS = 512, BARE_INTERPRETER_NAMES = /* @__PURE__ */ new Set([
452883
- "bash",
452884
- "sh",
452885
- "zsh",
452886
- "ksh",
452887
- "csh",
452888
- "tcsh",
452889
- "dash",
452890
- "fish",
452891
453674
  "node",
452892
453675
  "deno",
452893
453676
  "bun",
@@ -452898,15 +453681,108 @@ var MAX_RULE_TEXT_CHARS, BARE_INTERPRETER_NAMES, SUGGESTION_LEXICON, LEXICON_BOD
452898
453681
  "ruby",
452899
453682
  "php",
452900
453683
  "osascript",
452901
- "env",
453684
+ "java",
453685
+ "dotnet",
453686
+ "mono",
453687
+ "lua",
453688
+ "luajit",
453689
+ "julia",
453690
+ "Rscript",
453691
+ "tclsh",
453692
+ "groovy",
453693
+ "scala",
453694
+ "awk",
453695
+ "gawk",
453696
+ "mawk",
453697
+ "nawk",
453698
+ "sed",
453699
+ "bash",
453700
+ "sh",
453701
+ "zsh",
453702
+ "ksh",
453703
+ "csh",
453704
+ "tcsh",
453705
+ "dash",
453706
+ "fish",
453707
+ "cmd",
453708
+ "powershell",
453709
+ "pwsh",
453710
+ "busybox",
453711
+ "source",
453712
+ ".",
453713
+ "trap",
452902
453714
  "eval",
452903
453715
  "exec",
453716
+ "command",
453717
+ "builtin",
453718
+ "enable",
453719
+ "compgen",
453720
+ "complete",
453721
+ "bind",
453722
+ "mapfile",
453723
+ "readarray",
453724
+ "env",
453725
+ "noglob",
452904
453726
  "xargs",
452905
- "nohup",
452906
453727
  "sudo",
452907
453728
  "doas",
453729
+ "pkexec",
452908
453730
  "su",
452909
- "ssh"
453731
+ "runuser",
453732
+ "ssh",
453733
+ "chroot",
453734
+ "setpriv",
453735
+ "nohup",
453736
+ "nice",
453737
+ "ionice",
453738
+ "chrt",
453739
+ "taskset",
453740
+ "stdbuf",
453741
+ "timeout",
453742
+ "time",
453743
+ "watch",
453744
+ "setsid",
453745
+ "flock",
453746
+ "unshare",
453747
+ "nsenter",
453748
+ "script",
453749
+ "numactl",
453750
+ "prlimit",
453751
+ "systemd-run",
453752
+ "parallel",
453753
+ "strace",
453754
+ "ltrace",
453755
+ "valgrind",
453756
+ "gdb",
453757
+ "lldb",
453758
+ "perf",
453759
+ "firejail",
453760
+ "bwrap"
453761
+ ]), SHELL_RESERVED_WORDS = /* @__PURE__ */ new Set([
453762
+ "!",
453763
+ "[[",
453764
+ "]]",
453765
+ "{",
453766
+ "}",
453767
+ "((",
453768
+ "))",
453769
+ "case",
453770
+ "esac",
453771
+ "coproc",
453772
+ "do",
453773
+ "done",
453774
+ "elif",
453775
+ "else",
453776
+ "fi",
453777
+ "for",
453778
+ "function",
453779
+ "if",
453780
+ "in",
453781
+ "select",
453782
+ "then",
453783
+ "time",
453784
+ "until",
453785
+ "while"
452910
453786
  ]), SUGGESTION_LEXICON = [
452911
453787
  "git status",
452912
453788
  "git log",
@@ -453034,6 +453910,7 @@ var MAX_RULE_TEXT_CHARS, BARE_INTERPRETER_NAMES, SUGGESTION_LEXICON, LEXICON_BOD
453034
453910
  "gh search prs",
453035
453911
  "gh search code"
453036
453912
  ], LEXICON_BODIES = SUGGESTION_LEXICON.map((b3) => b3.split(" "));
453913
+ RULE_LANE_FLOOR = { pathPrefixedNameIsText: !0 }, MATCH_READING = { terminator: "keep", quotedOperatorsAreText: !1 };
453037
453914
  CONTROL_CHARS_RE = /[\u0000-\u0008\u000A-\u001F\u007F-\u009F\p{Cf}\u2028\u2029]/u, CONTROL_CHARS_GLOBAL_RE = new RegExp(CONTROL_CHARS_RE.source, "gu"), DISCLOSED_RULE_TEXT_MAX_CHARS = 120;
453038
453915
  }
453039
453916
  });
@@ -453343,9 +454220,9 @@ var init_reasoning = __esm({
453343
454220
 
453344
454221
  // node_modules/@sema-agent/core/dist/brain/status-sink.js
453345
454222
  import { AsyncLocalStorage as AsyncLocalStorage8 } from "node:async_hooks";
453346
- var statusSinkStore, telemetrySinkStore, init_status_sink = __esm({
454223
+ var statusSinkStore, telemetrySinkStore, reasoningFactsSinkStore, init_status_sink = __esm({
453347
454224
  "node_modules/@sema-agent/core/dist/brain/status-sink.js"() {
453348
- statusSinkStore = new AsyncLocalStorage8(), telemetrySinkStore = new AsyncLocalStorage8();
454225
+ statusSinkStore = new AsyncLocalStorage8(), telemetrySinkStore = new AsyncLocalStorage8(), reasoningFactsSinkStore = new AsyncLocalStorage8();
453349
454226
  }
453350
454227
  });
453351
454228
 
@@ -453538,6 +454415,7 @@ var init_agent_transcript_tool = __esm({
453538
454415
  init_build3();
453539
454416
  init_tools3();
453540
454417
  init_background_agent_store();
454418
+ init_task_registry();
453541
454419
  init_untrusted_text();
453542
454420
  init_subagent_steps();
453543
454421
  init_subagent();
@@ -453559,6 +454437,7 @@ var uplinkSeqGlobal, REVIVE_LEASE_TTL_MS, init_send_message_tool = __esm({
453559
454437
  init_tools3();
453560
454438
  init_task_registry();
453561
454439
  init_background_agent_store();
454440
+ init_harness();
453562
454441
  init_mailbox_store();
453563
454442
  init_observer();
453564
454443
  init_retain_ledger();
@@ -453814,6 +454693,20 @@ var ONE_DAY_MS, ONE_WEEK_MS, ONE_MONTH_MS, init_memory_recall = __esm({
453814
454693
  }
453815
454694
  });
453816
454695
 
454696
+ // node_modules/@sema-agent/core/dist/core/memory-engine/frontmatter.js
454697
+ var init_frontmatter = __esm({
454698
+ "node_modules/@sema-agent/core/dist/core/memory-engine/frontmatter.js"() {
454699
+ init_types27();
454700
+ }
454701
+ });
454702
+
454703
+ // node_modules/@sema-agent/core/dist/core/memory-engine/provenance-wording.js
454704
+ var MEMORY_EXPOSURE_HANDLE_TAG, MEMORY_SEARCH_BAND_ORDER_HEADER, init_provenance_wording = __esm({
454705
+ "node_modules/@sema-agent/core/dist/core/memory-engine/provenance-wording.js"() {
454706
+ MEMORY_EXPOSURE_HANDLE_TAG = "[external-origin]", MEMORY_SEARCH_BAND_ORDER_HEADER = `entries without the ${MEMORY_EXPOSURE_HANDLE_TAG} tag first, best match first within each group`;
454707
+ }
454708
+ });
454709
+
453817
454710
  // node_modules/@sema-agent/core/dist/core/memory-engine/tools.js
453818
454711
  var MEMORY_SEARCH_TOOL_NAME2, MEMORY_GET_TOOL_NAME2, MEMORY_GET_PAGE_CAP_BYTES, SEARCH_HINT, SEARCH_DESCRIPTION, GET_HINT, GET_DESCRIPTION, init_tools5 = __esm({
453819
454712
  "node_modules/@sema-agent/core/dist/core/memory-engine/tools.js"() {
@@ -453821,6 +454714,8 @@ var MEMORY_SEARCH_TOOL_NAME2, MEMORY_GET_TOOL_NAME2, MEMORY_GET_PAGE_CAP_BYTES,
453821
454714
  init_tools3();
453822
454715
  init_untrusted_text();
453823
454716
  init_memory_recall();
454717
+ init_frontmatter();
454718
+ init_provenance_wording();
453824
454719
  MEMORY_SEARCH_TOOL_NAME2 = "memory_search", MEMORY_GET_TOOL_NAME2 = "memory_get", MEMORY_GET_PAGE_CAP_BYTES = 24 * 1024, SEARCH_HINT = "Search this session's long-term memory entries by keyword \u2014 check memory before saying you do not have or do not know something.", SEARCH_DESCRIPTION = [
453825
454720
  SEARCH_HINT,
453826
454721
  "",
@@ -453858,19 +454753,20 @@ var MAX_MEMORY_BYTES, init_memory4 = __esm({
453858
454753
  }
453859
454754
  });
453860
454755
 
453861
- // node_modules/@sema-agent/core/dist/core/memory-engine/frontmatter.js
453862
- var init_frontmatter = __esm({
453863
- "node_modules/@sema-agent/core/dist/core/memory-engine/frontmatter.js"() {
453864
- init_types27();
453865
- }
453866
- });
453867
-
453868
454756
  // node_modules/@sema-agent/core/dist/core/memory-engine/header-hints.js
453869
454757
  var init_header_hints = __esm({
453870
454758
  "node_modules/@sema-agent/core/dist/core/memory-engine/header-hints.js"() {
453871
454759
  }
453872
454760
  });
453873
454761
 
454762
+ // node_modules/@sema-agent/core/dist/core/memory-engine/origin-clearance.js
454763
+ var init_origin_clearance = __esm({
454764
+ "node_modules/@sema-agent/core/dist/core/memory-engine/origin-clearance.js"() {
454765
+ init_layout();
454766
+ init_types27();
454767
+ }
454768
+ });
454769
+
453874
454770
  // node_modules/@sema-agent/core/dist/core/memory-engine/scan.js
453875
454771
  var init_scan = __esm({
453876
454772
  "node_modules/@sema-agent/core/dist/core/memory-engine/scan.js"() {
@@ -453916,7 +454812,7 @@ var init_export_bundle = __esm({
453916
454812
  });
453917
454813
 
453918
454814
  // node_modules/@sema-agent/core/dist/core/memory-engine/engine.js
453919
- var MEMORY_INDEX_MAX_BYTES, init_engine4 = __esm({
454815
+ var MEMORY_INDEX_MAX_BYTES, DEFAULT_HOLD_SETTLE_TIMEOUT_MS, init_engine4 = __esm({
453920
454816
  "node_modules/@sema-agent/core/dist/core/memory-engine/engine.js"() {
453921
454817
  init_harness();
453922
454818
  init_memory4();
@@ -453924,12 +454820,16 @@ var MEMORY_INDEX_MAX_BYTES, init_engine4 = __esm({
453924
454820
  init_reminder_mint();
453925
454821
  init_memory_recall();
453926
454822
  init_frontmatter();
454823
+ init_provenance_wording();
453927
454824
  init_header_hints();
454825
+ init_delegation_settlement();
454826
+ init_delegation_settlement();
454827
+ init_origin_clearance();
453928
454828
  init_file_backend();
453929
454829
  init_export_bundle();
453930
454830
  init_layout();
453931
454831
  init_scan();
453932
- MEMORY_INDEX_MAX_BYTES = 25 * 1024;
454832
+ MEMORY_INDEX_MAX_BYTES = 25 * 1024, DEFAULT_HOLD_SETTLE_TIMEOUT_MS = 4320 * 60 * 1e3;
453933
454833
  }
453934
454834
  });
453935
454835
 
@@ -454323,6 +455223,7 @@ var PROMPT_HASH_SALT, DEFAULT_RESOURCE_TTL_MS, USAGE_WINDOW_REAP_MARGIN_MS, DEFA
454323
455223
  init_engine4();
454324
455224
  init_content_origin();
454325
455225
  init_delegation_provenance();
455226
+ init_delegation_settlement();
454326
455227
  init_memory4();
454327
455228
  init_compliance();
454328
455229
  init_memory_admission();
@@ -454513,6 +455414,7 @@ var DEFAULT_MAX_BYTES, GROUNDING_RATIO_MAX_TEXT_CHARS, GROUNDING_ECHO_MAX_CHARS,
454513
455414
  init_build3();
454514
455415
  init_tools3();
454515
455416
  init_untrusted_text();
455417
+ init_reminder_disclosure();
454516
455418
  init_untrusted_egress();
454517
455419
  init_image();
454518
455420
  init_safety();
@@ -454595,8 +455497,10 @@ var init_repetition = __esm({
454595
455497
  });
454596
455498
 
454597
455499
  // node_modules/@sema-agent/core/dist/core/strategy-store.js
454598
- var init_strategy_store = __esm({
455500
+ var MAX_STRATEGY_TS_FUTURE_MS, init_strategy_store = __esm({
454599
455501
  "node_modules/@sema-agent/core/dist/core/strategy-store.js"() {
455502
+ init_memory_vector();
455503
+ MAX_STRATEGY_TS_FUTURE_MS = 1440 * 60 * 1e3;
454600
455504
  }
454601
455505
  });
454602
455506
 
@@ -454616,6 +455520,8 @@ var init_cumulative_stats = __esm({
454616
455520
  // node_modules/@sema-agent/core/dist/agents/teacher.js
454617
455521
  var init_teacher = __esm({
454618
455522
  "node_modules/@sema-agent/core/dist/agents/teacher.js"() {
455523
+ init_strategy_store();
455524
+ init_safe_notify();
454619
455525
  init_suspend_guard();
454620
455526
  init_tools3();
454621
455527
  init_untrusted_text();
@@ -454919,17 +455825,24 @@ var LedgerCore, SharedLedgerTable, init_shared_ledger = __esm({
454919
455825
  locks = /* @__PURE__ */ new Map();
454920
455826
  events = 0;
454921
455827
  handle;
455828
+ fence;
455829
+ released = !1;
454922
455830
  constructor(key, paths3, model, table) {
454923
455831
  this.key = key, this.paths = paths3, this.model = model, this.table = table;
454924
455832
  }
454925
455833
  bootstrap() {
454926
- for (let row2 of readJsonlRecords(this.paths.snapshotPath))
454927
- this.rows.set(this.model.keyOf(row2), row2);
454928
- let events3 = readJsonlRecords(this.paths.ledgerPath);
454929
- this.events = events3.length;
454930
- for (let ev of events3)
454931
- this.model.apply(this.rows, ev);
454932
- this.handle = new AppendLog(this.paths.ledgerPath);
455834
+ this.fence = acquireStoreDirLock(this.paths.dir, { label: this.model.label });
455835
+ try {
455836
+ for (let row2 of readJsonlRecords(this.paths.snapshotPath))
455837
+ this.rows.set(this.model.keyOf(row2), row2);
455838
+ let events3 = readJsonlRecords(this.paths.ledgerPath);
455839
+ this.events = events3.length;
455840
+ for (let ev of events3)
455841
+ this.model.apply(this.rows, ev);
455842
+ this.handle = new AppendLog(this.paths.ledgerPath);
455843
+ } catch (e) {
455844
+ throw this.fence.release(), this.fence = void 0, e;
455845
+ }
454933
455846
  }
454934
455847
  withLock(key, fn2) {
454935
455848
  let run2 = (this.locks.get(key) ?? Promise.resolve()).then(() => fn2(), () => fn2()), tail = run2.then(() => {
@@ -454947,13 +455860,15 @@ var LedgerCore, SharedLedgerTable, init_shared_ledger = __esm({
454947
455860
  }
454948
455861
  }
454949
455862
  compact() {
455863
+ if (this.released)
455864
+ throw new Error("file ledger: this authority was released (its store was closed) \u2014 refusing to compact a directory it no longer owns");
454950
455865
  let lines = [...this.rows.values()].map((r) => JSON.stringify(r)).join(`
454951
455866
  `);
454952
455867
  atomicWriteFile2(this.paths.tmpDir, this.paths.snapshotPath, lines.length ? `${lines}
454953
455868
  ` : ""), this.log.closeForSwap(), atomicWriteFile2(this.paths.tmpDir, this.paths.ledgerPath, ""), this.events = 0;
454954
455869
  }
454955
455870
  release() {
454956
- this.refs -= 1, !(this.refs > 0) && (this.table.get(this.key) === this && this.table.delete(this.key), this.handle?.close());
455871
+ this.refs -= 1, !(this.refs > 0) && (this.table.get(this.key) === this && this.table.delete(this.key), this.released = !0, this.handle?.close(), this.fence?.release(), this.fence = void 0);
454957
455872
  }
454958
455873
  get pendingEvents() {
454959
455874
  return this.events;
@@ -455035,6 +455950,7 @@ var CHECKPOINT_LEDGER_EVENT_REGISTRY, KNOWN_CHECKPOINT_LEDGER_EVENTS, checkpoint
455035
455950
  steer_append: !0
455036
455951
  }, KNOWN_CHECKPOINT_LEDGER_EVENTS = new Set(Object.keys(CHECKPOINT_LEDGER_EVENT_REGISTRY));
455037
455952
  checkpointLedgers = new SharedLedgerTable({
455953
+ label: "checkpoint ledger",
455038
455954
  keyOf: (cp2) => cp2.token,
455039
455955
  apply: applyCheckpointEvent
455040
455956
  });
@@ -455104,6 +456020,163 @@ var RESUME_CLAIM_TTL_MS, RESUME_CLAIM_REAP_GRACE_MS, init_workflow_journal_store
455104
456020
  }
455105
456021
  });
455106
456022
 
456023
+ // node_modules/@sema-agent/core/dist/stores/file/background-agent-store.js
456024
+ import { join as join173 } from "node:path";
456025
+ var agentLedgers, FileBackgroundAgentStore, init_background_agent_store2 = __esm({
456026
+ "node_modules/@sema-agent/core/dist/stores/file/background-agent-store.js"() {
456027
+ init_background_agent_store();
456028
+ init_shared_ledger();
456029
+ init_marker();
456030
+ agentLedgers = new SharedLedgerTable({
456031
+ label: "background-agent ledger",
456032
+ keyOf: (r) => FileBackgroundAgentStore.key(r.handle, r.scope),
456033
+ apply: (rows2, ev) => {
456034
+ if (ev.t === "delete") {
456035
+ rows2.delete(ev.k);
456036
+ return;
456037
+ }
456038
+ rows2.set(ev.k, ev.r);
456039
+ }
456040
+ }), FileBackgroundAgentStore = class _FileBackgroundAgentStore {
456041
+ fsyncEnabled;
456042
+ compactEvery;
456043
+ ledger;
456044
+ closed = !1;
456045
+ get rows() {
456046
+ return this.ledger.rows;
456047
+ }
456048
+ constructor(root2, opts = {}) {
456049
+ assertAdoptionBootGate(root2, "FileBackgroundAgentStore"), this.fsyncEnabled = opts.fsync !== !1, this.compactEvery = opts.compactEvery ?? 1e3;
456050
+ let dir = join173(root2, "background-agents");
456051
+ this.ledger = agentLedgers.acquire({
456052
+ dir,
456053
+ tmpDir: join173(root2, "tmp"),
456054
+ ledgerPath: join173(dir, "agents.jsonl"),
456055
+ snapshotPath: join173(dir, "agents.snapshot.jsonl")
456056
+ });
456057
+ }
456058
+ static key(handle2, scope) {
456059
+ return `${scope}\0${handle2}`;
456060
+ }
456061
+ withLock(key, fn2) {
456062
+ return this.ledger.withLock(key, fn2);
456063
+ }
456064
+ commit(ev) {
456065
+ this.ledger.commit(ev, this.fsyncEnabled, this.compactEvery);
456066
+ }
456067
+ async put(record2) {
456068
+ if (record2.scope === void 0 || record2.scope === "")
456069
+ throw new Error("BackgroundAgentStore.put: refusing a row without a scope (world-readable through the fallback)");
456070
+ let k2 = _FileBackgroundAgentStore.key(record2.handle, record2.scope);
456071
+ return this.withLock(k2, () => {
456072
+ if (this.rows.has(k2))
456073
+ throw new BackgroundAgentStoreError("agent_record.already_exists", "agent record already exists");
456074
+ let stored = structuredClone(record2);
456075
+ stored.rev = record2.rev ?? 0, this.commit({ t: "put", k: k2, r: stored });
456076
+ });
456077
+ }
456078
+ async get(handle2, scope) {
456079
+ let row2 = this.rows.get(_FileBackgroundAgentStore.key(handle2, scope));
456080
+ return row2 ? structuredClone(row2) : null;
456081
+ }
456082
+ async update(handle2, scope, record2, expect) {
456083
+ let k2 = _FileBackgroundAgentStore.key(handle2, scope);
456084
+ return this.withLock(k2, () => {
456085
+ let live = this.rows.get(k2);
456086
+ if (!live || live.scope !== scope || live.rev !== expect.rev)
456087
+ return !1;
456088
+ let stored = structuredClone(record2);
456089
+ return stored.handle = handle2, stored.scope = scope, stored.rev = live.rev + 1, this.commit({ t: "update", k: k2, r: stored }), !0;
456090
+ });
456091
+ }
456092
+ async updateIf(handle2, scope, record2, expect) {
456093
+ let k2 = _FileBackgroundAgentStore.key(handle2, scope);
456094
+ return this.withLock(k2, async () => {
456095
+ let live = this.rows.get(k2);
456096
+ if (!live || live.scope !== scope || live.rev !== expect.rev || expect.status !== void 0 && live.status !== expect.status || expect.parkedCheckpointToken !== void 0 && (expect.parkedCheckpointToken === null ? live.parkedCheckpointToken !== void 0 : live.parkedCheckpointToken !== expect.parkedCheckpointToken) || expect.parkClaimId !== void 0 && (expect.parkClaimId === null ? live.parkClaimId !== void 0 : live.parkClaimId !== expect.parkClaimId))
456097
+ return !1;
456098
+ let stored = structuredClone(record2);
456099
+ return stored.handle = handle2, stored.scope = scope, stored.rev = live.rev + 1, this.commit({ t: "update", k: k2, r: stored }), !0;
456100
+ });
456101
+ }
456102
+ async listBySession(scope, sessionId, opts) {
456103
+ return queryBackgroundAgents(this.rows.values(), { scope, sessionId, status: opts?.status, limit: opts?.limit });
456104
+ }
456105
+ async listByScope(scope, opts) {
456106
+ return queryBackgroundAgents(this.rows.values(), { scope, status: opts?.status, limit: opts?.limit });
456107
+ }
456108
+ async listScopes() {
456109
+ return [...new Set([...this.rows.values()].map((r) => r.scope))].sort();
456110
+ }
456111
+ async delete(handle2, scope, expect) {
456112
+ let k2 = _FileBackgroundAgentStore.key(handle2, scope);
456113
+ return this.withLock(k2, () => {
456114
+ let live = this.rows.get(k2);
456115
+ return !live || expect !== void 0 && live.rev !== expect.rev ? !1 : (this.commit({ t: "delete", k: k2 }), !0);
456116
+ });
456117
+ }
456118
+ async reap(scope, now2, opts) {
456119
+ if (assertBackgroundAgentReapOptions(opts), !opts || opts.maxAgeMs === void 0 && opts.keep === void 0 && opts.staleRunningMaxAgeMs === void 0)
456120
+ return 0;
456121
+ let changed = /* @__PURE__ */ new Set();
456122
+ if (opts.staleRunningMaxAgeMs !== void 0) {
456123
+ let staleCandidates = [...this.rows.entries()].filter(([, r]) => r.scope === scope && r.status === "running" && now2 - r.updatedAt > opts.staleRunningMaxAgeMs).map(([k2]) => k2);
456124
+ for (let k2 of staleCandidates)
456125
+ await this.withLock(k2, () => {
456126
+ let live = this.rows.get(k2);
456127
+ if (!live || live.status !== "running" || now2 - live.updatedAt <= opts.staleRunningMaxAgeMs)
456128
+ return !1;
456129
+ let next = structuredClone(live);
456130
+ return next.status = "failed", next.stoppedBy = "system", next.summary = next.summary ?? STALE_RUNNING_REAP_ATTRIBUTION, next.error = next.error ?? STALE_RUNNING_REAP_ATTRIBUTION, next.settledAt = now2, next.updatedAt = now2, next.rev = live.rev + 1, this.commit({ t: "update", k: k2, r: next }), !0;
456131
+ }) && changed.add(k2);
456132
+ }
456133
+ let terminal = [...this.rows.entries()].filter(([, r]) => r.scope === scope && r.status !== "running" && r.status !== "parked").sort(([, a], [, b3]) => b3.spawnedAt - a.spawnedAt), doomed = /* @__PURE__ */ new Map();
456134
+ if (opts.maxAgeMs !== void 0)
456135
+ for (let [k2, r] of terminal)
456136
+ (r.settledAt ?? r.spawnedAt) < now2 - opts.maxAgeMs && doomed.set(k2, { byAge: !0 });
456137
+ if (opts.keep !== void 0)
456138
+ for (let [k2] of terminal.slice(Math.max(0, opts.keep)))
456139
+ doomed.has(k2) || doomed.set(k2, { byAge: !1 });
456140
+ for (let [k2, why] of doomed)
456141
+ await this.withLock(k2, () => {
456142
+ let live = this.rows.get(k2);
456143
+ return !live || live.scope !== scope || live.status === "running" || live.status === "parked" || why.byAge && opts.maxAgeMs !== void 0 && (live.settledAt ?? live.spawnedAt) >= now2 - opts.maxAgeMs ? !1 : (this.commit({ t: "delete", k: k2 }), !0);
456144
+ }) && changed.add(k2);
456145
+ return changed.size;
456146
+ }
456147
+ compactNow() {
456148
+ this.ledger.compact();
456149
+ }
456150
+ get size() {
456151
+ return this.rows.size;
456152
+ }
456153
+ close() {
456154
+ this.closed || (this.closed = !0, this.ledger.release());
456155
+ }
456156
+ };
456157
+ }
456158
+ });
456159
+
456160
+ // node_modules/@sema-agent/core/dist/stores/file/mailbox-store.js
456161
+ var init_mailbox_store2 = __esm({
456162
+ "node_modules/@sema-agent/core/dist/stores/file/mailbox-store.js"() {
456163
+ init_retention_policy();
456164
+ init_mailbox_store();
456165
+ init_fs_atomic();
456166
+ init_marker();
456167
+ }
456168
+ });
456169
+
456170
+ // node_modules/@sema-agent/core/dist/stores/file/strategy-store.js
456171
+ var STALE_TEMP_MS, init_strategy_store2 = __esm({
456172
+ "node_modules/@sema-agent/core/dist/stores/file/strategy-store.js"() {
456173
+ init_fs_atomic();
456174
+ init_safe_notify();
456175
+ init_strategy_store();
456176
+ STALE_TEMP_MS = 3600 * 1e3;
456177
+ }
456178
+ });
456179
+
455107
456180
  // node_modules/@sema-agent/core/dist/core/permission-rule-sync.js
455108
456181
  var init_permission_rule_sync = __esm({
455109
456182
  "node_modules/@sema-agent/core/dist/core/permission-rule-sync.js"() {
@@ -455115,10 +456188,10 @@ var init_permission_rule_sync = __esm({
455115
456188
 
455116
456189
  // node_modules/@sema-agent/core/dist/stores/file/permission-rule-store.js
455117
456190
  import { closeSync as closeSync15, constants as FS2, existsSync as existsSync30, fsyncSync as fsyncSync12, lstatSync as lstatSync5, mkdirSync as mkdirSync24, openSync as openSync16, readFileSync as readFileSync42, renameSync as renameSync15, unlinkSync as unlinkSync13, writeFileSync as writeFileSync23 } from "node:fs";
455118
- import { join as join173 } from "node:path";
456191
+ import { join as join174 } from "node:path";
455119
456192
  import { createHash as createHash27, randomBytes as randomBytes28 } from "node:crypto";
455120
456193
  function atomicPublish(dir, file2, payload2) {
455121
- let tmp = join173(dir, `.${randomBytes28(8).toString("hex")}.tmp`), fd2;
456194
+ let tmp = join174(dir, `.${randomBytes28(8).toString("hex")}.tmp`), fd2;
455122
456195
  try {
455123
456196
  fd2 = openSync16(tmp, FS2.O_WRONLY | FS2.O_CREAT | FS2.O_EXCL | (FS2.O_NOFOLLOW ?? 0), 384), writeFileSync23(fd2, payload2), fsyncSync12(fd2), closeSync15(fd2), fd2 = void 0, renameSync15(tmp, file2);
455124
456197
  let dfd;
@@ -455365,6 +456438,10 @@ var init_file2 = __esm({
455365
456438
  init_file_snapshot_store2();
455366
456439
  init_workflow_journal_store2();
455367
456440
  init_usage_window_store2();
456441
+ init_background_agent_store2();
456442
+ init_mailbox_store2();
456443
+ init_roster_store();
456444
+ init_strategy_store2();
455368
456445
  init_checkpoint_store2();
455369
456446
  init_memory_store();
455370
456447
  init_session_store2();
@@ -455373,6 +456450,8 @@ var init_file2 = __esm({
455373
456450
  init_file_snapshot_store2();
455374
456451
  init_workflow_journal_store2();
455375
456452
  init_usage_window_store2();
456453
+ init_strategy_store2();
456454
+ init_fs_atomic();
455376
456455
  init_fs_atomic();
455377
456456
  init_fs_atomic();
455378
456457
  init_marker();
@@ -455397,16 +456476,6 @@ var init_fs_write_gate_policy = __esm({
455397
456476
  }
455398
456477
  });
455399
456478
 
455400
- // node_modules/@sema-agent/core/dist/stores/file/mailbox-store.js
455401
- var init_mailbox_store2 = __esm({
455402
- "node_modules/@sema-agent/core/dist/stores/file/mailbox-store.js"() {
455403
- init_retention_policy();
455404
- init_mailbox_store();
455405
- init_fs_atomic();
455406
- init_marker();
455407
- }
455408
- });
455409
-
455410
456479
  // node_modules/@sema-agent/core/dist/stores/file/task-list-store.js
455411
456480
  var init_task_list_store = __esm({
455412
456481
  "node_modules/@sema-agent/core/dist/stores/file/task-list-store.js"() {
@@ -455583,6 +456652,7 @@ var init_memory_engine = __esm({
455583
456652
  "node_modules/@sema-agent/core/dist/core/memory-engine/index.js"() {
455584
456653
  init_engine4();
455585
456654
  init_tools5();
456655
+ init_provenance_wording();
455586
456656
  init_scan();
455587
456657
  init_file_backend();
455588
456658
  init_export_bundle();
@@ -455766,6 +456836,7 @@ var runLedgers, init_workflow_run_store2 = __esm({
455766
456836
  init_shared_ledger();
455767
456837
  init_marker();
455768
456838
  runLedgers = new SharedLedgerTable({
456839
+ label: "workflow-run ledger",
455769
456840
  keyOf: (run2) => run2.id,
455770
456841
  apply: (runs, ev) => {
455771
456842
  if (ev.t === "delete") {
@@ -455852,142 +456923,6 @@ var init_background_agent_store_contract = __esm({
455852
456923
  }
455853
456924
  });
455854
456925
 
455855
- // node_modules/@sema-agent/core/dist/stores/file/background-agent-store.js
455856
- import { join as join174 } from "node:path";
455857
- var agentLedgers, FileBackgroundAgentStore, init_background_agent_store2 = __esm({
455858
- "node_modules/@sema-agent/core/dist/stores/file/background-agent-store.js"() {
455859
- init_background_agent_store();
455860
- init_shared_ledger();
455861
- init_marker();
455862
- agentLedgers = new SharedLedgerTable({
455863
- keyOf: (r) => FileBackgroundAgentStore.key(r.handle, r.scope),
455864
- apply: (rows2, ev) => {
455865
- if (ev.t === "delete") {
455866
- rows2.delete(ev.k);
455867
- return;
455868
- }
455869
- rows2.set(ev.k, ev.r);
455870
- }
455871
- }), FileBackgroundAgentStore = class _FileBackgroundAgentStore {
455872
- fsyncEnabled;
455873
- compactEvery;
455874
- ledger;
455875
- closed = !1;
455876
- get rows() {
455877
- return this.ledger.rows;
455878
- }
455879
- constructor(root2, opts = {}) {
455880
- assertAdoptionBootGate(root2, "FileBackgroundAgentStore"), this.fsyncEnabled = opts.fsync !== !1, this.compactEvery = opts.compactEvery ?? 1e3;
455881
- let dir = join174(root2, "background-agents");
455882
- this.ledger = agentLedgers.acquire({
455883
- dir,
455884
- tmpDir: join174(root2, "tmp"),
455885
- ledgerPath: join174(dir, "agents.jsonl"),
455886
- snapshotPath: join174(dir, "agents.snapshot.jsonl")
455887
- });
455888
- }
455889
- static key(handle2, scope) {
455890
- return `${scope}\0${handle2}`;
455891
- }
455892
- withLock(key, fn2) {
455893
- return this.ledger.withLock(key, fn2);
455894
- }
455895
- commit(ev) {
455896
- this.ledger.commit(ev, this.fsyncEnabled, this.compactEvery);
455897
- }
455898
- async put(record2) {
455899
- if (record2.scope === void 0 || record2.scope === "")
455900
- throw new Error("BackgroundAgentStore.put: refusing a row without a scope (world-readable through the fallback)");
455901
- let k2 = _FileBackgroundAgentStore.key(record2.handle, record2.scope);
455902
- return this.withLock(k2, () => {
455903
- if (this.rows.has(k2))
455904
- throw new BackgroundAgentStoreError("agent_record.already_exists", "agent record already exists");
455905
- let stored = structuredClone(record2);
455906
- stored.rev = record2.rev ?? 0, this.commit({ t: "put", k: k2, r: stored });
455907
- });
455908
- }
455909
- async get(handle2, scope) {
455910
- let row2 = this.rows.get(_FileBackgroundAgentStore.key(handle2, scope));
455911
- return row2 ? structuredClone(row2) : null;
455912
- }
455913
- async update(handle2, scope, record2, expect) {
455914
- let k2 = _FileBackgroundAgentStore.key(handle2, scope);
455915
- return this.withLock(k2, () => {
455916
- let live = this.rows.get(k2);
455917
- if (!live || live.scope !== scope || live.rev !== expect.rev)
455918
- return !1;
455919
- let stored = structuredClone(record2);
455920
- return stored.handle = handle2, stored.scope = scope, stored.rev = live.rev + 1, this.commit({ t: "update", k: k2, r: stored }), !0;
455921
- });
455922
- }
455923
- async updateIf(handle2, scope, record2, expect) {
455924
- let k2 = _FileBackgroundAgentStore.key(handle2, scope);
455925
- return this.withLock(k2, async () => {
455926
- let live = this.rows.get(k2);
455927
- if (!live || live.scope !== scope || live.rev !== expect.rev || expect.status !== void 0 && live.status !== expect.status || expect.parkedCheckpointToken !== void 0 && (expect.parkedCheckpointToken === null ? live.parkedCheckpointToken !== void 0 : live.parkedCheckpointToken !== expect.parkedCheckpointToken) || expect.parkClaimId !== void 0 && (expect.parkClaimId === null ? live.parkClaimId !== void 0 : live.parkClaimId !== expect.parkClaimId))
455928
- return !1;
455929
- let stored = structuredClone(record2);
455930
- return stored.handle = handle2, stored.scope = scope, stored.rev = live.rev + 1, this.commit({ t: "update", k: k2, r: stored }), !0;
455931
- });
455932
- }
455933
- async listBySession(scope, sessionId, opts) {
455934
- return queryBackgroundAgents(this.rows.values(), { scope, sessionId, status: opts?.status, limit: opts?.limit });
455935
- }
455936
- async listByScope(scope, opts) {
455937
- return queryBackgroundAgents(this.rows.values(), { scope, status: opts?.status, limit: opts?.limit });
455938
- }
455939
- async listScopes() {
455940
- return [...new Set([...this.rows.values()].map((r) => r.scope))].sort();
455941
- }
455942
- async delete(handle2, scope, expect) {
455943
- let k2 = _FileBackgroundAgentStore.key(handle2, scope);
455944
- return this.withLock(k2, () => {
455945
- let live = this.rows.get(k2);
455946
- return !live || expect !== void 0 && live.rev !== expect.rev ? !1 : (this.commit({ t: "delete", k: k2 }), !0);
455947
- });
455948
- }
455949
- async reap(scope, now2, opts) {
455950
- if (assertBackgroundAgentReapOptions(opts), !opts || opts.maxAgeMs === void 0 && opts.keep === void 0 && opts.staleRunningMaxAgeMs === void 0)
455951
- return 0;
455952
- let changed = /* @__PURE__ */ new Set();
455953
- if (opts.staleRunningMaxAgeMs !== void 0) {
455954
- let staleCandidates = [...this.rows.entries()].filter(([, r]) => r.scope === scope && r.status === "running" && now2 - r.updatedAt > opts.staleRunningMaxAgeMs).map(([k2]) => k2);
455955
- for (let k2 of staleCandidates)
455956
- await this.withLock(k2, () => {
455957
- let live = this.rows.get(k2);
455958
- if (!live || live.status !== "running" || now2 - live.updatedAt <= opts.staleRunningMaxAgeMs)
455959
- return !1;
455960
- let next = structuredClone(live);
455961
- return next.status = "failed", next.stoppedBy = "system", next.summary = next.summary ?? STALE_RUNNING_REAP_ATTRIBUTION, next.error = next.error ?? STALE_RUNNING_REAP_ATTRIBUTION, next.settledAt = now2, next.updatedAt = now2, next.rev = live.rev + 1, this.commit({ t: "update", k: k2, r: next }), !0;
455962
- }) && changed.add(k2);
455963
- }
455964
- let terminal = [...this.rows.entries()].filter(([, r]) => r.scope === scope && r.status !== "running" && r.status !== "parked").sort(([, a], [, b3]) => b3.spawnedAt - a.spawnedAt), doomed = /* @__PURE__ */ new Map();
455965
- if (opts.maxAgeMs !== void 0)
455966
- for (let [k2, r] of terminal)
455967
- (r.settledAt ?? r.spawnedAt) < now2 - opts.maxAgeMs && doomed.set(k2, { byAge: !0 });
455968
- if (opts.keep !== void 0)
455969
- for (let [k2] of terminal.slice(Math.max(0, opts.keep)))
455970
- doomed.has(k2) || doomed.set(k2, { byAge: !1 });
455971
- for (let [k2, why] of doomed)
455972
- await this.withLock(k2, () => {
455973
- let live = this.rows.get(k2);
455974
- return !live || live.scope !== scope || live.status === "running" || live.status === "parked" || why.byAge && opts.maxAgeMs !== void 0 && (live.settledAt ?? live.spawnedAt) >= now2 - opts.maxAgeMs ? !1 : (this.commit({ t: "delete", k: k2 }), !0);
455975
- }) && changed.add(k2);
455976
- return changed.size;
455977
- }
455978
- compactNow() {
455979
- this.ledger.compact();
455980
- }
455981
- get size() {
455982
- return this.rows.size;
455983
- }
455984
- close() {
455985
- this.closed || (this.closed = !0, this.ledger.release());
455986
- }
455987
- };
455988
- }
455989
- });
455990
-
455991
456926
  // node_modules/@sema-agent/core/dist/agents/agent-definition.js
455992
456927
  var init_agent_definition = __esm({
455993
456928
  "node_modules/@sema-agent/core/dist/agents/agent-definition.js"() {
@@ -456187,6 +457122,7 @@ var init_dist10 = __esm({
456187
457122
  init_memory_admission();
456188
457123
  init_retention();
456189
457124
  init_governance_codes();
457125
+ init_governance_codes();
456190
457126
  init_session_store();
456191
457127
  init_session_reconcile();
456192
457128
  init_session4();
@@ -456330,6 +457266,7 @@ var init_dist10 = __esm({
456330
457266
  init_roster_store();
456331
457267
  init_catalog2();
456332
457268
  init_task_registry();
457269
+ init_defaults2();
456333
457270
  init_coordinator();
456334
457271
  init_subagent();
456335
457272
  init_retain_ledger();
@@ -471022,7 +471959,7 @@ function readRestartInflightLine() {
471022
471959
  ${caveat}`, key };
471023
471960
  }
471024
471961
  function EngineRestartConfirm({ onDone }) {
471025
- let upgrade2 = React131.useSyncExternalStore(subscribeUpgradeState, getUpgradeState), kind = upgrade2.phase === "ready" ? upgrade2.kind ?? "update" : "update", [inflight4, setInflight] = React131.useState(() => readRestartInflightLine());
471962
+ let upgrade2 = React131.useSyncExternalStore(subscribeUpgradeState, getUpgradeState), kind = upgrade2.phase === "ready" ? upgrade2.kind ?? "update" : "update", [inflight3, setInflight] = React131.useState(() => readRestartInflightLine());
471026
471963
  React131.useEffect(() => {
471027
471964
  let t2 = setInterval(() => setInflight(readRestartInflightLine()), 1e3);
471028
471965
  return () => clearInterval(t2);
@@ -471036,7 +471973,7 @@ function EngineRestartConfirm({ onDone }) {
471036
471973
  return;
471037
471974
  }
471038
471975
  let atConfirm = readRestartInflightLine();
471039
- if (atConfirm.key !== inflight4.key) {
471976
+ if (atConfirm.key !== inflight3.key) {
471040
471977
  setInflight(atConfirm), setNeedsReconfirm(!0);
471041
471978
  return;
471042
471979
  }
@@ -471053,7 +471990,7 @@ function EngineRestartConfirm({ onDone }) {
471053
471990
  }
471054
471991
  );
471055
471992
  },
471056
- [inflight4.key]
471993
+ [inflight3.key]
471057
471994
  ), options = [
471058
471995
  {
471059
471996
  label: needsReconfirm ? "Yes, restart anyway" : "Yes, restart the engine now",
@@ -471069,9 +472006,9 @@ function EngineRestartConfirm({ onDone }) {
471069
472006
  return /* @__PURE__ */ (0, import_jsx_runtime372.jsx)(PermissionDialog, { title: "Restart engine to apply?", children: /* @__PURE__ */ (0, import_jsx_runtime372.jsxs)(ThemedBox_default, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
471070
472007
  /* @__PURE__ */ (0, import_jsx_runtime372.jsxs)(ThemedBox_default, { marginBottom: 1, flexDirection: "column", children: [
471071
472008
  /* @__PURE__ */ (0, import_jsx_runtime372.jsx)(ThemedText, { children: restartConfirmSubtitle(kind) }),
471072
- inflight4.line !== null ? /* @__PURE__ */ (0, import_jsx_runtime372.jsxs)(import_jsx_runtime372.Fragment, { children: [
472009
+ inflight3.line !== null ? /* @__PURE__ */ (0, import_jsx_runtime372.jsxs)(import_jsx_runtime372.Fragment, { children: [
471073
472010
  /* @__PURE__ */ (0, import_jsx_runtime372.jsx)(ThemedText, { children: " " }),
471074
- /* @__PURE__ */ (0, import_jsx_runtime372.jsx)(ThemedText, { color: "warning", children: inflight4.line })
472011
+ /* @__PURE__ */ (0, import_jsx_runtime372.jsx)(ThemedText, { color: "warning", children: inflight3.line })
471075
472012
  ] }) : null,
471076
472013
  needsReconfirm ? /* @__PURE__ */ (0, import_jsx_runtime372.jsxs)(import_jsx_runtime372.Fragment, { children: [
471077
472014
  /* @__PURE__ */ (0, import_jsx_runtime372.jsx)(ThemedText, { children: " " }),
@@ -478006,6 +478943,9 @@ function askCountdownRow(remainingMs) {
478006
478943
  let total = Math.ceil(remainingMs / 1e3), m2 = Math.floor(total / 60), s = total % 60;
478007
478944
  return `This approval window closes in ${m2 > 0 ? `${String(m2)}m ${String(s).padStart(2, "0")}s` : `${String(s)}s`} \u2014 after that the engine's own policy takes over`;
478008
478945
  }
478946
+ function askCountdownIsUrgent(remainingMs) {
478947
+ return !Number.isFinite(remainingMs) || remainingMs <= 0 ? !1 : remainingMs <= ASK_COUNTDOWN_URGENT_MS;
478948
+ }
478009
478949
  function askRetractionRow(cause, toolName2) {
478010
478950
  let what = `the approval request for "${toolName2}"`;
478011
478951
  switch (cause) {
@@ -478019,9 +478959,10 @@ function askRetractionRow(cause, toolName2) {
478019
478959
  return `sema: ${what} was taken down (${cause}). Nothing was decided on your behalf here.`;
478020
478960
  }
478021
478961
  }
478022
- var ABSOLUTE_KEYS, RECEIVED_AT_KEYS, SERVER_NOW_KEYS, RELATIVE_MS_KEYS, RELATIVE_SEC_KEYS, init_askWindowCountdown = __esm({
478962
+ var ABSOLUTE_KEYS, RECEIVED_AT_KEYS, SERVER_NOW_KEYS, RELATIVE_MS_KEYS, RELATIVE_SEC_KEYS, ASK_COUNTDOWN_URGENT_MS, init_askWindowCountdown = __esm({
478023
478963
  "build-src/src/sema/askWindowCountdown.ts"() {
478024
478964
  ABSOLUTE_KEYS = ["expiresAtMs", "expiresAt", "askExpiresAt", "deadlineAt", "windowEndsAt"], RECEIVED_AT_KEYS = ["receivedAtMs"], SERVER_NOW_KEYS = ["serverNowMs", "serverTimeMs"], RELATIVE_MS_KEYS = ["expiresInMs", "askWindowMs", "windowMs", "ttlMs"], RELATIVE_SEC_KEYS = ["expiresInSec", "askWindowSec", "windowSec", "ttlSec", "ttlSeconds"];
478965
+ ASK_COUNTDOWN_URGENT_MS = 6e4;
478025
478966
  }
478026
478967
  });
478027
478968
 
@@ -478039,8 +478980,10 @@ function AskWindowCountdownRow({
478039
478980
  alive = !1, t2 !== void 0 && clearTimeout(t2);
478040
478981
  };
478041
478982
  }, [expiresAtMs]), expiresAtMs === void 0) return null;
478042
- let row2 = askCountdownRow(expiresAtMs - now2);
478043
- return row2 === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime404.jsx)(ThemedBox_default, { paddingX: 1, children: /* @__PURE__ */ (0, import_jsx_runtime404.jsx)(ThemedText, { dimColor: !0, children: row2 }) });
478983
+ let remainingMs = expiresAtMs - now2, row2 = askCountdownRow(remainingMs);
478984
+ if (row2 === void 0) return null;
478985
+ let urgent = askCountdownIsUrgent(remainingMs);
478986
+ return /* @__PURE__ */ (0, import_jsx_runtime404.jsx)(ThemedBox_default, { paddingX: 1, children: /* @__PURE__ */ (0, import_jsx_runtime404.jsx)(ThemedText, { dimColor: !urgent, color: urgent ? "warning" : void 0, children: row2 }) });
478044
478987
  }
478045
478988
  var React143, import_jsx_runtime404, init_AskWindowCountdownRow = __esm({
478046
478989
  "build-src/src/components/permissions/AskWindowCountdownRow.tsx"() {
@@ -498361,7 +499304,7 @@ function _temp158() {
498361
499304
  }
498362
499305
  var import_compiler_runtime308, import_react313, SETTINGS_ERRORS_NOTIFICATION_KEY, init_useSettingsErrors = __esm({
498363
499306
  "build-src/src/hooks/notifs/useSettingsErrors.tsx"() {
498364
- import_compiler_runtime308 = __toESM(require_compiler_runtime(), 1), import_react313 = __toESM(require_react(), 1);
499307
+ import_compiler_runtime308 = __toESM(require_compiler_runtime()), import_react313 = __toESM(require_react());
498365
499308
  init_notifications2();
498366
499309
  init_state();
498367
499310
  init_allErrors();
@@ -501563,7 +502506,7 @@ function REPL({
501563
502506
  item.reject(new Error("Prompt cancelled by user"));
501564
502507
  setPromptQueue([]), abortController?.abort("user-cancel");
501565
502508
  } else activeRemote.isRemoteMode ? activeRemote.cancelRequest() : abortController?.abort("user-cancel");
501566
- setAbortController(null), mrOnTurnComplete(messagesRef.current, !0);
502509
+ activeRemote.isRemoteMode || bestEffortInteractiveCancel(), setAbortController(null), mrOnTurnComplete(messagesRef.current, !0);
501567
502510
  }
501568
502511
  }
501569
502512
  let handleQueuedCommandOnCancel = (0, import_react332.useCallback)(() => {
@@ -512086,11 +513029,15 @@ function shellApprovalCardPort(req) {
512086
513029
  // ⇒ 整键缺席 ⇒ 卡形与修前逐字节相同。绝不拿 #175 那个 300s 硬编码上去 —— 那是 server
512087
513030
  // 侧随部署可改的旋钮,壳抄一份等于渲一个看起来精确、实际与引擎无关的数字(见
512088
513031
  // askWindowCountdown.ts 的缺席纪律段)。
512089
- // ✅ 供给按车道分:design/172 v1 呈卡帧的 **live `tasks/stream` 腿**窗三键端到端在场 ⇒
512090
- // 这条腿上 `askDeadlineMs` 真解出来、倒计时行与到点撤卡 timer 真起来(见下方 `askDeadlineMs
512091
- // !== undefined` 分支);durable 重放腿 / 旧族 `tool_approval` 帧腿 / durable park 腿三处
512092
- // 仍无窗位供给 那三条腿上这一位仍恒缺席、卡形逐字节不变(逐腿点名见
512093
- // askWindowCountdown.ts 头注「车道覆盖」段)。
513032
+ // ✅ 供给按车道分(1.0.88 更新:旧族帧腿由「整腿无窗」改为「按装配点分」):
513033
+ // · design/172 v1 呈卡帧的 **live `tasks/stream` 腿**窗三键端到端在场 这条腿上
513034
+ // `askDeadlineMs` 真解出来、倒计时行与到点撤卡 timer 真起来(见下方
513035
+ // `askDeadlineMs !== undefined` 分支);
513036
+ // · **旧族 `tool_approval` 帧腿**自 client-core 0.39.0 + 壳 `liveClient.makeHitlDeps` 接线起
513037
+ // **同样按腿有窗**:live 装配点声明 `windowIsCurrent: true` ⇒ 有窗;durable 装配点与
513038
+ // park→decide 续流 ⇒ 闸落 ⇒ 无窗;
513039
+ // · durable 重放腿 / durable park 腿仍无窗位供给 ⇒ 那两条腿上这一位仍恒缺席、卡形逐字节不变。
513040
+ // 逐腿点名与证据见 askWindowCountdown.ts 头注「车道覆盖」段(唯一台账,别在这里抄第二份)。
512094
513041
  ...askDeadlineMs !== void 0 ? { askExpiresAtMs: askDeadlineMs } : {},
512095
513042
  permissionPromptStartTimeMs: Date.now(),
512096
513043
  onUserInteraction() {
@@ -512302,9 +513249,30 @@ function frameSaysExpired(frame) {
512302
513249
  let at = frame.expiresAtMs, srvNow = frame.serverNowMs;
512303
513250
  return typeof at == "number" && Number.isFinite(at) && typeof srvNow == "number" && Number.isFinite(srvNow) ? at <= srvNow : !1;
512304
513251
  }
513252
+ function readCoherentEnvelopeWindow(env6) {
513253
+ let inMs = env6.expiresInMs, at = env6.expiresAtMs, srvNow = env6.serverNowMs;
513254
+ if (typeof inMs != "number" || !Number.isFinite(inMs) || typeof at != "number" || !Number.isFinite(at) || typeof srvNow != "number" || !Number.isFinite(srvNow) || at <= 0 || srvNow <= 0) return;
513255
+ let expected = Math.max(0, at - srvNow);
513256
+ if (!(Math.abs(inMs - expected) > ENVELOPE_WINDOW_COHERENCE_TOLERANCE_MS))
513257
+ return { expiresInMs: inMs, expiresAtMs: at, serverNowMs: srvNow };
513258
+ }
513259
+ function envelopeWindowSaysExpired(w2) {
513260
+ return w2.expiresInMs <= 0 && w2.expiresAtMs <= w2.serverNowMs;
513261
+ }
512305
513262
  function askCallKey(askId) {
512306
513263
  return askGateQuestionId(askId);
512307
513264
  }
513265
+ function windowKeysFrom(frame, opts) {
513266
+ return opts.windowIsCurrent !== !0 ? {} : {
513267
+ // 🔴 帧**到手**的本地时刻(调用点在任何 await 之前盖的)。读口拿它当本地锚点,
513268
+ // 否则能力位探测(≤1.5s)与 legacy 收尾宽限(750ms)会被**还回**服务端的窗里,
513269
+ // 卡在真实 deadline 之后仍可点(复审)。
513270
+ ...typeof opts.receivedAtMs == "number" && Number.isFinite(opts.receivedAtMs) ? { receivedAtMs: opts.receivedAtMs } : {},
513271
+ ...typeof frame.expiresInMs == "number" && Number.isFinite(frame.expiresInMs) ? { expiresInMs: frame.expiresInMs } : {},
513272
+ ...typeof frame.expiresAtMs == "number" && Number.isFinite(frame.expiresAtMs) ? { expiresAtMs: frame.expiresAtMs } : {},
513273
+ ...typeof frame.serverNowMs == "number" && Number.isFinite(frame.serverNowMs) ? { serverNowMs: frame.serverNowMs } : {}
513274
+ };
513275
+ }
512308
513276
  function approvalCardRequestFrom(frame, opts) {
512309
513277
  let card = frame.card, notes = [riskNoteFor(card.risk)];
512310
513278
  card.argsOmitted === !0 && notes.push("arguments omitted by the engine (over the 16 KiB cap) \u2014 this does NOT mean the call has no arguments");
@@ -512328,23 +513296,9 @@ function approvalCardRequestFrom(frame, opts) {
512328
513296
  ...card.delegation !== void 0 ? { delegation: card.delegation } : {},
512329
513297
  ...card.ruleSuggestions !== void 0 && card.ruleSuggestions.length > 0 ? { ruleSuggestions: card.ruleSuggestions } : {},
512330
513298
  ...card.fromSubagent === !0 && typeof card.sourceAgentName == "string" && card.sourceAgentName !== "" ? { workerBadge: { name: cleanForDisplay(card.sourceAgentName, 60), color: "suggestion" } } : {},
512331
- // 窗三键原样转出([4297] Q2,见函数头注)
512332
- // 🔴 逐键**在场才 stamp**:类型面写的是必填,但 wire 是开集、老 worker 可能不发,而
512333
- // 「缺席 ⇒ 不渲倒计时」正是这一批的成文降级路径 —— 照必填读法合成一个 0 出来会让每张卡
512334
- // 当场自撤。
512335
- // 🔴 `windowIsCurrent !== true` ⇒ 三键**整族不转**(复审实撞):账本重放的历史帧
512336
- // 带的是铸帧时刻的旧余量,拿它算「本地 now + 余量」等于给一只早就过期的 ask 续一个新窗
512337
- // (卡复活、倒计时从头走、到点撤卡被推迟)。新旧在帧里读不出来 —— 只有装配点知道自己接的
512338
- // 是哪条腿,所以判据在那里,而这里的缺省选「不渲」那一边。
512339
- ...opts.windowIsCurrent === !0 ? {
512340
- // 🔴 帧**到手**的本地时刻(调用点在任何 await 之前盖的)。读口拿它当本地锚点,
512341
- // 否则能力位探测(≤1.5s)与 legacy 收尾宽限(750ms)会被**还回**服务端的窗里,
512342
- // 卡在真实 deadline 之后仍可点(复审)。
512343
- ...typeof opts.receivedAtMs == "number" && Number.isFinite(opts.receivedAtMs) ? { receivedAtMs: opts.receivedAtMs } : {},
512344
- ...typeof frame.expiresInMs == "number" && Number.isFinite(frame.expiresInMs) ? { expiresInMs: frame.expiresInMs } : {},
512345
- ...typeof frame.expiresAtMs == "number" && Number.isFinite(frame.expiresAtMs) ? { expiresAtMs: frame.expiresAtMs } : {},
512346
- ...typeof frame.serverNowMs == "number" && Number.isFinite(frame.serverNowMs) ? { serverNowMs: frame.serverNowMs } : {}
512347
- } : {}
513299
+ // 窗三键原样转出([4297] Q2,见函数头注)——投影判据单源在 `windowKeysFrom`(通用卡腿共用
513300
+ // 同一口;两腿各抄一份就是同形存量)。
513301
+ ...windowKeysFrom(frame, opts)
512348
513302
  };
512349
513303
  }
512350
513304
  function genericCardRequestFrom(env6, askId, opts) {
@@ -512356,7 +513310,14 @@ function genericCardRequestFrom(env6, askId, opts) {
512356
513310
  args: typeof card.args == "object" && card.args !== null ? card.args : {},
512357
513311
  callKey: askCallKey(askId),
512358
513312
  ...opts.signal !== void 0 ? { signal: opts.signal } : {},
512359
- wireNote: notes.join(" \xB7 ")
513313
+ wireNote: notes.join(" \xB7 "),
513314
+ // 窗三键(见函数头注)——**先验自洽再投影**;验不过 ⇒ 整族不转(连本地锚点 `receivedAtMs` 都不盖:
513315
+ // 一个没有窗的卡上留个孤零零的锚点只会让下一棒以为这里有窗)⇒ 卡形与修前逐字节相同。
513316
+ // 投影口本身与 v1 腿同源(`windowKeysFrom`:新鲜度门 / 逐键在场 / 本地锚点三条纪律不重写一遍)。
513317
+ ...(() => {
513318
+ let w2 = readCoherentEnvelopeWindow(env6);
513319
+ return w2 === void 0 ? {} : windowKeysFrom(w2, opts);
513320
+ })()
512360
513321
  };
512361
513322
  }
512362
513323
  function defaultNotify(text2) {
@@ -512396,10 +513357,10 @@ async function* consumeStreamApprovalFrames(events3, deps2, opts = {}) {
512396
513357
  "a stream-approval frame arrived while this worker reports streamApproval=false (stale read / failed probe / genuine disagreement \u2014 indistinguishable here). Servicing it anyway: forwarding it downstream would DROP it, and this frame may be the only carrier of a pending card."
512397
513358
  ), !0;
512398
513359
  }
512399
- let card = deps2.surfaceCard ?? surfaceApprovalCard, notify5 = deps2.notify ?? defaultNotify, surfaceNote = deps2.surfaceDecisionNote ?? defaultSurfaceDecisionNote, legacyClaimed = /* @__PURE__ */ new Set(), legacySettled = /* @__PURE__ */ new Set(), handled = /* @__PURE__ */ new Set(), live = /* @__PURE__ */ new Map(), inflight4 = /* @__PURE__ */ new Set(), torn = !1, track2 = (p) => {
513360
+ let card = deps2.surfaceCard ?? surfaceApprovalCard, notify5 = deps2.notify ?? defaultNotify, surfaceNote = deps2.surfaceDecisionNote ?? defaultSurfaceDecisionNote, legacyClaimed = /* @__PURE__ */ new Set(), legacySettled = /* @__PURE__ */ new Set(), handled = /* @__PURE__ */ new Set(), live = /* @__PURE__ */ new Map(), inflight3 = /* @__PURE__ */ new Set(), torn = !1, track2 = (p) => {
512400
513361
  let guarded = p.catch(() => {
512401
513362
  });
512402
- inflight4.add(guarded), guarded.finally(() => inflight4.delete(guarded));
513363
+ inflight3.add(guarded), guarded.finally(() => inflight3.delete(guarded));
512403
513364
  };
512404
513365
  try {
512405
513366
  for await (let ev of events3) {
@@ -512430,8 +513391,8 @@ async function* consumeStreamApprovalFrames(events3, deps2, opts = {}) {
512430
513391
  } finally {
512431
513392
  torn = !0;
512432
513393
  for (let c2 of live.values()) c2.abort.abort();
512433
- live.clear(), inflight4.size > 0 && await Promise.race([
512434
- Promise.allSettled([...inflight4]),
513394
+ live.clear(), inflight3.size > 0 && await Promise.race([
513395
+ Promise.allSettled([...inflight3]),
512435
513396
  new Promise((r) => setTimeout(r, TEARDOWN_BUDGET_MS))
512436
513397
  ]);
512437
513398
  }
@@ -512463,7 +513424,8 @@ async function* consumeStreamApprovalFrames(events3, deps2, opts = {}) {
512463
513424
  `approval_request ask=${cleanForDisplay(askId, 64)}: the legacy leg saw approvalId=${cleanForDisplay(approvalId, 64)} but never settled it (wrong replica / dropped connection is exactly this path) \u2014 running the durable CAS route`
512464
513425
  );
512465
513426
  }
512466
- if (v1 !== void 0 && frameSaysExpired(v1)) {
513427
+ let envWindow = v1 === void 0 ? readCoherentEnvelopeWindow(raw2) : void 0;
513428
+ if (v1 !== void 0 ? frameSaysExpired(v1) : envWindow !== void 0 && envelopeWindowSaysExpired(envWindow)) {
512467
513429
  release2(), logging(
512468
513430
  `approval_request ask=${cleanForDisplay(askId, 64)} arrived already expired per its own window (expiresInMs=0 / expiresAtMs<=serverNowMs) \u2014 no card is raised (a card that can only ever return 404 is worse than no card)`
512469
513431
  );
@@ -512484,7 +513446,14 @@ async function* consumeStreamApprovalFrames(events3, deps2, opts = {}) {
512484
513446
  // 复审:本地锚点取**帧到手**那一刻(下面 await 掉的时间不还给窗)。
512485
513447
  receivedAtMs
512486
513448
  })
512487
- ) : await card(genericCardRequestFrom(raw2, askId, { signal: abort.signal }));
513449
+ ) : await card(
513450
+ genericCardRequestFrom(raw2, askId, {
513451
+ signal: abort.signal,
513452
+ // #324 件①:窗三键是信封级的 ⇒ 未知 card 形照样有窗。判据与 v1 腿逐字同源。
513453
+ windowIsCurrent: opts.windowIsCurrent === !0,
513454
+ receivedAtMs
513455
+ })
513456
+ );
512488
513457
  } catch (e) {
512489
513458
  logForDebugging(`[sema][wire] stream-approval card raise failed (fail-soft, engine window still governs): ${String(e)}`);
512490
513459
  return;
@@ -512642,7 +513611,7 @@ async function* consumeStreamApprovalFrames(events3, deps2, opts = {}) {
512642
513611
  logForDebugging(`[sema][wire] ${line}`);
512643
513612
  }
512644
513613
  }
512645
- var STREAM_APPROVAL_CAP, ASK_DECISION_DISABLED_CODE, IDEMPOTENCY_KEY_MAX, PARKING_POLL_MAX, PARKING_POLL_DELAY_MS, CAPS_SETTLE_BUDGET_MS, LEGACY_SETTLE_GRACE_MS, MAX_DECISION_NOTE_CHARS, TEARDOWN_BUDGET_MS, TYPED_NAME_TO_KIND, NOTICE_KEY2, init_approvalStreamWire = __esm({
513614
+ var STREAM_APPROVAL_CAP, ASK_DECISION_DISABLED_CODE, IDEMPOTENCY_KEY_MAX, PARKING_POLL_MAX, PARKING_POLL_DELAY_MS, CAPS_SETTLE_BUDGET_MS, LEGACY_SETTLE_GRACE_MS, MAX_DECISION_NOTE_CHARS, TEARDOWN_BUDGET_MS, TYPED_NAME_TO_KIND, ENVELOPE_WINDOW_COHERENCE_TOLERANCE_MS, NOTICE_KEY2, init_approvalStreamWire = __esm({
512646
513615
  "build-src/src/sema/approvalStreamWire.ts"() {
512647
513616
  init_dist();
512648
513617
  init_debug();
@@ -512660,6 +513629,7 @@ var STREAM_APPROVAL_CAP, ASK_DECISION_DISABLED_CODE, IDEMPOTENCY_KEY_MAX, PARKIN
512660
513629
  ["AskParkingError", "parking"],
512661
513630
  ["FeatureDisabledError", "ask-lane-disabled"]
512662
513631
  ]);
513632
+ ENVELOPE_WINDOW_COHERENCE_TOLERANCE_MS = 1e3;
512663
513633
  NOTICE_KEY2 = "stream-approval";
512664
513634
  }
512665
513635
  });
@@ -513298,33 +514268,40 @@ function createLiveConversationClient(config4) {
513298
514268
  }
513299
514269
  );
513300
514270
  return body.persistRule !== void 0 && surfaceRulePersistOutcome(ack), ack;
513301
- }, baseUrlTrimmed = config4.baseUrl.replace(/\/+$/, ""), hitlDeps = {
513302
- client: client3,
513303
- // 🔴 续流也要经登记级(对抗复审轮4 H3 实撞)**与流内审批级**(1.0.74 终扫 P2-2/P2-3):
513304
- // HITL 桥在 park→decide 之后把内部流**换成**这条 `runsEvents` 的返回值 —— 只包住最初的
513305
- // source 等于漏掉整条续流。台账级漏 = 子代若在批准之后才起、或首个 tick 落在续流里,
513306
- // 详情面的「继续」入口被永久藏起来;审批级漏 = park 之后续流上到达的 approval_request /
513307
- // approval_revoke 帧无人消费(投影器只有 dropped 一条路)。两层组合收在
513308
- // composeHitlContinuationEvents(与主管道同序同参数形,台账取舍见其头注)。
513309
- // 这里的 run id 是**本次 attach 的 taskId**,天然流局部。
513310
- runsEvents: (taskId, opts) => (
513311
- // session 与**这次 attach 实际发出去的那个值**同源(下面 spread 的同一次求值),不是逐帧现读。
513312
- ((sessionSpread) => composeHitlContinuationEvents(client3.runs.events(taskId, { ...opts, ...sessionSpread }), {
514271
+ }, baseUrlTrimmed = config4.baseUrl.replace(/\/+$/, ""), makeHitlDeps = (lane) => {
514272
+ let windowIsCurrent = lane.windowIsCurrent;
514273
+ return {
514274
+ client: client3,
514275
+ // 🔴 续流也要经登记级(对抗复审轮4 H3 实撞)**与流内审批级**(1.0.74 终扫 P2-2/P2-3):
514276
+ // HITL 桥在 park→decide 之后把内部流**换成**这条 `runsEvents` 的返回值 —— 只包住最初的
514277
+ // source 等于漏掉整条续流。台账级漏 = 子代若在批准之后才起、或首个 tick 落在续流里,
514278
+ // 详情面的「继续」入口被永久藏起来;审批级漏 = park 之后续流上到达的 approval_request /
514279
+ // approval_revoke 帧无人消费(投影器只有 dropped 一条路)。两层组合收在
514280
+ // composeHitlContinuationEvents(与主管道同序同参数形,台账取舍见其头注)
514281
+ // 这里的 run id 是**本次 attach taskId**,天然流局部。
514282
+ runsEvents: (taskId, opts) => (windowIsCurrent = !1, ((sessionSpread) => composeHitlContinuationEvents(client3.runs.events(taskId, { ...opts, ...sessionSpread }), {
513313
514283
  taskId,
513314
514284
  ownerSessionId: sessionSpread.session,
513315
514285
  approvalDeps: approvalStreamDeps,
513316
514286
  ...opts?.signal ? { signal: opts.signal } : {}
513317
- }))(engineSessionParamSpread())
513318
- ),
513319
- respondToolApproval,
513320
- // #229 respond-note 供给链(A-029.12 件3):帧腿车道参数 —— 包编排层的 note 门读
513321
- // `approvalDecisionNoteCapable`,缺席 = fail-closed 到「不发」侧,note cli 恒死件。
513322
- // 供给 = caps 缓存的 `approvalDecisionNote` 位(server ≥7.15.0 硬编码 true 的版本探测位;
513323
- // per-call 真值归 ack.noteRecorded,A-029.9 消费面另批)getter 按**读取时刻**取值:
513324
- // caps 探测是 boot fire-and-forget 的,构造时 stamp 布尔会把「探测在飞」冻成永久 false。
513325
- get approvalLane() {
513326
- return { approvalDecisionNoteCapable: engineCapTrue(config4.baseUrl, "approvalDecisionNote") };
513327
- }
514287
+ }))(engineSessionParamSpread())),
514288
+ respondToolApproval,
514289
+ // #229 respond-note 供给链(A-029.12 件3):帧腿车道参数 —— 包编排层的 note 门读
514290
+ // `approvalDecisionNoteCapable`,缺席 = fail-closed 到「不发」侧,note cli 恒死件。
514291
+ // 供给 = caps 缓存的 `approvalDecisionNote` 位(server ≥7.15.0 硬编码 true 的版本探测位;
514292
+ // per-call 真值归 ack.noteRecorded,A-029.9 消费面另批)。getter 按**读取时刻**取值:
514293
+ // caps 探测是 boot 期 fire-and-forget 的,构造时 stamp 布尔会把「探测在飞」冻成永久 false
514294
+ // 🔴 `windowIsCurrent` 同理必须走 getter:闩是在 `runsEvents` 里落的,构造时 stamp 布尔
514295
+ // 等于把开流那一刻的值冻死,续流之后照旧过境三键(= 没修)
514296
+ get approvalLane() {
514297
+ return {
514298
+ approvalDecisionNoteCapable: engineCapTrue(config4.baseUrl, "approvalDecisionNote"),
514299
+ // 🔴 只在真为 live 时**显式**声明;false 也如实写出去(包侧 `!== true` 读法两者等价,
514300
+ // 但显式 false 让「这条腿判过了」在 diff 与 census 上可见,不与「忘了传」同形)。
514301
+ windowIsCurrent
514302
+ };
514303
+ }
514304
+ };
513328
514305
  }, approvalStreamDeps = {
513329
514306
  decide: {
513330
514307
  // C4([3777] 第 5 层):传输层失败退避重试。**幂等键复用是这条腿的全部前提** —— `body`
@@ -513437,7 +514414,10 @@ function createLiveConversationClient(config4) {
513437
514414
  }
513438
514415
  )
513439
514416
  ),
513440
- hitlDeps,
514417
+ // legacy `tool_approval` 帧腿的车道:**live 装配点** ⇒ 窗三键过境(归属判据与上面
514418
+ // 孪生族那一位同源,逐条见 makeHitlDeps 头注)。park→decide 续流上的重放帧由工厂
514419
+ // 内那枚每流闩自动降位,不靠这里第二次判断。
514420
+ makeHitlDeps({ windowIsCurrent: !0 }),
513441
514421
  {
513442
514422
  ...opts?.signal ? { signal: opts.signal } : {}
513443
514423
  }
@@ -513486,7 +514466,10 @@ function createLiveConversationClient(config4) {
513486
514466
  { ...opts?.signal ? { signal: opts.signal } : {} }
513487
514467
  )
513488
514468
  ),
513489
- hitlDeps,
514469
+ // legacy `tool_approval` 帧腿的车道:**durable 重放装配点** ⇒ 窗三键**不**过境。
514470
+ // 与上面 `consumeStreamApprovalFrames` 在本腿刻意不传同名 opt 是同一条判据的两半
514471
+ // (孪生族与包腿同口径);这里写显式 `false` 而不是省略,好让「判过了」可见。
514472
+ makeHitlDeps({ windowIsCurrent: !1 }),
513490
514473
  {
513491
514474
  taskId,
513492
514475
  ...opts?.signal ? { signal: opts.signal } : {}
@@ -514284,6 +515267,7 @@ async function* ask(params) {
514284
515267
  }), finalResultText, lastAssistantUuid = "", markedInflight = !!process.env.SEMA_LIVE_BASEURL;
514285
515268
  markedInflight && markTurnInflight();
514286
515269
  try {
515270
+ let emittedNoticeKeys = /* @__PURE__ */ new Set();
514287
515271
  for await (let msg of sdk) {
514288
515272
  if (signal?.aborted) break;
514289
515273
  let t2 = msg.type;
@@ -514294,16 +515278,32 @@ async function* ask(params) {
514294
515278
  }
514295
515279
  if (!(t2 === "retry_status" || t2 === "turn_usage" || t2 === "task_progress" || t2 === "steering_injected")) {
514296
515280
  if (t2 === "human_input") {
514297
- let hi = msg, clean8 = (v2) => (
514298
- // eslint-disable-next-line no-control-regex
514299
- String(v2 ?? "").replace(/[\x00-\x1f\x7f]/g, ".").slice(0, 120)
514300
- ), who = hi.actor?.id ? `${clean8(hi.actor.id)}${hi.actor.hostAsserted === !0 ? "" : " (unverified)"}` : "unattributed";
515281
+ let hi = msg, clean8 = (v2) => cleanUntrustedForDisplay(v2, 120), who = hi.actor?.id ? `${clean8(hi.actor.id)}${hi.actor.hostAsserted === !0 ? "" : " (unverified)"}` : "unattributed";
514301
515282
  logForDebugging(
514302
515283
  `[sema][print] human_input ledger frame (audit): carrier=${clean8(hi.carrier)} eventId=${clean8(hi.eventId)} by=${who}`
514303
515284
  );
514304
515285
  continue;
514305
515286
  }
514306
515287
  if (!(t2 === "diagnostics" || t2 === "workspace_changed")) {
515288
+ if (t2 === "engine_notice") {
515289
+ let en2 = msg, clean8 = (v2) => cleanUntrustedForDisplay(v2, 160), detailText = "";
515290
+ try {
515291
+ detailText = en2.detail === void 0 ? "" : cleanUntrustedForDisplay(JSON.stringify(en2.detail), 400);
515292
+ } catch {
515293
+ detailText = "(unserializable)";
515294
+ }
515295
+ logForDebugging(
515296
+ `[sema][print] engine_notice swallowed (audit; no stdout parity frame \u2014 see [4429]/#302): code=${clean8(en2.code)} eventId=${clean8(en2.eventId)} eventSeq=${clean8(en2.eventSeq)} ts=${clean8(en2.ts)} sessionId=${clean8(en2.sessionId)} message=${clean8(en2.message)} detail=${detailText}`
515297
+ );
515298
+ let noticeKey = `${clean8(en2.eventId)}|${clean8(en2.eventSeq)}|${clean8(en2.code)}`;
515299
+ if (!emittedNoticeKeys.has(noticeKey)) {
515300
+ emittedNoticeKeys.add(noticeKey);
515301
+ let msgPart = en2.message === void 0 ? "" : ` \u2014 ${clean8(en2.message)}`;
515302
+ process.stderr.write(`[sema] engine notice: ${clean8(en2.code)}${msgPart}
515303
+ `);
515304
+ }
515305
+ continue;
515306
+ }
514307
515307
  if (t2 === "prompt_suggestions") {
514308
515308
  let list = msg.suggestions;
514309
515309
  if (Array.isArray(list)) {
@@ -514490,6 +515490,7 @@ var client2, clientExplicitlySet2, printNotifiedKeys, init_seamQueryEngine = __e
514490
515490
  init_dist();
514491
515491
  init_deferSessionExemption();
514492
515492
  init_debug();
515493
+ init_untrustedDisplayText();
514493
515494
  init_dist();
514494
515495
  init_dist();
514495
515496
  init_dist();
@@ -528176,8 +529177,7 @@ function ModelHubBody({
528176
529177
  }
528177
529178
  rr.renamedTo && (renamed = rr.renamedTo);
528178
529179
  }
528179
- renamed && requestEngineConfigRespawn().catch(() => {
528180
- }), nav2.pop();
529180
+ renamed && pendingRestartLaneAvailable() && notePendingEngineRestart("config", "catalog"), nav2.pop();
528181
529181
  }
528182
529182
  }),
528183
529183
  () => readEdit?.() ?? null,
@@ -528320,7 +529320,7 @@ var React192, import_jsx_runtime504, clampShown, hostOf5, SUPPORTED_CHANNELS, AD
528320
529320
  init_modelCtxOverride();
528321
529321
  init_modelChannels();
528322
529322
  init_rosterStore();
528323
- init_engineEndpointSwap();
529323
+ init_engineUpgradeCoordinator();
528324
529324
  init_tierStore();
528325
529325
  init_KeybindingContext();
528326
529326
  init_catalogScreens();
@@ -531749,7 +532749,7 @@ Usage: sema --remote "your task description"`, () => gracefulShutdown(1));
531749
532749
  pendingHookMessages
531750
532750
  }, renderAndRun);
531751
532751
  }
531752
- }).version("sema 1.0.87", "-v, --version", "Output the version number"), program2.option("-w, --worktree [name]", "Create a new git worktree for this session (optionally specify a name)"), program2.option("--tmux", "Create a tmux session for the worktree (requires --worktree). Uses iTerm2 native panes when available; use --tmux=classic for traditional tmux."), canUserConfigureAdvisor() && program2.addOption(new Option("--advisor <model>", "Enable the server-side advisor tool with the specified model (alias or full ID).").hideHelp()), program2.addOption(new Option("--bg, --background", "Start the session as a background agent and return immediately (manage with `sema agents`)")), program2.command("ps").description("List background sessions").action(async () => {
532752
+ }).version("sema 1.0.89", "-v, --version", "Output the version number"), program2.option("-w, --worktree [name]", "Create a new git worktree for this session (optionally specify a name)"), program2.option("--tmux", "Create a tmux session for the worktree (requires --worktree). Uses iTerm2 native panes when available; use --tmux=classic for traditional tmux."), canUserConfigureAdvisor() && program2.addOption(new Option("--advisor <model>", "Enable the server-side advisor tool with the specified model (alias or full ID).").hideHelp()), program2.addOption(new Option("--bg, --background", "Start the session as a background agent and return immediately (manage with `sema agents`)")), program2.command("ps").description("List background sessions").action(async () => {
531753
532753
  await (await Promise.resolve().then(() => (init_bg2(), bg_exports))).psHandler([]), process.exit(process.exitCode ?? 0);
531754
532754
  }), program2.command("logs [id]").description("Print a background session's recent terminal output").action(async (id) => {
531755
532755
  await (await Promise.resolve().then(() => (init_bg2(), bg_exports))).logsHandler(id, []), process.exit(process.exitCode ?? 0);
@@ -532825,9 +533825,6 @@ var React202, import_jsx_runtime517, ALL_INTERFACES_BIND_HOST, init_BindHostFiel
532825
533825
  // build-src/src/sema/config/EngineScreen.tsx
532826
533826
  import { readFileSync as readFileSync61 } from "node:fs";
532827
533827
  import { join as join211 } from "node:path";
532828
- function localEngineLane() {
532829
- return !process.env.SEMA_LIVE_BASEURL && process.env.SEMA_TOC_ENGINE !== "0";
532830
- }
532831
533828
  function settingsEnv2() {
532832
533829
  try {
532833
533830
  let sj = JSON.parse(
@@ -532873,7 +533870,7 @@ function portEditScreen() {
532873
533870
  return;
532874
533871
  }
532875
533872
  let err8 = applyEnginePort(p);
532876
- !err8 && localEngineLane() && notePendingEngineRestart("config"), saveNotice = err8 ? `failed to save port: ${err8.message}` : localEngineLane() ? `port ${p} saved to settings.json \u2014 the open session shows an engine-restart banner \u2014 press ctrl+u there to apply` : `port ${p} saved to settings.json \u2014 takes effect the next time a local engine is spawned (this session is attached to an external engine or engine autostart is off)`;
533873
+ !err8 && pendingRestartLaneAvailable() && notePendingEngineRestart("config"), saveNotice = err8 ? `failed to save port: ${err8.message}` : pendingRestartLaneAvailable() ? `port ${p} saved to settings.json \u2014 the open session shows an engine-restart banner \u2014 press ctrl+u there to apply` : `port ${p} saved to settings.json \u2014 takes effect the next time a local engine is spawned (this session is not managing a local engine \u2014 attached to an external one, autostart off, or run as a standalone config command)`;
532877
533874
  }
532878
533875
  });
532879
533876
  }
@@ -532888,7 +533885,7 @@ function bindHostEditScreen() {
532888
533885
  current: configuredBindHost().host,
532889
533886
  onSubmit: (host) => {
532890
533887
  let err8 = applyEngineBindHost(host);
532891
- !err8 && localEngineLane() && notePendingEngineRestart("config"), saveNotice = err8 ? `failed to save bind address: ${err8.message}` : host === null ? localEngineLane() ? `bind address back to default ${DEFAULT_BIND_HOST} (key removed from settings.json) \u2014 the open session shows an engine-restart banner \u2014 press ctrl+u there to apply` : `bind address back to default ${DEFAULT_BIND_HOST} (key removed from settings.json) \u2014 takes effect the next time a local engine is spawned (this session is attached to an external engine or engine autostart is off)` : localEngineLane() ? `bind address ${host} saved to settings.json \u2014 the open session shows an engine-restart banner \u2014 press ctrl+u there to apply` : `bind address ${host} saved to settings.json \u2014 takes effect the next time a local engine is spawned (this session is attached to an external engine or engine autostart is off)`, nav.pop();
533888
+ !err8 && pendingRestartLaneAvailable() && notePendingEngineRestart("config"), saveNotice = err8 ? `failed to save bind address: ${err8.message}` : host === null ? pendingRestartLaneAvailable() ? `bind address back to default ${DEFAULT_BIND_HOST} (key removed from settings.json) \u2014 the open session shows an engine-restart banner \u2014 press ctrl+u there to apply` : `bind address back to default ${DEFAULT_BIND_HOST} (key removed from settings.json) \u2014 takes effect the next time a local engine is spawned (this session is not managing a local engine \u2014 attached to an external one, autostart off, or run as a standalone config command)` : pendingRestartLaneAvailable() ? `bind address ${host} saved to settings.json \u2014 the open session shows an engine-restart banner \u2014 press ctrl+u there to apply` : `bind address ${host} saved to settings.json \u2014 takes effect the next time a local engine is spawned (this session is not managing a local engine \u2014 attached to an external one, autostart off, or run as a standalone config command)`, nav.pop();
532892
533889
  }
532893
533890
  }
532894
533891
  )
@@ -532933,7 +533930,7 @@ function readFaceEditScreen() {
532933
533930
  return;
532934
533931
  }
532935
533932
  let effective = configuredEngineReadFace(getClaudeConfigHomeDir());
532936
- effective.face === face && localEngineLane() && notePendingEngineRestart("config"), saveNotice = effective.face !== face ? `read face ${face} saved to settings.json \u2014 but the READ_FACE environment variable (${effective.face}) overrides it, so the engine stays "${effective.face}". Unset READ_FACE and relaunch sema to let this setting take effect.` : face === "open" ? localEngineLane() ? "read face back to default open \u2014 the whole filesystem is readable (key removed from settings.json); the open session shows an engine-restart banner \u2014 press ctrl+u there to apply" : "read face back to default open (key removed from settings.json) \u2014 takes effect the next time a local engine is spawned (this session is attached to an external engine or engine autostart is off)" : localEngineLane() ? "read face roots saved to settings.json \u2014 the engine reads only the workspace root plus declared read-only roots; the open session shows an engine-restart banner \u2014 press ctrl+u there to apply" : "read face roots saved to settings.json \u2014 takes effect the next time a local engine is spawned (this session is attached to an external engine or engine autostart is off)", nav.pop();
533933
+ effective.face === face && pendingRestartLaneAvailable() && notePendingEngineRestart("config"), saveNotice = effective.face !== face ? `read face ${face} saved to settings.json \u2014 but the READ_FACE environment variable (${effective.face}) overrides it, so the engine stays "${effective.face}". Unset READ_FACE and relaunch sema to let this setting take effect.` : face === "open" ? pendingRestartLaneAvailable() ? "read face back to default open \u2014 the whole filesystem is readable (key removed from settings.json); the open session shows an engine-restart banner \u2014 press ctrl+u there to apply" : "read face back to default open (key removed from settings.json) \u2014 takes effect the next time a local engine is spawned (this session is not managing a local engine \u2014 attached to an external one, autostart off, or run as a standalone config command)" : pendingRestartLaneAvailable() ? "read face roots saved to settings.json \u2014 the engine reads only the workspace root plus declared read-only roots; the open session shows an engine-restart banner \u2014 press ctrl+u there to apply" : "read face roots saved to settings.json \u2014 takes effect the next time a local engine is spawned (this session is not managing a local engine \u2014 attached to an external one, autostart off, or run as a standalone config command)", nav.pop();
532937
533934
  }
532938
533935
  }
532939
533936
  )
@@ -534054,11 +535051,11 @@ function wrapWorkflowDetailWithLiveActivity(base, opts) {
534054
535051
  ensureWorkflowActivityLedger(opts);
534055
535052
  let baseSubscribe = base.subscribe?.bind(base);
534056
535053
  function mergeSnapshot(snap) {
534057
- let ledger = readWorkflowActivityLedger(opts.workflowId);
534058
- if (!snap || !ledger || ledger.byCallKey.size === 0 && ledger.byLabel.size === 0) return snap;
535054
+ let ledger2 = readWorkflowActivityLedger(opts.workflowId);
535055
+ if (!snap || !ledger2 || ledger2.byCallKey.size === 0 && ledger2.byLabel.size === 0) return snap;
534059
535056
  let touched = !1, phases = snap.phases.map((ph) => {
534060
535057
  let agents3 = ph.agents.map((a) => {
534061
- let acc = a.callKey !== void 0 ? ledger.byCallKey.get(a.callKey) : a.label ? ledger.byLabel.get(a.label) : void 0;
535058
+ let acc = a.callKey !== void 0 ? ledger2.byCallKey.get(a.callKey) : a.label ? ledger2.byLabel.get(a.label) : void 0;
534062
535059
  if (!acc) return a;
534063
535060
  let patch2 = {};
534064
535061
  return a.toolCalls == null && acc.toolCalls > 0 && (patch2.toolCalls = acc.toolCalls), (a.activity == null || a.activity.length === 0) && acc.activity.length > 0 && (patch2.activity = acc.activity, acc.lastToolName !== void 0 && a.lastToolName == null && (patch2.lastToolName = acc.lastToolName, acc.lastToolSummary !== void 0 && (patch2.lastToolSummary = acc.lastToolSummary))), a.model == null && acc.requestedModel !== void 0 && (patch2.model = acc.requestedModel), a.fallbackModel == null && acc.resolvedModel !== void 0 && (patch2.fallbackModel = acc.resolvedModel), acc.lastProgressAt !== void 0 && (a.lastProgressAt == null || acc.lastProgressAt > a.lastProgressAt) && (patch2.lastProgressAt = acc.lastProgressAt), Object.keys(patch2).length === 0 ? a : (touched = !0, { ...a, ...patch2 });
@@ -536664,9 +537661,9 @@ var IDLE_EXIT_MS, DISPATCH_SCAN_MS, DAEMON_LOG_ROTATE_BYTES, ADOPTED_SWEEP_MS, C
536664
537661
  let seen2 = this.seenNonces.get(nonce);
536665
537662
  if (seen2) return seen2;
536666
537663
  }
536667
- let keys2 = [`short:${job.short}`, ...nonce ? [`nonce:${nonce}`] : []], inflight4 = keys2.map((k2) => this.inflightDispatches.get(k2)).find(Boolean);
536668
- if (inflight4) {
536669
- let outcome = await inflight4;
537664
+ let keys2 = [`short:${job.short}`, ...nonce ? [`nonce:${nonce}`] : []], inflight3 = keys2.map((k2) => this.inflightDispatches.get(k2)).find(Boolean);
537665
+ if (inflight3) {
537666
+ let outcome = await inflight3;
536670
537667
  return nonce && this.seenNonces.set(nonce, outcome), outcome;
536671
537668
  }
536672
537669
  let flight = (async () => {
@@ -537800,6 +538797,16 @@ async function launchReplProduction() {
537800
538797
  } catch {
537801
538798
  }
537802
538799
  })(), engineHealthLoop = startHealthCheckLoop2(instance2, (reason) => {
538800
+ if (reason === "configDriftResolved") {
538801
+ (async () => {
538802
+ try {
538803
+ let { retractHeartbeatConfigPending: retractHeartbeatConfigPending2 } = await Promise.resolve().then(() => (init_engineUpgradeCoordinator(), engineUpgradeCoordinator_exports));
538804
+ retractHeartbeatConfigPending2();
538805
+ } catch {
538806
+ }
538807
+ })();
538808
+ return;
538809
+ }
537803
538810
  if (reason !== "configDrift" && reason !== "versionDrift") {
537804
538811
  console.error(`[sema] local engine ${reason} \u2014 auto-restarting (limited retries), session preserved`), (async () => {
537805
538812
  try {
@@ -537814,7 +538821,10 @@ async function launchReplProduction() {
537814
538821
  (async () => {
537815
538822
  try {
537816
538823
  let { notePendingEngineRestart: notePendingEngineRestart2 } = await Promise.resolve().then(() => (init_engineUpgradeCoordinator(), engineUpgradeCoordinator_exports));
537817
- notePendingEngineRestart2(reason === "configDrift" ? "config" : "update");
538824
+ notePendingEngineRestart2(
538825
+ reason === "configDrift" ? "config" : "update",
538826
+ reason === "configDrift" ? "heartbeat-config" : "heartbeat-version"
538827
+ );
537818
538828
  } catch {
537819
538829
  }
537820
538830
  })();
@@ -537855,31 +538865,6 @@ async function launchReplProduction() {
537855
538865
  });
537856
538866
  } catch {
537857
538867
  }
537858
- try {
537859
- let { registerEngineConfigRespawn: registerEngineConfigRespawn2 } = await Promise.resolve().then(() => (init_engineEndpointSwap(), engineEndpointSwap_exports));
537860
- registerEngineConfigRespawn2(async () => {
537861
- engineHealthLoop?.stop();
537862
- let rr = await respawnOnConfigDrift2(currentEngineInstance);
537863
- if (!(rr.baseUrl && rr.instance))
537864
- return console.error(`[sema] /model endpoint respawn failed (${rr.reason ?? "unknown"}) \u2014 REPL stays up`), !1;
537865
- let { createLiveConversationClient: createLiveConversationClient2 } = await Promise.resolve().then(() => (init_liveClient(), liveClient_exports)), { setSeamClient: setSeamClient2 } = await Promise.resolve().then(() => (init_seamQuery(), seamQuery_exports)), { setQueryEngineClient: setQueryEngineClient2 } = await Promise.resolve().then(() => (init_seamQueryEngine(), seamQueryEngine_exports)), { resolveLiveAuthToken: resolveLiveAuthToken2 } = await Promise.resolve().then(() => (init_engineTarget(), engineTarget_exports)), swapClient = createLiveConversationClient2({
537866
- baseUrl: rr.baseUrl,
537867
- authToken: resolveLiveAuthToken2(rr.baseUrl),
537868
- // #118:同上,零 'anon' 占位符
537869
- principal: resolveLivePrincipal(),
537870
- afterEngineRespawn: !0
537871
- // 同上:换端点的温切也是换进程,caps 必须对新引擎重探
537872
- });
537873
- setSeamClient2(swapClient), setQueryEngineClient2(swapClient), installEngineHealthLoop(rr.instance);
537874
- try {
537875
- let { noteEngineReplacedExternally: noteEngineReplacedExternally2 } = await Promise.resolve().then(() => (init_engineUpgradeCoordinator(), engineUpgradeCoordinator_exports));
537876
- noteEngineReplacedExternally2();
537877
- } catch {
537878
- }
537879
- return console.error(`[sema] engine respawned onto the picked model's endpoint at ${rr.baseUrl} \u2014 session intact`), !0;
537880
- });
537881
- } catch {
537882
- }
537883
538868
  try {
537884
538869
  let { initEngineUpgradeCoordinator: initEngineUpgradeCoordinator2 } = await Promise.resolve().then(() => (init_engineUpgradeCoordinator(), engineUpgradeCoordinator_exports)), { resolveEngineEntry: resolveEngineEntry2, respawnOnConfigDrift: warmRespawn, getServiceAuthToken: tokenAfterRespawn } = await Promise.resolve().then(() => (init_engineLifecycleManager(), engineLifecycleManager_exports)), entry = resolveEngineEntry2(), entryFile = entry?.args[entry.args.length - 1];
537885
538870
  entryFile && initEngineUpgradeCoordinator2({